use of com.orientechnologies.common.concur.OOfflineNodeException in project orientdb by orientechnologies.
the class OStorageRemote method reopenRemoteDatabase.
protected String reopenRemoteDatabase() throws IOException {
String currentURL = getCurrentServerURL();
do {
do {
final OChannelBinaryAsynchClient network = getNetwork(currentURL);
try {
OStorageRemoteSession session = getCurrentSession();
OStorageRemoteNodeSession nodeSession = session.getOrCreateServerSession(network.getServerURL());
if (nodeSession == null || !nodeSession.isValid()) {
openRemoteDatabase(network);
connectionManager.release(network);
return network.getServerURL();
} else {
try {
network.writeByte(OChannelBinaryProtocol.REQUEST_DB_REOPEN);
network.writeInt(nodeSession.getSessionId());
network.writeBytes(nodeSession.getToken());
} finally {
endRequest(network);
}
final int sessionId;
try {
byte[] newToken = network.beginResponse(nodeSession.getSessionId(), true);
sessionId = network.readInt();
if (newToken != null && newToken.length > 0) {
nodeSession.setSession(sessionId, newToken);
} else {
nodeSession.setSession(sessionId, nodeSession.getToken());
}
OLogManager.instance().debug(this, "Client connected to %s with session id=%d", network.getServerURL(), sessionId);
return currentURL;
} finally {
endResponse(network);
connectionManager.release(network);
}
}
} catch (OIOException e) {
if (network != null) {
// REMOVE THE NETWORK CONNECTION IF ANY
connectionManager.remove(network);
}
OLogManager.instance().error(this, "Cannot open database with url " + currentURL, e);
} catch (OOfflineNodeException e) {
if (network != null) {
// REMOVE THE NETWORK CONNECTION IF ANY
connectionManager.remove(network);
}
OLogManager.instance().debug(this, "Cannot open database with url " + currentURL, e);
} catch (OSecurityException ex) {
OLogManager.instance().debug(this, "Invalidate token for url=%s", ex, currentURL);
OStorageRemoteSession session = getCurrentSession();
session.removeServerSession(currentURL);
if (network != null) {
// REMOVE THE NETWORK CONNECTION IF ANY
try {
connectionManager.remove(network);
} catch (Exception e) {
// IGNORE ANY EXCEPTION
OLogManager.instance().debug(this, "Cannot remove connection or database url=" + currentURL, e);
}
}
} catch (OException e) {
connectionManager.release(network);
// PROPAGATE ANY OTHER ORIENTDB EXCEPTION
throw e;
} catch (Exception e) {
OLogManager.instance().debug(this, "Cannot open database with url " + currentURL, e);
if (network != null) {
// REMOVE THE NETWORK CONNECTION IF ANY
try {
connectionManager.remove(network);
} catch (Exception ex) {
// IGNORE ANY EXCEPTION
OLogManager.instance().debug(this, "Cannot remove connection or database url=" + currentURL, e);
}
}
}
} while (connectionManager.getAvailableConnections(currentURL) > 0);
currentURL = useNewServerURL(currentURL);
} while (currentURL != null);
// REFILL ORIGINAL SERVER LIST
parseServerURLs();
synchronized (serverURLs) {
throw new OStorageException("Cannot create a connection to remote server address(es): " + serverURLs);
}
}
use of com.orientechnologies.common.concur.OOfflineNodeException in project orientdb by orientechnologies.
the class ODistributedStorage method updateRecord.
@Override
public OStorageOperationResult<Integer> updateRecord(final ORecordId iRecordId, final boolean updateContent, final byte[] iContent, final int iVersion, final byte iRecordType, final int iMode, final ORecordCallback<Integer> iCallback) {
resetLastValidBackup();
if (OScenarioThreadLocal.INSTANCE.isRunModeDistributed()) {
// ALREADY DISTRIBUTED
return wrapped.updateRecord(iRecordId, updateContent, iContent, iVersion, iRecordType, iMode, iCallback);
}
final ODistributedConfiguration dbCfg = distributedConfiguration;
final String clusterName = getClusterNameByRID(iRecordId);
final String localNodeName = dManager.getLocalNodeName();
checkWriteQuorum(dbCfg, clusterName, localNodeName);
try {
checkNodeIsMaster(localNodeName, dbCfg, "Update record " + iRecordId);
final List<String> nodes = dbCfg.getServers(clusterName, null);
if (nodes.isEmpty())
// NO REPLICATION: EXECUTE IT LOCALLY
return wrapped.updateRecord(iRecordId, updateContent, iContent, iVersion, iRecordType, iMode, iCallback);
final Set<String> clusterNames = Collections.singleton(clusterName);
Boolean executionModeSynch = dbCfg.isExecutionModeSynchronous(clusterName);
if (executionModeSynch == null)
executionModeSynch = iMode == 0;
final boolean syncMode = executionModeSynch;
return (OStorageOperationResult<Integer>) executeRecordOperationInLock(syncMode, iRecordId, new OCallable<Object, OCallable<Void, ODistributedRequestId>>() {
@Override
public Object call(OCallable<Void, ODistributedRequestId> unlockCallback) {
final OUpdateRecordTask task = (OUpdateRecordTask) dManager.getTaskFactoryManager().getFactoryByServerNames(nodes).createTask(OUpdateRecordTask.FACTORYID);
task.init(iRecordId, iContent, iVersion, iRecordType);
final OStorageOperationResult<Integer> localResult;
final boolean executedLocally = nodes.contains(localNodeName);
if (executedLocally) {
// EXECUTE ON LOCAL NODE FIRST
try {
// LOAD CURRENT RECORD
task.checkRecordExists();
localResult = (OStorageOperationResult<Integer>) OScenarioThreadLocal.executeAsDistributed(new Callable() {
@Override
public Object call() throws Exception {
task.setLastLSN(wrapped.getLSN());
return wrapped.updateRecord(iRecordId, updateContent, iContent, iVersion, iRecordType, iMode, iCallback);
}
});
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw OException.wrapException(new ODistributedException("Cannot delete record " + iRecordId), e);
}
nodes.remove(localNodeName);
} else
localResult = null;
if (nodes.isEmpty()) {
unlockCallback.call(null);
if (!executedLocally)
throw new ODistributedException("Cannot execute distributed update on record " + iRecordId + " because no nodes are available");
} else {
final Integer localResultPayload = localResult != null ? localResult.getResult() : null;
if (syncMode || localResult == null) {
// REPLICATE IT
try {
final ODistributedResponse dResponse = dManager.sendRequest(getName(), clusterNames, nodes, task, dManager.getNextMessageIdCounter(), EXECUTION_MODE.RESPONSE, localResultPayload, unlockCallback, null);
final Object payload = dResponse.getPayload();
if (payload instanceof Exception) {
if (payload instanceof ORecordNotFoundException) {
// REPAIR THE RECORD IMMEDIATELY
localDistributedDatabase.getDatabaseRepairer().enqueueRepairRecord((ORecordId) ((ORecordNotFoundException) payload).getRid());
}
executeUndoOnLocalServer(dResponse.getRequestId(), task);
if (payload instanceof ONeedRetryException)
throw (ONeedRetryException) payload;
throw OException.wrapException(new ODistributedException("Error on execution distributed update record"), (Exception) payload);
}
// UPDATE LOCALLY
return new OStorageOperationResult<Integer>((Integer) payload);
} catch (RuntimeException e) {
executeUndoOnLocalServer(null, task);
throw e;
} catch (Exception e) {
executeUndoOnLocalServer(null, task);
throw ODatabaseException.wrapException(new ODistributedException("Cannot execute distributed update record"), e);
}
}
// ASYNCHRONOUS CALL: EXECUTE LOCALLY AND THEN DISTRIBUTE
asynchronousExecution(new OAsynchDistributedOperation(getName(), Collections.singleton(clusterName), nodes, task, dManager.getNextMessageIdCounter(), localResultPayload, unlockCallback, null));
}
return localResult;
}
});
} catch (ONeedRetryException e) {
localDistributedDatabase.getDatabaseRepairer().enqueueRepairRecord(iRecordId);
// PASS THROUGH
throw e;
} catch (HazelcastInstanceNotActiveException e) {
throw new OOfflineNodeException("Hazelcast instance is not available");
} catch (HazelcastException e) {
throw new OOfflineNodeException("Hazelcast instance is not available");
} catch (Exception e) {
localDistributedDatabase.getDatabaseRepairer().enqueueRepairRecord(iRecordId);
handleDistributedException("Cannot route UPDATE_RECORD operation for %s to the distributed node", e, iRecordId);
// UNREACHABLE
return null;
}
}
use of com.orientechnologies.common.concur.OOfflineNodeException in project orientdb by orientechnologies.
the class ODistributedStorage method readRecord.
public OStorageOperationResult<ORawBuffer> readRecord(final ORecordId iRecordId, final String iFetchPlan, final boolean iIgnoreCache, final boolean prefetchRecords, final ORecordCallback<ORawBuffer> iCallback) {
final ORawBuffer memCopy = localDistributedDatabase.getRecordIfLocked(iRecordId);
if (memCopy != null)
return new OStorageOperationResult<ORawBuffer>(memCopy);
try {
final String clusterName = getClusterNameByRID(iRecordId);
final ODistributedConfiguration dbCfg = distributedConfiguration;
final List<String> nodes = dbCfg.getServers(clusterName, null);
final int availableNodes = nodes.size();
// CHECK IF LOCAL NODE OWNS THE DATA AND READ-QUORUM = 1: GET IT LOCALLY BECAUSE IT'S FASTER
final String localNodeName = dManager.getLocalNodeName();
if (nodes.isEmpty() || nodes.contains(dManager.getLocalNodeName()) && dbCfg.getReadQuorum(clusterName, availableNodes, localNodeName) <= 1) {
// DON'T REPLICATE
return (OStorageOperationResult<ORawBuffer>) OScenarioThreadLocal.executeAsDistributed(new Callable() {
@Override
public Object call() throws Exception {
return wrapped.readRecord(iRecordId, iFetchPlan, iIgnoreCache, prefetchRecords, iCallback);
}
});
}
final OReadRecordTask task = ((OReadRecordTask) dManager.getTaskFactoryManager().getFactoryByServerNames(nodes).createTask(OReadRecordTask.FACTORYID)).init(iRecordId);
// DISTRIBUTE IT
final ODistributedResponse response = dManager.sendRequest(getName(), Collections.singleton(clusterName), nodes, task, dManager.getNextMessageIdCounter(), EXECUTION_MODE.RESPONSE, null, null, null);
final Object dResult = response != null ? response.getPayload() : null;
if (dResult instanceof ONeedRetryException)
throw (ONeedRetryException) dResult;
else if (dResult instanceof Exception)
throw OException.wrapException(new ODistributedException("Error on execution distributed read record"), (Exception) dResult);
return new OStorageOperationResult<ORawBuffer>((ORawBuffer) dResult);
} catch (ONeedRetryException e) {
// PASS THROUGH
throw e;
} catch (HazelcastInstanceNotActiveException e) {
throw new OOfflineNodeException("Hazelcast instance is not available");
} catch (HazelcastException e) {
throw new OOfflineNodeException("Hazelcast instance is not available");
} catch (Exception e) {
handleDistributedException("Cannot route read record operation for %s to the distributed node", e, iRecordId);
// UNREACHABLE
return null;
}
}
use of com.orientechnologies.common.concur.OOfflineNodeException in project orientdb by orientechnologies.
the class OStorageRemote method baseNetworkOperation.
public <T> T baseNetworkOperation(final OStorageRemoteOperation<T> operation, final String errorMessage, int retry) {
OStorageRemoteSession session = getCurrentSession();
if (session.commandExecuting)
throw new ODatabaseException("Cannot execute the request because an asynchronous operation is in progress. Please use a different connection");
String serverUrl = null;
do {
OChannelBinaryAsynchClient network = null;
if (serverUrl == null)
serverUrl = getNextAvailableServerURL(false, session);
do {
try {
network = getNetwork(serverUrl);
} catch (OException e) {
serverUrl = useNewServerURL(serverUrl);
if (serverUrl == null)
throw e;
}
} while (network == null);
try {
// In case i do not have a token or i'm switching between server i've to execute a open operation.
OStorageRemoteNodeSession nodeSession = session.getServerSession(network.getServerURL());
if (nodeSession == null || !nodeSession.isValid()) {
openRemoteDatabase(network);
if (!network.tryLock()) {
connectionManager.release(network);
continue;
}
}
return operation.execute(network, session);
} catch (ODistributedRedirectException e) {
connectionManager.release(network);
OLogManager.instance().debug(this, "Redirecting the request from server '%s' to the server '%s' because %s", e.getFromServer(), e.toString(), e.getMessage());
// RECONNECT TO THE SERVER SUGGESTED IN THE EXCEPTION
serverUrl = e.getToServerAddress();
} catch (OModificationOperationProhibitedException mope) {
connectionManager.release(network);
handleDBFreeze();
serverUrl = null;
} catch (OTokenException e) {
connectionManager.release(network);
session.removeServerSession(network.getServerURL());
if (--retry <= 0)
throw OException.wrapException(new OStorageException(errorMessage), e);
serverUrl = null;
} catch (OTokenSecurityException e) {
connectionManager.release(network);
session.removeServerSession(network.getServerURL());
if (--retry <= 0)
throw OException.wrapException(new OStorageException(errorMessage), e);
serverUrl = null;
} catch (OOfflineNodeException e) {
connectionManager.release(network);
// Remove the current url because the node is offline
synchronized (serverURLs) {
serverURLs.remove(serverUrl);
}
for (OStorageRemoteSession activeSession : sessions) {
// Not thread Safe ...
activeSession.removeServerSession(serverUrl);
}
serverUrl = null;
} catch (IOException e) {
connectionManager.release(network);
retry = handleIOException(retry, network, e);
serverUrl = null;
} catch (OIOException e) {
connectionManager.release(network);
retry = handleIOException(retry, network, e);
serverUrl = null;
} catch (OException e) {
connectionManager.release(network);
throw e;
} catch (Exception e) {
connectionManager.release(network);
throw OException.wrapException(new OStorageException(errorMessage), e);
}
} while (true);
}
use of com.orientechnologies.common.concur.OOfflineNodeException in project orientdb by orientechnologies.
the class ODistributedAbstractPlugin method onOpen.
/**
* Auto register myself as hook.
*/
@Override
public void onOpen(final ODatabaseInternal iDatabase) {
if (!isRelatedToLocalServer(iDatabase))
return;
if (status != NODE_STATUS.ONLINE && status != NODE_STATUS.STARTING)
return;
final ODatabaseDocumentInternal currDb = ODatabaseRecordThreadLocal.INSTANCE.getIfDefined();
try {
final String dbName = iDatabase.getName();
final ODistributedConfiguration cfg = getDatabaseConfiguration(dbName);
if (cfg == null)
return;
ODistributedDatabaseImpl distribDatabase = getMessageService().getDatabase(dbName);
if (distribDatabase == null) {
// CHECK TO PUBLISH IT TO THE CLUSTER
distribDatabase = messageService.registerDatabase(dbName, cfg);
distribDatabase.checkNodeInConfiguration(cfg, getLocalNodeName());
distribDatabase.resume();
distribDatabase.setOnline();
}
if (!(iDatabase.getStorage() instanceof ODistributedStorage) || ((ODistributedStorage) iDatabase.getStorage()).getDistributedManager().isOffline()) {
final ODistributedStorage storage = getStorage(dbName);
// INIT IT
storage.wrap((OAbstractPaginatedStorage) iDatabase.getStorage().getUnderlying());
iDatabase.replaceStorage(storage);
if (isNodeOnline(nodeName, dbName))
installDbClustersLocalStrategy(iDatabase);
}
} catch (HazelcastException e) {
throw new OOfflineNodeException("Hazelcast instance is not available");
} catch (HazelcastInstanceNotActiveException e) {
throw new OOfflineNodeException("Hazelcast instance is not available");
} finally {
// RESTORE ORIGINAL DATABASE INSTANCE IN TL
ODatabaseRecordThreadLocal.INSTANCE.set(currDb);
}
}
Aggregations