public Map<OIdentifiable, Change> deserializeChanges(final byte[] stream, int offset) { final int count = OIntegerSerializer.INSTANCE.deserializeLiteral(stream, offset); offset += OIntegerSerializer.INT_SIZE; final HashMap<OIdentifiable, Change> res = new HashMap<OIdentifiable, Change>(); for (int i = 0; i < count; i++) { ORecordId rid = OLinkSerializer.INSTANCE.deserialize(stream, offset); offset += OLinkSerializer.RID_SIZE; Change change = ChangeSerializationHelper.INSTANCE.deserializeChange(stream, offset); offset += Change.SIZE; final OIdentifiable identifiable; if (rid.isTemporary() && rid.getRecord() != null) identifiable = rid.getRecord(); else identifiable = rid; res.put(identifiable, change); } return res; }
protected void addRecord( final ORecordInternal<?> iRecord, final byte iStatus, final String iClusterName) { checkTransaction(); switch (iStatus) { case ORecordOperation.CREATED: database.checkSecurity( ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_CREATE, iClusterName); database.callbackHooks(TYPE.BEFORE_CREATE, iRecord); break; case ORecordOperation.LOADED: /** * Read hooks already invoked in {@link * com.orientechnologies.orient.core.db.record.ODatabaseRecordAbstract#executeReadRecord} . */ break; case ORecordOperation.UPDATED: database.checkSecurity( ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_UPDATE, iClusterName); database.callbackHooks(TYPE.BEFORE_UPDATE, iRecord); break; case ORecordOperation.DELETED: database.checkSecurity( ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_DELETE, iClusterName); database.callbackHooks(TYPE.BEFORE_DELETE, iRecord); break; } try { if (iRecord.getIdentity().isTemporary()) temp2persistent.put(iRecord.getIdentity().copy(), iRecord); if ((status == OTransaction.TXSTATUS.COMMITTING) && database.getStorage() instanceof OStorageEmbedded) { // I'M COMMITTING: BYPASS LOCAL BUFFER switch (iStatus) { case ORecordOperation.CREATED: case ORecordOperation.UPDATED: final ORID oldRid = iRecord.getIdentity().copy(); database.executeSaveRecord( iRecord, iClusterName, iRecord.getRecordVersion(), iRecord.getRecordType(), false, OPERATION_MODE.SYNCHRONOUS, false, null, null); updateIdentityAfterCommit(oldRid, iRecord.getIdentity()); break; case ORecordOperation.DELETED: database.executeDeleteRecord( iRecord, iRecord.getRecordVersion(), false, false, OPERATION_MODE.SYNCHRONOUS, false); break; } final ORecordOperation txRecord = getRecordEntry(iRecord.getIdentity()); if (txRecord == null) { // NOT IN TX, SAVE IT ANYWAY allEntries.put(iRecord.getIdentity(), new ORecordOperation(iRecord, iStatus)); } else if (txRecord.record != iRecord) { // UPDATE LOCAL RECORDS TO AVOID MISMATCH OF VERSION/CONTENT final String clusterName = getDatabase().getClusterNameById(iRecord.getIdentity().getClusterId()); if (!clusterName.equals(OMetadataDefault.CLUSTER_MANUAL_INDEX_NAME) && !clusterName.equals(OMetadataDefault.CLUSTER_INDEX_NAME)) OLogManager.instance() .warn( this, "Found record in transaction with the same RID %s but different instance. Probably the record has been loaded from another transaction and reused on the current one: reload it from current transaction before to update or delete it", iRecord.getIdentity()); txRecord.record = iRecord; txRecord.type = iStatus; } } else { final ORecordId rid = (ORecordId) iRecord.getIdentity(); if (!rid.isValid()) { iRecord.onBeforeIdentityChanged(rid); // ASSIGN A UNIQUE SERIAL TEMPORARY ID if (rid.clusterId == ORID.CLUSTER_ID_INVALID) rid.clusterId = iClusterName != null ? database.getClusterIdByName(iClusterName) : database.getDefaultClusterId(); rid.clusterPosition = OClusterPositionFactory.INSTANCE.valueOf(newObjectCounter--); iRecord.onAfterIdentityChanged(iRecord); } else // REMOVE FROM THE DB'S CACHE database.getLevel1Cache().freeRecord(rid); ORecordOperation txEntry = getRecordEntry(rid); if (txEntry == null) { if (!(rid.isTemporary() && iStatus != ORecordOperation.CREATED)) { // NEW ENTRY: JUST REGISTER IT txEntry = new ORecordOperation(iRecord, iStatus); recordEntries.put(rid, 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: recordEntries.remove(rid); 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.record.ODatabaseRecordAbstract#executeReadRecord}. */ break; case ORecordOperation.UPDATED: database.callbackHooks(TYPE.AFTER_UPDATE, iRecord); break; case ORecordOperation.DELETED: database.callbackHooks(TYPE.AFTER_DELETE, iRecord); break; } } catch (Throwable t) { 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; } if (t instanceof RuntimeException) throw (RuntimeException) t; else throw new ODatabaseException("Error on saving record " + iRecord.getIdentity(), t); } }