/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.runtime.jobs;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.DataSourceRegistry;
import org.jkiss.dbeaver.registry.ProjectRegistry;
import java.util.*;
/**
* KeepAliveJob
*/
public class KeepAliveJob extends AbstractJob
{
public static final int MONITOR_INTERVAL = 3000; // once per 3 seconds
private static final Log log = Log.getLog(KeepAliveJob.class);
private Map<String, Long> checkCache = new HashMap<>();
private final Set<String> pingCache = new HashSet<>();
public KeepAliveJob()
{
super("Keep-Alive monitor");
setUser(false);
setSystem(true);
}
@Override
protected IStatus run(DBRProgressMonitor monitor)
{
if (DBeaverCore.isClosing()) {
return Status.OK_STATUS;
}
final DBeaverCore core = DBeaverCore.getInstance();
final ProjectRegistry projectRegistry = core.getProjectRegistry();
if (projectRegistry == null) {
return Status.OK_STATUS;
}
for (DataSourceDescriptor ds : DataSourceRegistry.getAllDataSources()) {
checkDataSourceAlive(monitor, ds);
}
if (!DBeaverCore.isClosing()) {
scheduleMonitor();
}
return Status.OK_STATUS;
}
private void checkDataSourceAlive(DBRProgressMonitor monitor, final DataSourceDescriptor dataSourceDescriptor) {
if (!dataSourceDescriptor.isConnected()) {
return;
}
final int keepAliveInterval = dataSourceDescriptor.getConnectionConfiguration().getKeepAliveInterval();
if (keepAliveInterval <= 0) {
return;
}
final String dsId = dataSourceDescriptor.getId();
synchronized (this) {
if (pingCache.contains(dsId)) {
// Ping is still in progress. Hanged?
// Anyway - just skip it
return;
}
}
final DBPDataSource dataSource = dataSourceDescriptor.getDataSource();
if (dataSource == null) {
return;
}
Long lastCheckTime;
synchronized (this) {
lastCheckTime = checkCache.get(dsId);
}
if (lastCheckTime == null) {
final Date connectTime = dataSourceDescriptor.getConnectTime();
if (connectTime != null) {
lastCheckTime = connectTime.getTime();
}
}
if (lastCheckTime == null) {
log.debug("Can't determine last check time for " + dsId);
return;
}
long curTime = System.currentTimeMillis();
if ((curTime - lastCheckTime) / 1000 > keepAliveInterval) {
final PingJob pingJob = new PingJob(dataSource);
pingJob.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
synchronized (KeepAliveJob.this) {
checkCache.put(dsId, System.currentTimeMillis());
pingCache.remove(dsId);
}
}
});
synchronized (this) {
pingCache.add(dsId);
}
pingJob.schedule();
}
}
public void scheduleMonitor() {
schedule(MONITOR_INTERVAL);
}
}