use of com.orientechnologies.orient.server.distributed.task.ORemoteTask in project orientdb by orientechnologies.
the class ODistributedResponseManager method fixNodesInConflict.
protected boolean fixNodesInConflict(final List<ODistributedResponse> bestResponsesGroup, final int conflicts, final boolean cannotFixRecordLockException) {
// NO FIFTY/FIFTY CASE: FIX THE CONFLICTED NODES BY OVERWRITING THE RECORD WITH THE WINNER'S RESULT
final ODistributedResponse goodResponse = bestResponsesGroup.get(0);
if (goodResponse.getPayload() instanceof Throwable)
return false;
ODistributedServerLog.debug(this, dManager.getLocalNodeName(), null, DIRECTION.NONE, "Detected %d conflicts, but the quorum (%d) has been reached. Checking responses and in case fixing remote records (reqId=%s)", conflicts, quorum, request.getId());
for (List<ODistributedResponse> responseGroup : responseGroups) {
if (responseGroup != bestResponsesGroup) {
// CONFLICT GROUP: FIX THEM ONE BY ONE
for (ODistributedResponse r : responseGroup) {
if (cannotFixRecordLockException && r.getPayload() instanceof ODistributedRecordLockedException) {
// NO FIX, THE RECORD WAS LOCKED
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.debug(this, dManager.getLocalNodeName(), null, DIRECTION.NONE, "Node '%s' responded with a record lock exception: cannot fix the operation, undo the entire operation (reqId=%s)", r.getExecutorNodeName(), request);
return false;
}
final ORemoteTask fixTask = ((OAbstractReplicatedTask) request.getTask()).getFixTask(request, request.getTask(), r.getPayload(), goodResponse.getPayload(), r.getExecutorNodeName(), dManager);
if (fixTask == null) {
// FIX NOT AVAILABLE: UNDO THE ENTIRE OPERATION
ODistributedServerLog.debug(this, dManager.getLocalNodeName(), null, DIRECTION.NONE, "No fix operation available: cannot fix the operation, undo the entire operation (reqId=%s)", request);
return false;
}
executeFix(r.getExecutorNodeName(), fixTask, r.getPayload(), goodResponse);
}
}
}
return true;
}
use of com.orientechnologies.orient.server.distributed.task.ORemoteTask in project orientdb by orientechnologies.
the class ODistributedDatabaseImpl method send2Nodes.
@Override
public ODistributedResponse send2Nodes(final ODistributedRequest iRequest, final Collection<String> iClusterNames, Collection<String> iNodes, final ODistributedRequest.EXECUTION_MODE iExecutionMode, final Object localResult, final OCallable<Void, ODistributedRequestId> iAfterSentCallback, final OCallable<Void, ODistributedResponseManager> endCallback) {
boolean afterSendCallBackCalled = false;
try {
checkForServerOnline(iRequest);
final String databaseName = iRequest.getDatabaseName();
if (iNodes.isEmpty()) {
ODistributedServerLog.error(this, localNodeName, null, DIRECTION.OUT, "No nodes configured for database '%s' request: %s", databaseName, iRequest);
throw new ODistributedException("No nodes configured for partition '" + databaseName + "' request: " + iRequest);
}
final ODistributedConfiguration cfg = manager.getDatabaseConfiguration(databaseName);
final ORemoteTask task = iRequest.getTask();
final boolean checkNodesAreOnline = task.isNodeOnlineRequired();
final Set<String> nodesConcurToTheQuorum = manager.getDistributedStrategy().getNodesConcurInQuorum(manager, cfg, iRequest, iNodes, databaseName, localResult);
// AFTER COMPUTED THE QUORUM, REMOVE THE OFFLINE NODES TO HAVE THE LIST OF REAL AVAILABLE NODES
final int availableNodes = checkNodesAreOnline ? manager.getNodesWithStatus(iNodes, databaseName, ODistributedServerManager.DB_STATUS.ONLINE, ODistributedServerManager.DB_STATUS.BACKUP, ODistributedServerManager.DB_STATUS.SYNCHRONIZING) : iNodes.size();
final int expectedResponses = localResult != null ? availableNodes + 1 : availableNodes;
final int quorum = calculateQuorum(task.getQuorumType(), iClusterNames, cfg, expectedResponses, nodesConcurToTheQuorum.size(), checkNodesAreOnline, localNodeName);
final boolean groupByResponse = task.getResultStrategy() != OAbstractRemoteTask.RESULT_STRATEGY.UNION;
final boolean waitLocalNode = waitForLocalNode(cfg, iClusterNames, iNodes);
// CREATE THE RESPONSE MANAGER
final ODistributedResponseManager currentResponseMgr = new ODistributedResponseManager(manager, iRequest, iNodes, nodesConcurToTheQuorum, expectedResponses, quorum, waitLocalNode, adjustTimeoutWithLatency(iNodes, task.getSynchronousTimeout(expectedResponses), iRequest.getId()), adjustTimeoutWithLatency(iNodes, task.getTotalTimeout(availableNodes), iRequest.getId()), groupByResponse, endCallback);
if (localResult != null && currentResponseMgr.setLocalResult(localNodeName, localResult)) {
// COLLECT LOCAL RESULT
return currentResponseMgr.getQuorumResponse();
}
// SORT THE NODE TO GUARANTEE THE SAME ORDER OF DELIVERY
if (!(iNodes instanceof List))
iNodes = new ArrayList<String>(iNodes);
if (iNodes.size() > 1)
Collections.sort((List<String>) iNodes);
msgService.registerRequest(iRequest.getId().getMessageId(), currentResponseMgr);
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.debug(this, localNodeName, iNodes.toString(), DIRECTION.OUT, "Sending request %s...", iRequest);
for (String node : iNodes) {
// CATCH ANY EXCEPTION LOG IT AND IGNORE TO CONTINUE SENDING REQUESTS TO OTHER NODES
try {
final ORemoteServerController remoteServer = manager.getRemoteServer(node);
remoteServer.sendRequest(iRequest);
} catch (Throwable e) {
currentResponseMgr.removeServerBecauseUnreachable(node);
String reason = e.getMessage();
if (e instanceof ODistributedException && e.getCause() instanceof IOException) {
// CONNECTION ERROR: REMOVE THE CONNECTION
reason = e.getCause().getMessage();
manager.closeRemoteServer(node);
} else if (e instanceof OSecurityAccessException) {
// THE CONNECTION COULD BE STALE, CREATE A NEW ONE AND RETRY
manager.closeRemoteServer(node);
try {
final ORemoteServerController remoteServer = manager.getRemoteServer(node);
remoteServer.sendRequest(iRequest);
continue;
} catch (Throwable ex) {
// IGNORE IT BECAUSE MANAGED BELOW
}
}
if (!manager.isNodeAvailable(node))
// NODE IS NOT AVAILABLE
ODistributedServerLog.debug(this, localNodeName, node, ODistributedServerLog.DIRECTION.OUT, "Error on sending distributed request %s. The target node is not available. Active nodes: %s", e, iRequest, manager.getAvailableNodeNames(databaseName));
else
ODistributedServerLog.error(this, localNodeName, node, ODistributedServerLog.DIRECTION.OUT, "Error on sending distributed request %s (err=%s). Active nodes: %s", iRequest, reason, manager.getAvailableNodeNames(databaseName));
}
}
if (currentResponseMgr.getExpectedNodes().isEmpty())
// NO SERVER TO SEND A MESSAGE
throw new ODistributedException("No server active for distributed request (" + iRequest + ") against database '" + databaseName + (iClusterNames != null ? "." + iClusterNames : "") + "' to nodes " + iNodes);
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.debug(this, localNodeName, iNodes.toString(), DIRECTION.OUT, "Sent request %s", iRequest);
totalSentRequests.incrementAndGet();
afterSendCallBackCalled = true;
if (iAfterSentCallback != null)
iAfterSentCallback.call(iRequest.getId());
if (iExecutionMode == ODistributedRequest.EXECUTION_MODE.RESPONSE)
return waitForResponse(iRequest, currentResponseMgr);
return null;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw OException.wrapException(new ODistributedException("Error on executing distributed request (" + iRequest + ") against database '" + databaseName + (iClusterNames != null ? "." + iClusterNames : "") + "' to nodes " + iNodes), e);
} finally {
if (iAfterSentCallback != null && !afterSendCallBackCalled)
iAfterSentCallback.call(iRequest.getId());
}
}
use of com.orientechnologies.orient.server.distributed.task.ORemoteTask in project orientdb by orientechnologies.
the class OAbstract2pcTask method getFixTask.
@Override
public ORemoteTask getFixTask(final ODistributedRequest iRequest, final ORemoteTask iOriginalTask, final Object iBadResponse, final Object iGoodResponse, final String executorNodeName, final ODistributedServerManager dManager) {
if (!(iGoodResponse instanceof OTxTaskResult)) {
// TODO: MANAGE ERROR ON LOCAL NODE
ODistributedServerLog.debug(this, getNodeSource(), null, DIRECTION.NONE, "Error on creating fix-task for request: '%s' because good response is not expected type: %s", iRequest, iBadResponse);
return null;
}
final OCompleted2pcTask fixTask = (OCompleted2pcTask) dManager.getTaskFactoryManager().getFactoryByServerName(executorNodeName).createTask(OCompleted2pcTask.FACTORYID);
fixTask.init(iRequest.getId(), false, getPartitionKey());
for (int i = 0; i < tasks.size(); ++i) {
final OAbstractRecordReplicatedTask t = tasks.get(i);
final Object badResult = iBadResponse == null ? null : iBadResponse instanceof Throwable ? iBadResponse : ((OTxTaskResult) iBadResponse).results.get(i);
final Object goodResult = ((OTxTaskResult) iGoodResponse).results.get(i);
final ORemoteTask undoTask = t.getFixTask(iRequest, t, badResult, goodResult, executorNodeName, dManager);
if (undoTask == null)
return null;
fixTask.addFixTask(undoTask);
}
return fixTask;
}
use of com.orientechnologies.orient.server.distributed.task.ORemoteTask in project orientdb by orientechnologies.
the class OAbstract2pcTask method fromStream.
@Override
public void fromStream(final DataInput in, final ORemoteTaskFactory factory) throws IOException {
final int size = in.readInt();
for (int i = 0; i < size; ++i) {
final ORemoteTask task = factory.createTask(in.readByte());
task.fromStream(in, factory);
tasks.add((OAbstractRecordReplicatedTask) task);
}
final boolean hasLastLSN = in.readBoolean();
if (hasLastLSN)
lastLSN = new OLogSequenceNumber(in);
}
use of com.orientechnologies.orient.server.distributed.task.ORemoteTask in project orientdb by orientechnologies.
the class OCompleted2pcTask method toStream.
@Override
public void toStream(final DataOutput out) throws IOException {
requestId.toStream(out);
out.writeBoolean(success);
out.writeInt(fixTasks.size());
for (ORemoteTask task : fixTasks) {
out.writeByte(task.getFactoryId());
task.toStream(out);
}
}
Aggregations