use of com.orientechnologies.orient.core.command.OCommandRequestAsynch in project orientdb by orientechnologies.
the class OStorageRemote method command.
/**
* Execute the command remotely and get the results back.
*/
public Object command(final OCommandRequestText iCommand) {
if (!(iCommand instanceof OSerializableStream))
throw new OCommandExecutionException("Cannot serialize the command to be executed to the server side.");
final boolean live = iCommand instanceof OLiveQuery;
final ODatabaseDocument database = ODatabaseRecordThreadLocal.INSTANCE.get();
return networkOperation(new OStorageRemoteOperation<Object>() {
@Override
public Object execute(final OChannelBinaryAsynchClient network, OStorageRemoteSession session) throws IOException {
Object result = null;
session.commandExecuting = true;
try {
final boolean asynch = iCommand instanceof OCommandRequestAsynch && ((OCommandRequestAsynch) iCommand).isAsynchronous();
try {
beginRequest(network, OChannelBinaryProtocol.REQUEST_COMMAND, session);
if (live) {
network.writeByte((byte) 'l');
} else {
// ASYNC / SYNC
network.writeByte((byte) (asynch ? 'a' : 's'));
}
network.writeBytes(OStreamSerializerAnyStreamable.INSTANCE.toStream(iCommand));
} finally {
endRequest(network);
}
try {
beginResponse(network, session);
// Collection of prefetched temporary record (nested projection record), to refer for avoid garbage collection.
List<ORecord> temporaryResults = new ArrayList<ORecord>();
boolean addNextRecord = true;
if (asynch) {
byte status;
// ASYNCH: READ ONE RECORD AT TIME
while ((status = network.readByte()) > 0) {
final ORecord record = (ORecord) OChannelBinaryProtocol.readIdentifiable(network);
if (record == null)
continue;
switch(status) {
case 1:
// PUT AS PART OF THE RESULT SET. INVOKE THE LISTENER
if (addNextRecord) {
addNextRecord = iCommand.getResultListener().result(record);
database.getLocalCache().updateRecord(record);
}
break;
case 2:
if (record.getIdentity().getClusterId() == -2)
temporaryResults.add(record);
// PUT IN THE CLIENT LOCAL CACHE
database.getLocalCache().updateRecord(record);
}
}
} else {
result = readSynchResult(network, database, temporaryResults);
if (live) {
final ODocument doc = ((List<ODocument>) result).get(0);
final Integer token = doc.field("token");
final Boolean unsubscribe = doc.field("unsubscribe");
if (token != null) {
if (Boolean.TRUE.equals(unsubscribe)) {
if (OStorageRemote.this.asynchEventListener != null)
OStorageRemote.this.asynchEventListener.unregisterLiveListener(token);
} else {
final OLiveResultListener listener = (OLiveResultListener) iCommand.getResultListener();
ODatabaseDocumentInternal current = ODatabaseRecordThreadLocal.INSTANCE.get();
final ODatabaseDocument dbCopy = current.copy();
ORemoteConnectionPool pool = OStorageRemote.this.connectionManager.getPool(network.getServerURL());
OStorageRemote.this.asynchEventListener.registerLiveListener(pool, token, new OLiveResultListener() {
@Override
public void onUnsubscribe(int iLiveToken) {
listener.onUnsubscribe(iLiveToken);
dbCopy.close();
}
@Override
public void onLiveResult(int iLiveToken, ORecordOperation iOp) throws OException {
dbCopy.activateOnCurrentThread();
listener.onLiveResult(iLiveToken, iOp);
}
@Override
public void onError(int iLiveToken) {
listener.onError(iLiveToken);
dbCopy.close();
}
});
}
} else {
throw new OStorageException("Cannot execute live query, returned null token");
}
}
}
if (!temporaryResults.isEmpty()) {
if (result instanceof OBasicResultSet<?>) {
((OBasicResultSet<?>) result).setTemporaryRecordCache(temporaryResults);
}
}
return result;
} finally {
endResponse(network);
}
} finally {
session.commandExecuting = false;
if (iCommand.getResultListener() != null && !live)
iCommand.getResultListener().end();
}
}
}, "Error on executing command: " + iCommand);
}
Aggregations