use of com.orientechnologies.orient.server.distributed.task.ODistributedRecordLockedException in project orientdb by orientechnologies.
the class ODistributedResponseManager method manageConflicts.
protected RuntimeException manageConflicts() {
if (!groupResponsesByResult || request.getTask().getQuorumType() == OCommandDistributedReplicateRequest.QUORUM_TYPE.NONE)
// NO QUORUM
return null;
if (dManager.getNodeStatus() != ODistributedServerManager.NODE_STATUS.ONLINE)
// CURRENT NODE OFFLINE: JUST RETURN
return null;
final int bestResponsesGroupIndex = getBestResponsesGroup();
final List<ODistributedResponse> bestResponsesGroup = responseGroups.get(bestResponsesGroupIndex);
final int maxCoherentResponses = bestResponsesGroup.size();
final int conflicts = getExpectedResponses() - (maxCoherentResponses);
if (isMinimumQuorumReached(true)) {
// QUORUM SATISFIED
if (responseGroups.size() == 1)
// NO CONFLICT
return null;
if (checkNoWinnerCase(bestResponsesGroup))
// TODO: CALL THE RECORD CONFLICT PIPELINE
return null;
if (fixNodesInConflict(bestResponsesGroup, conflicts))
// FIX SUCCEED
return null;
}
// QUORUM HASN'T BEEN REACHED
if (ODistributedServerLog.isDebugEnabled()) {
ODistributedServerLog.debug(this, dManager.getLocalNodeName(), null, DIRECTION.NONE, "Detected %d node(s) in timeout or in conflict and quorum (%d) has not been reached, rolling back changes for request (%s)", conflicts, quorum, request);
ODistributedServerLog.debug(this, dManager.getLocalNodeName(), null, DIRECTION.NONE, composeConflictMessage());
}
if (!undoRequest()) {
// SKIP UNDO
return null;
}
// CHECK IF THERE IS AT LEAST ONE ODistributedRecordLockedException or OConcurrentCreateException
for (Object r : responses.values()) {
if (r instanceof ODistributedRecordLockedException)
throw (ODistributedRecordLockedException) r;
else if (r instanceof OConcurrentCreateException)
throw (OConcurrentCreateException) r;
}
final Object goodResponsePayload = bestResponsesGroup.isEmpty() ? null : bestResponsesGroup.get(0).getPayload();
if (goodResponsePayload instanceof RuntimeException)
// RESPONSE IS ALREADY AN EXCEPTION: THROW THIS
return (RuntimeException) goodResponsePayload;
else if (goodResponsePayload instanceof Throwable)
return OException.wrapException(new ODistributedException(composeConflictMessage()), (Throwable) goodResponsePayload);
else {
if (responseGroups.size() <= 2) {
// CHECK IF THE BAD RESPONSE IS AN EXCEPTION, THEN PROPAGATE IT
for (int i = 0; i < responseGroups.size(); ++i) {
if (i == bestResponsesGroupIndex)
continue;
final List<ODistributedResponse> badResponses = responseGroups.get(i);
if (badResponses.get(0).getPayload() instanceof RuntimeException)
return (RuntimeException) badResponses.get(0).getPayload();
}
}
return new ODistributedOperationException(composeConflictMessage());
}
}
use of com.orientechnologies.orient.server.distributed.task.ODistributedRecordLockedException in project orientdb by orientechnologies.
the class ODistributedResponseManager method fixNodesInConflict.
protected boolean fixNodesInConflict(final List<ODistributedResponse> bestResponsesGroup, final int conflicts) {
// 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. Fixing remote records. Request (%s)", conflicts, quorum, request);
for (List<ODistributedResponse> responseGroup : responseGroups) {
if (responseGroup != bestResponsesGroup) {
// CONFLICT GROUP: FIX THEM ONE BY ONE
for (ODistributedResponse r : responseGroup) {
if (r.getPayload() instanceof ODistributedRecordLockedException)
// NO FIX, THE RECORD WAS LOCKED
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
return false;
ODistributedServerLog.debug(this, dManager.getLocalNodeName(), r.getExecutorNodeName(), DIRECTION.OUT, "Sending fix message (%s) for response (%s) on request (%s) to be: %s", fixTask, r, request, goodResponse);
dManager.sendRequest(request.getDatabaseName(), null, OMultiValue.getSingletonList(r.getExecutorNodeName()), fixTask, dManager.getNextMessageIdCounter(), ODistributedRequest.EXECUTION_MODE.NO_RESPONSE, null, null);
}
}
}
return true;
}
use of com.orientechnologies.orient.server.distributed.task.ODistributedRecordLockedException in project orientdb by orientechnologies.
the class ODistributedDatabaseImpl method lockRecord.
@Override
public boolean lockRecord(final ORID rid, final ODistributedRequestId iRequestId, final long timeout) {
// TODO: IMPROVE THIS BY RECEIVING THE RECORD AS PARAMETER INSTEAD OF RELOADING IT
ORawBuffer originalRecord = null;
if (rid.isPersistent()) {
final ODatabaseDocumentInternal db = ODatabaseRecordThreadLocal.INSTANCE.getIfDefined();
if (db != null)
originalRecord = db.getStorage().getUnderlying().readRecord((ORecordId) rid, null, false, true, null).getResult();
}
final ODistributedLock lock = new ODistributedLock(iRequestId, originalRecord);
boolean newLock = true;
ODistributedLock currentLock = lockManager.putIfAbsent(rid, lock);
if (currentLock != null) {
if (iRequestId.equals(currentLock.reqId)) {
// SAME ID, ALREADY LOCKED
ODistributedServerLog.debug(this, localNodeName, null, DIRECTION.NONE, "Distributed transaction: %s locked record %s in database '%s' owned by %s (thread=%d)", iRequestId, rid, databaseName, currentLock.reqId, Thread.currentThread().getId());
currentLock = null;
newLock = false;
} else {
// TRY TO RE-LOCK IT UNTIL TIMEOUT IS EXPIRED
final long startTime = System.currentTimeMillis();
do {
try {
if (timeout > 0) {
if (!currentLock.lock.await(timeout, TimeUnit.MILLISECONDS))
continue;
} else
currentLock.lock.await();
currentLock = lockManager.putIfAbsent(rid, lock);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
} while (currentLock != null && (timeout == 0 || System.currentTimeMillis() - startTime < timeout));
}
}
//
if (ODistributedServerLog.isDebugEnabled())
if (currentLock == null) {
ODistributedServerLog.debug(this, localNodeName, null, DIRECTION.NONE, "Distributed transaction: %s locked record %s in database '%s' (thread=%d)", iRequestId, rid, databaseName, Thread.currentThread().getId());
} else {
ODistributedServerLog.debug(this, localNodeName, null, DIRECTION.NONE, "Distributed transaction: %s cannot lock record %s in database '%s' owned by %s (thread=%d)", iRequestId, rid, databaseName, currentLock.reqId, Thread.currentThread().getId());
}
if (currentLock != null)
throw new ODistributedRecordLockedException(manager.getLocalNodeName(), rid, currentLock.reqId, timeout);
return newLock;
}
use of com.orientechnologies.orient.server.distributed.task.ODistributedRecordLockedException in project orientdb by orientechnologies.
the class HALocalGraphTest method startThread.
private Runnable startThread(final int id, final OrientGraphFactory graphFactory) {
Runnable th = new Runnable() {
@Override
public void run() {
// OrientBaseGraph graph = new OrientGraph(getDBURL());
// OrientGraph graph = graphFactory.getTx();
boolean useSQL = false;
StringBuilder sb = new StringBuilder(".");
for (int m = 0; m < id; m++) {
sb.append(".");
}
long st = System.currentTimeMillis();
try {
String query = "select from Test where prop2='v2-1'";
boolean isRunning = true;
for (int i = 1; i < TOTAL_CYCLES_PER_THREAD && isRunning; i++) {
if ((i % 2500) == 0) {
long et = System.currentTimeMillis();
log(sb.toString() + " [" + id + "] Total Records Processed: [" + i + "] Current: [2500] Time taken: [" + (et - st) / 1000 + "] seconds");
st = System.currentTimeMillis();
}
if (sleep > 0)
Thread.sleep(sleep);
OrientGraph graph = graphFactory.getTx();
if (!graph.getRawGraph().getURL().startsWith("remote:"))
Assert.assertTrue(graph.getVertexType("Test").getClusterSelection() instanceof OLocalClusterWrapperStrategy);
try {
if (useSQL) {
boolean update = true;
boolean isException = false;
String sql = "Update Test set prop5='" + String.valueOf(System.currentTimeMillis()) + "', updateTime='" + new Date().toString() + "' where prop2='v2-1'";
for (int k = 0; k < 10 && update; k++) {
try {
graph.command(new OCommandSQL(sql)).execute();
if (isException) {
log("********** [" + id + "][" + k + "] Update success after distributed lock Exception");
}
update = false;
break;
} catch (ONeedRetryException ex) {
if (ex instanceof OConcurrentModificationException || ex.getCause() instanceof OConcurrentModificationException) {
} else {
isException = true;
log("*$$$$$$$$$$$$$$ [" + id + "][" + k + "] Distributed Exception: [" + ex + "] Cause: [" + (ex.getCause() != null ? ex.getCause() : "--") + "] ");
}
} catch (ODistributedException ex) {
if (ex.getCause() instanceof OConcurrentModificationException) {
} else {
isException = true;
log("*$$$$$$$$$$$$$$ [" + id + "][" + k + "] Distributed Exception: [" + ex + "] Cause: [" + (ex.getCause() != null ? ex.getCause() : "--") + "] ");
}
} catch (Exception ex) {
log("[" + id + "][" + k + "] Exception " + ex);
}
}
} else {
boolean retry = true;
Iterable<Vertex> vtxs = null;
for (int k = 0; k < 100 && retry; k++) try {
vtxs = graph.command(new OCommandSQL(query)).execute();
break;
} catch (ONeedRetryException e) {
// RETRY
}
for (Vertex vtx : vtxs) {
if (retry) {
retry = true;
boolean isException = false;
for (int k = 0; k < 100 && retry; k++) {
OrientVertex vtx1 = (OrientVertex) vtx;
try {
vtx1.setProperty("prop5", "prop55");
vtx1.setProperty("updateTime", new Date().toString());
vtx1.setProperty("blob", new byte[1000]);
graph.commit();
if (isException) {
// log("********** [" + id + "][" + k + "] Update success after distributed lock Exception for vertex " +
// vtx1);
}
retry = false;
break;
} catch (OConcurrentModificationException ex) {
vtx1.reload();
} catch (ONeedRetryException ex) {
if (ex instanceof ODistributedRecordLockedException) {
if (k > 20)
log("*$$$$$$$$$$$$$$ [" + id + "][" + k + "] ODistributedRecordLockedException: [" + ex + "] Cause: [" + (ex.getCause() != null ? ex.getCause() : "--") + "] for vertex " + vtx1);
vtx1.reload();
} else if (ex instanceof ONeedRetryException || ex.getCause() instanceof ONeedRetryException) {
vtx1.reload();
} else {
if (ex.getCause() instanceof ConcurrentModificationException) {
ex.printStackTrace();
}
log("*$$$$$$$$$$$$$$ [" + id + "][" + k + "] Distributed Exception: [" + ex + "] Cause: [" + (ex.getCause() != null ? ex.getCause() : "--") + "] for vertex " + vtx1);
}
// log("*** [" + id + "][" + k + "] Distributed Exception: [" + ex + "] Cause: [" + (ex.getCause() != null ?
// ex.getCause() : "--") + "] for vertex " + vtx1);
isException = true;
} catch (ODistributedException ex) {
if (ex.getCause() instanceof ONeedRetryException) {
vtx1.reload();
} else {
if (ex.getCause() instanceof ConcurrentModificationException) {
ex.printStackTrace();
}
log("*$$$$$$$$$$$$$$ [" + id + "][" + k + "] Distributed Exception: [" + ex + "] Cause: [" + (ex.getCause() != null ? ex.getCause() : "--") + "] for vertex " + vtx1);
}
// log("*** [" + id + "][" + k + "] Distributed Exception: [" + ex + "] Cause: [" + (ex.getCause() != null ?
// ex.getCause() : "--") + "] for vertex " + vtx1);
isException = true;
} catch (Exception ex) {
log("[" + id + "][" + k + "] Exception " + ex + " for vertex " + vtx1);
}
}
if (retry) {
log("********** [" + id + "] Failed to update after Exception for vertex " + vtx);
}
}
}
}
} finally {
graph.shutdown();
}
operations.incrementAndGet();
}
} catch (Exception ex) {
System.out.println("ID: [" + id + "]********** Exception " + ex + " \n\n");
ex.printStackTrace();
} finally {
log("[" + id + "] Done................>>>>>>>>>>>>>>>>>>");
}
}
};
return th;
}
use of com.orientechnologies.orient.server.distributed.task.ODistributedRecordLockedException in project orientdb by orientechnologies.
the class ConcurrentDistributedUpdateTest method createWriter.
protected Callable<Void> createWriter(final int serverId, final int threadId, final String databaseURL) {
return new Callable<Void>() {
@Override
public Void call() throws Exception {
final String id = serverId + "." + threadId;
boolean isRunning = true;
final OrientBaseGraph graph = new OrientGraph(databaseURL);
try {
String query = "select from Test where prop2='v2-1'";
for (int i = 0; i < 100 && isRunning; i++) {
if ((i % 25) == 0) {
log("[" + id + "] Records Processed: [" + i + "]");
}
Iterable<Vertex> vtxs = graph.command(new OCommandSQL(query)).execute();
boolean update = true;
for (Vertex vtx : vtxs) {
if (update) {
update = true;
for (int k = 0; k < 10 && update; k++) {
OrientVertex vtx1 = (OrientVertex) vtx;
try {
vtx1.setProperty("prop5", "prop55");
graph.commit();
// log("[" + id + "/" + i + "/" + k + "] OK!\n");
break;
} catch (OConcurrentModificationException ex) {
vtx1.reload();
} catch (ODistributedRecordLockedException ex) {
log("[" + id + "/" + i + "/" + k + "] Distributed lock Exception " + ex + " for vertex " + vtx1 + " \n");
// ex.printStackTrace();
update = false;
// isRunning = false;
break;
} catch (Exception ex) {
log("[" + id + "/" + i + "/" + k + "] Exception " + ex + " for vertex " + vtx1 + "\n\n");
ex.printStackTrace();
isRunning = false;
break;
}
}
if (!isRunning)
break;
}
}
}
} catch (Exception ex) {
System.out.println("ID: [" + id + "]********** Exception " + ex + " \n\n");
ex.printStackTrace();
} finally {
log("[" + id + "] Done................>>>>>>>>>>>>>>>>>>");
graph.shutdown();
runningWriters.countDown();
}
Assert.assertTrue(isRunning);
return null;
}
};
}
Aggregations