use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OTransactionOptimistic method addRecord.
public void addRecord(final ORecord iRecord, final byte iStatus, final String iClusterName) {
checkTransaction();
if (iStatus != ORecordOperation.LOADED)
changedDocuments.remove(iRecord);
try {
switch(iStatus) {
case ORecordOperation.CREATED:
{
database.checkSecurity(ORule.ResourceGeneric.CLUSTER, ORole.PERMISSION_CREATE, iClusterName);
RESULT res = database.callbackHooks(TYPE.BEFORE_CREATE, iRecord);
if (res == RESULT.RECORD_CHANGED && iRecord instanceof ODocument)
((ODocument) iRecord).validate();
}
break;
case ORecordOperation.LOADED:
/**
* Read hooks already invoked in {@link com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx#executeReadRecord}
*/
break;
case ORecordOperation.UPDATED:
{
database.checkSecurity(ORule.ResourceGeneric.CLUSTER, ORole.PERMISSION_UPDATE, iClusterName);
RESULT res = database.callbackHooks(TYPE.BEFORE_UPDATE, iRecord);
if (res == RESULT.RECORD_CHANGED && iRecord instanceof ODocument)
((ODocument) iRecord).validate();
}
break;
case ORecordOperation.DELETED:
database.checkSecurity(ORule.ResourceGeneric.CLUSTER, ORole.PERMISSION_DELETE, iClusterName);
database.callbackHooks(TYPE.BEFORE_DELETE, iRecord);
break;
}
try {
final ORecordId rid = (ORecordId) iRecord.getIdentity();
if (!rid.isValid()) {
ORecordInternal.onBeforeIdentityChanged(iRecord);
database.assignAndCheckCluster(iRecord, iClusterName);
rid.setClusterPosition(newObjectCounter--);
ORecordInternal.onAfterIdentityChanged(iRecord);
}
ORecordOperation txEntry = getRecordEntry(rid);
if (txEntry == null) {
if (!(rid.isTemporary() && iStatus != ORecordOperation.CREATED)) {
// NEW ENTRY: JUST REGISTER IT
txEntry = new ORecordOperation(iRecord, iStatus);
allEntries.put(rid.copy(), txEntry);
}
} else {
// UPDATE PREVIOUS STATUS
txEntry.record = iRecord;
switch(txEntry.type) {
case ORecordOperation.LOADED:
switch(iStatus) {
case ORecordOperation.UPDATED:
txEntry.type = ORecordOperation.UPDATED;
break;
case ORecordOperation.DELETED:
txEntry.type = ORecordOperation.DELETED;
break;
}
break;
case ORecordOperation.UPDATED:
switch(iStatus) {
case ORecordOperation.DELETED:
txEntry.type = ORecordOperation.DELETED;
break;
}
break;
case ORecordOperation.DELETED:
break;
case ORecordOperation.CREATED:
switch(iStatus) {
case ORecordOperation.DELETED:
allEntries.remove(rid);
// txEntry.type = ORecordOperation.DELETED;
break;
}
break;
}
}
switch(iStatus) {
case ORecordOperation.CREATED:
database.callbackHooks(TYPE.AFTER_CREATE, iRecord);
break;
case ORecordOperation.LOADED:
/**
* Read hooks already invoked in
* {@link com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx#executeReadRecord} .
*/
break;
case ORecordOperation.UPDATED:
database.callbackHooks(TYPE.AFTER_UPDATE, iRecord);
break;
case ORecordOperation.DELETED:
database.callbackHooks(TYPE.AFTER_DELETE, iRecord);
break;
}
// RESET TRACKING
if (iRecord instanceof ODocument && ((ODocument) iRecord).isTrackingChanges()) {
ODocumentInternal.clearTrackData(((ODocument) iRecord));
}
} catch (Exception e) {
switch(iStatus) {
case ORecordOperation.CREATED:
database.callbackHooks(TYPE.CREATE_FAILED, iRecord);
break;
case ORecordOperation.UPDATED:
database.callbackHooks(TYPE.UPDATE_FAILED, iRecord);
break;
case ORecordOperation.DELETED:
database.callbackHooks(TYPE.DELETE_FAILED, iRecord);
break;
}
throw OException.wrapException(new ODatabaseException("Error on saving record " + iRecord.getIdentity()), e);
}
} finally {
switch(iStatus) {
case ORecordOperation.CREATED:
database.callbackHooks(TYPE.FINALIZE_CREATION, iRecord);
break;
case ORecordOperation.UPDATED:
database.callbackHooks(TYPE.FINALIZE_UPDATE, iRecord);
break;
case ORecordOperation.DELETED:
database.callbackHooks(TYPE.FINALIZE_DELETION, iRecord);
break;
}
}
}
use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OLiveQueryTest method testLiveInsertOnCluster.
@Test
public void testLiveInsertOnCluster() {
ODatabaseDocumentTx db = new ODatabaseDocumentTx("memory:OLiveQueryTest");
db.activateOnCurrentThread();
db.create();
try {
OClass clazz = db.getMetadata().getSchema().createClass("test");
int defaultCluster = clazz.getDefaultClusterId();
OCluster cluster = db.getStorage().getClusterById(defaultCluster);
MyLiveQueryListener listener = new MyLiveQueryListener();
db.query(new OLiveQuery<ODocument>("live select from cluster:" + cluster.getName(), listener));
db.command(new OCommandSQL("insert into cluster:" + cluster.getName() + " set name = 'foo', surname = 'bar'")).execute();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Assert.assertEquals(listener.ops.size(), 1);
for (ORecordOperation doc : listener.ops) {
Assert.assertEquals(doc.type, ORecordOperation.CREATED);
Assert.assertEquals(((ODocument) doc.record).field("name"), "foo");
}
} finally {
db.drop();
}
}
use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class ODistributedTransactionManager method processCommitResult.
protected boolean processCommitResult(final String localNodeName, final OTransaction iTx, final OTxTask txTask, final Set<String> involvedClusters, final Iterable<ORecordOperation> tmpEntries, final Collection<String> nodes, final int autoRetryDelay, final ODistributedRequestId reqId, final ODistributedResponse dResponse, final boolean isLastRetry) throws InterruptedException {
final Object result = dResponse.getPayload();
if (result instanceof OTxTaskResult) {
final OTxTaskResult txResult = (OTxTaskResult) result;
final List<Object> list = txResult.results;
for (int i = 0; i < txTask.getTasks().size(); ++i) {
final Object o = list.get(i);
final OAbstractRecordReplicatedTask task = txTask.getTasks().get(i);
if (task instanceof OCreateRecordTask) {
final OCreateRecordTask t = (OCreateRecordTask) task;
iTx.updateIdentityAfterCommit(t.getRid(), ((OPlaceholder) o).getIdentity());
final ORecord rec = iTx.getRecord(t.getRid());
if (rec != null)
ORecordInternal.setVersion(rec, ((OPlaceholder) o).getVersion());
} else if (task instanceof OUpdateRecordTask) {
final OUpdateRecordTask t = (OUpdateRecordTask) task;
ORecordInternal.setVersion(iTx.getRecord(t.getRid()), (Integer) o);
} else if (task instanceof ODeleteRecordTask) {
}
}
// RESET DIRTY FLAGS TO AVOID CALLING AUTO-SAVE
for (ORecordOperation op : tmpEntries) {
final ORecord record = op.getRecord();
if (record != null)
ORecordInternal.unsetDirty(record);
}
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.debug(this, localNodeName, null, ODistributedServerLog.DIRECTION.NONE, "Distributed transaction %s completed", reqId);
sendTxCompleted(localNodeName, involvedClusters, nodes, reqId, true, txTask.getPartitionKey());
} else if (result instanceof ODistributedRecordLockedException) {
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.debug(this, localNodeName, nodes.toString(), ODistributedServerLog.DIRECTION.IN, "Distributed transaction %s error: record %s is locked by %s", reqId, ((ODistributedRecordLockedException) result).getRid(), ((ODistributedRecordLockedException) result).getLockHolder());
// if this is the last retry (and it failed), we don't need to wait anymore
if (autoRetryDelay > 0 && !isLastRetry)
Thread.sleep(autoRetryDelay / 2 + new Random().nextInt(autoRetryDelay));
// RETRY
return false;
} else if (result instanceof Exception) {
// EXCEPTION: LOG IT AND ADD AS NESTED EXCEPTION
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.debug(this, localNodeName, nodes.toString(), ODistributedServerLog.DIRECTION.IN, "Distributed transaction %s received error: %s", reqId, result, result.toString());
// LET TO THE CALLER TO UNDO IT
if (result instanceof OTransactionException || result instanceof ONeedRetryException)
throw (RuntimeException) result;
if (result instanceof ORecordNotFoundException) {
// REPAIR THE RECORD IMMEDIATELY
localDistributedDatabase.getDatabaseRepairer().repairRecord((ORecordId) ((ORecordNotFoundException) result).getRid());
// RETRY
return false;
}
throw OException.wrapException(new OTransactionException("Error on committing distributed transaction"), (Exception) result);
} else {
// UNKNOWN RESPONSE TYPE
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.info(this, localNodeName, nodes.toString(), ODistributedServerLog.DIRECTION.IN, "Distributed transaction %s error, received unknown response type: %s", reqId, result);
// ROLLBACK TX
storage.executeUndoOnLocalServer(dResponse.getRequestId(), txTask);
sendTxCompleted(localNodeName, involvedClusters, nodes, dResponse.getRequestId(), false, txTask.getPartitionKey());
throw new OTransactionException("Error on committing distributed transaction, received unknown response type " + result);
}
return true;
}
use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OrientElement method checkDeletedInTx.
protected boolean checkDeletedInTx() {
OrientBaseGraph curGraph = getGraph();
if (curGraph == null)
return false;
ORID id;
if (getRecord() != null)
id = getRecord().getIdentity();
else
return false;
final ORecordOperation oper = curGraph.getRawGraph().getTransaction().getRecordEntry(id);
if (oper == null)
return id.isTemporary();
else
return oper.type == ORecordOperation.DELETED;
}
use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OTransactionOptimisticProxy method begin.
@Override
public void begin() {
super.begin();
// Needed for keep the exception and insure that all data is read from the socket.
OException toThrow = null;
try {
setUsingLog(channel.readByte() == 1);
Map<ORecord, byte[]> lazyDeserialize = new IdentityHashMap<ORecord, byte[]>();
byte lastTxStatus;
for (lastTxStatus = channel.readByte(); lastTxStatus == 1; lastTxStatus = channel.readByte()) {
final byte recordStatus = channel.readByte();
final ORecordId rid = channel.readRID();
final byte recordType = channel.readByte();
final ORecordOperation entry = new OTransactionEntryProxy(recordType);
entry.type = recordStatus;
switch(recordStatus) {
case ORecordOperation.CREATED:
byte[] content = channel.readBytes();
ORecordInternal.fill(entry.getRecord(), rid, 0, null, true);
// oNetworkProtocolBinary.fillRecord(rid, content, 0, entry.getRecord(), database);
lazyDeserialize.put(entry.getRecord(), content);
// SAVE THE RECORD TO RETRIEVE THEM FOR THE NEW RID TO SEND BACK TO THE REQUESTER
createdRecords.put(rid.copy(), entry.getRecord());
break;
case ORecordOperation.UPDATED:
int version = channel.readVersion();
byte[] bytes = channel.readBytes();
ORecordInternal.fill(entry.getRecord(), rid, version, null, true);
// oNetworkProtocolBinary.fillRecord(rid, bytes, version, entry.getRecord(), database);
lazyDeserialize.put(entry.getRecord(), bytes);
if (protocolVersion >= 23)
ORecordInternal.setContentChanged(entry.getRecord(), channel.readBoolean());
break;
case ORecordOperation.DELETED:
// LOAD RECORD TO BE SURE IT HASN'T BEEN DELETED BEFORE + PROVIDE CONTENT FOR ANY HOOK
final ORecord rec = rid.getRecord();
int deleteVersion = channel.readVersion();
if (rec == null)
toThrow = new ORecordNotFoundException(rid);
else {
ORecordInternal.setVersion(rec, deleteVersion);
entry.setRecord(rec);
}
break;
default:
throw new OTransactionException("Unrecognized tx command: " + recordStatus);
}
// PUT IN TEMPORARY LIST TO GET FETCHED AFTER ALL FOR CACHE
tempEntries.put(entry.getRecord().getIdentity(), entry);
}
String dbSerializerName = "";
if (database != null)
dbSerializerName = database.getSerializer().toString();
String name = oNetworkProtocolBinary.getRecordSerializerName(connection);
for (Map.Entry<ORecord, byte[]> entry : lazyDeserialize.entrySet()) {
ORecord record = entry.getKey();
final boolean contentChanged = ORecordInternal.isContentChanged(record);
if (ORecordInternal.getRecordType(record) == ODocument.RECORD_TYPE && !dbSerializerName.equals(name)) {
ORecordSerializer ser = ORecordSerializerFactory.instance().getFormat(name);
ser.fromStream(entry.getValue(), record, null);
record.setDirty();
ORecordInternal.setContentChanged(record, contentChanged);
} else {
record.fromStream(entry.getValue());
record.setDirty();
ORecordInternal.setContentChanged(record, contentChanged);
}
}
if (toThrow != null)
throw toThrow;
if (lastTxStatus == -1)
// ABORT TX
throw new OTransactionAbortedException("Transaction aborted by the client");
final ODocument remoteIndexEntries = new ODocument(channel.readBytes());
fillIndexOperations(remoteIndexEntries);
// FIRE THE TRIGGERS ONLY AFTER HAVING PARSED THE REQUEST
for (Entry<ORID, ORecordOperation> entry : tempEntries.entrySet()) {
if (entry.getValue().type == ORecordOperation.UPDATED) {
// SPECIAL CASE FOR UPDATE: WE NEED TO LOAD THE RECORD AND APPLY CHANGES TO GET WORKING HOOKS (LIKE INDEXES)
final ORecord record = entry.getValue().record.getRecord();
final boolean contentChanged = ORecordInternal.isContentChanged(record);
final ORecord loadedRecord = record.getIdentity().copy().getRecord();
if (loadedRecord == null)
throw new ORecordNotFoundException(record.getIdentity());
if (ORecordInternal.getRecordType(loadedRecord) == ODocument.RECORD_TYPE && ORecordInternal.getRecordType(loadedRecord) == ORecordInternal.getRecordType(record)) {
((ODocument) loadedRecord).merge((ODocument) record, false, false);
loadedRecord.setDirty();
ORecordInternal.setContentChanged(loadedRecord, contentChanged);
ORecordInternal.setVersion(loadedRecord, record.getVersion());
entry.getValue().record = loadedRecord;
// SAVE THE RECORD TO RETRIEVE THEM FOR THE NEW VERSIONS TO SEND BACK TO THE REQUESTER
updatedRecords.put((ORecordId) entry.getKey(), entry.getValue().getRecord());
}
}
addRecord(entry.getValue().getRecord(), entry.getValue().type, null);
}
tempEntries.clear();
// UNMARSHALL ALL THE RECORD AT THE END TO BE SURE ALL THE RECORD ARE LOADED IN LOCAL TX
for (ORecord record : createdRecords.values()) {
unmarshallRecord(record);
if (record instanceof ODocument) {
// Force conversion of value to class for trigger default values.
ODocumentInternal.autoConvertValueToClass(connection.getDatabase(), (ODocument) record);
}
}
for (ORecord record : updatedRecords.values()) unmarshallRecord(record);
} catch (IOException e) {
rollback();
throw OException.wrapException(new OSerializationException("Cannot read transaction record from the network. Transaction aborted"), e);
}
}
Aggregations