/*
* 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.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.net.DBWNetworkHandler;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.ui.UIUtils;
import java.util.ArrayList;
import java.util.List;
/**
* InvalidateJob
*/
public class InvalidateJob extends DataSourceJob
{
private static final Log log = Log.getLog(InvalidateJob.class);
public static class ContextInvalidateResult {
public final DBCExecutionContext.InvalidateResult result;
public final Exception error;
public ContextInvalidateResult(DBCExecutionContext.InvalidateResult result, Exception error) {
this.result = result;
this.error = error;
}
@Override
public String toString() {
return result.name();
}
}
private long timeSpent;
private List<ContextInvalidateResult> invalidateResults = new ArrayList<>();
//private boolean reconnect;
public InvalidateJob(
DBCExecutionContext context/*,
boolean reconnect*/)
{
super("Invalidate " + context.getDataSource().getContainer().getName(), null, context);
// this.reconnect = reconnect;
}
public List<ContextInvalidateResult> getInvalidateResults() {
return invalidateResults;
}
public long getTimeSpent() {
return timeSpent;
}
@Override
protected IStatus run(DBRProgressMonitor monitor)
{
DBPDataSource dataSource = getExecutionContext().getDataSource();
this.invalidateResults = invalidateDataSource(monitor, dataSource, true);
return Status.OK_STATUS;
}
public static List<ContextInvalidateResult> invalidateDataSource(DBRProgressMonitor monitor, DBPDataSource dataSource, boolean disconnectOnFailure) {
long timeSpent = 0;
List<ContextInvalidateResult> invalidateResults = new ArrayList<>();
DBPDataSourceContainer container = dataSource.getContainer();
DBWNetworkHandler[] activeHandlers = container.getActiveNetworkHandlers();
boolean networkOK = true;
boolean hasGoodContexts = false;
if (activeHandlers != null && activeHandlers.length > 0) {
for (DBWNetworkHandler nh : activeHandlers) {
monitor.subTask("Invalidate network [" + container.getName() + "]");
try {
nh.invalidateHandler(monitor);
} catch (Exception e) {
invalidateResults.add(new ContextInvalidateResult(DBCExecutionContext.InvalidateResult.ERROR, e));
networkOK = false;
break;
}
}
}
if (networkOK) {
// Invalidate datasource
monitor.subTask("Invalidate connections of [" + container.getName() + "]");
DBCExecutionContext[] allContexts = dataSource.getAllContexts();
for (DBCExecutionContext context : allContexts) {
long startTime = System.currentTimeMillis();
try {
final DBCExecutionContext.InvalidateResult result = context.invalidateContext(monitor, disconnectOnFailure);
if (result != DBCExecutionContext.InvalidateResult.ERROR) {
hasGoodContexts = true;
}
invalidateResults.add(new ContextInvalidateResult(result, null));
} catch (Exception e) {
invalidateResults.add(new ContextInvalidateResult(DBCExecutionContext.InvalidateResult.ERROR, e));
} finally {
timeSpent += (System.currentTimeMillis() - startTime);
}
}
}
if (!hasGoodContexts && disconnectOnFailure) {
// Close whole datasource. Target host seems to be unavailable
try {
container.disconnect(monitor);
} catch (Exception e) {
log.error("Error closing unaccessible datasource", e);
}
StringBuilder msg = new StringBuilder();
for (ContextInvalidateResult result : invalidateResults) {
if (result.error != null) {
if (msg.length() > 0) msg.append("\n");
msg.append(result.error.getMessage());
}
}
UIUtils.showErrorDialog(null, "Forced disconnect", "Datasource '" + container.getName() + "' was disconnected: destination database unreachable.\n" + msg);
}
return invalidateResults;
}
@Override
protected void canceling()
{
getThread().interrupt();
}
}