/** * Update the record. * * @param iForceCreate * @param iCallback */ public void saveRecord( final ORecordInternal<?> iRecord, final String iClusterName, final OPERATION_MODE iMode, boolean iForceCreate, final ORecordCallback<? extends Number> iCallback) { try { database.executeSaveRecord( iRecord, iClusterName, iRecord.getVersion(), iRecord.getRecordType(), true, iMode, iForceCreate, iCallback); } catch (Exception e) { // REMOVE IT FROM THE CACHE TO AVOID DIRTY RECORDS final ORecordId rid = (ORecordId) iRecord.getIdentity(); if (rid.isValid()) database.getLevel1Cache().freeRecord(rid); if (e instanceof RuntimeException) throw (RuntimeException) e; throw new OException(e); } }
/** Deletes the record. */ public void deleteRecord(final ORecordInternal<?> iRecord, final OPERATION_MODE iMode) { if (!iRecord.getIdentity().isPersistent()) return; try { database.executeDeleteRecord(iRecord, iRecord.getVersion(), true, true, iMode); } catch (Exception e) { // REMOVE IT FROM THE CACHE TO AVOID DIRTY RECORDS final ORecordId rid = (ORecordId) iRecord.getIdentity(); if (rid.isValid()) database.getLevel1Cache().freeRecord(rid); if (e instanceof RuntimeException) throw (RuntimeException) e; throw new OException(e); } }
public long createRecord( final ORecordId iRid, final byte[] iContent, final byte iRecordType, final ORecordCallback<Long> iCallback) { checkConnection(); do { try { final OChannelBinaryClient network = beginRequest(OChannelBinaryProtocol.REQUEST_RECORD_CREATE); try { network.writeShort((short) iRid.clusterId); network.writeBytes(iContent); network.writeByte(iRecordType); } finally { endRequest(network); } if (iCallback == null) try { beginResponse(network); iRid.clusterPosition = network.readLong(); return iRid.clusterPosition; } finally { endResponse(network); } else { Callable<Object> response = new Callable<Object>() { public Object call() throws Exception { final Long result; beginResponse(network); try { result = network.readLong(); } finally { endResponse(network); } iCallback.call(result); return null; } }; asynchExecutor.submit(new FutureTask<Object>(response)); } } catch (OException e) { // PASS THROUGH throw e; } catch (Exception e) { handleException("Error on create record in cluster: " + iRid.clusterId, e); } } while (true); }
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; }
@SuppressWarnings("unchecked") protected Object unwrap(Object node) { Object result = node; if (node instanceof Map) { Map<String, Object> cast = (Map<String, Object>) node; ORecordId id; if (cast.containsKey("id")) { id = new ORecordId((String) cast.get("id")); cast.remove("id"); } else id = new ORecordId(); ODocument real; if (id.isNew()) { if (cast.containsKey("class")) { real = new ODocument((String) cast.get("class")); cast.remove("class"); } else throw new RuntimeException( "Unknown class in newly created ODocument. Please provide 'class' property in every new object."); } else real = new ODocument(id); for (String key : cast.keySet()) real.field(key, unwrap(cast.get(key))); result = real; } else if (node instanceof List) { List<Object> cast = (List<Object>) node; for (int i = 0; i < cast.size(); i++) cast.set(i, unwrap(cast.get(i))); } return result; }
public void executeDeleteRecord(final OIdentifiable iRecord, final int iVersion) { checkOpeness(); final ORecordId rid = (ORecordId) iRecord.getIdentity(); if (rid == null) throw new ODatabaseException( "Cannot delete record because it has no identity. Probably was created from scratch or contains projections of fields rather than a full record"); if (!rid.isValid()) return; checkSecurity( ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_DELETE, getClusterNameById(rid.clusterId)); setCurrentDatabaseinThreadLocal(); try { callbackHooks(TYPE.BEFORE_DELETE, iRecord); underlying.delete(rid, iVersion); callbackHooks(TYPE.AFTER_DELETE, iRecord); // REMOVE THE RECORD FROM 1 AND 2 LEVEL CACHES getLevel1Cache().deleteRecord(rid); } catch (OException e) { // RE-THROW THE EXCEPTION throw e; } catch (Throwable t) { // WRAP IT AS ODATABASE EXCEPTION throw new ODatabaseException( "Error on deleting record in cluster #" + iRecord.getIdentity().getClusterId(), t); } }
@Override public IRelation convertToEntity(ODocument document) { Relation relation = new Relation(); // load relation link ODocument relationLink = getRelationLink(document, true); if (relationLink == null) return null; // exact error was logged below // get from/to - slim entities, just title and id relation.setFromEntity(getRelatedEntity(relationLink, "out")); relation.setToEntity(getRelatedEntity(relationLink, "in")); // set relation type ORecordId relationType = document.field("relationType", ORecordId.class); if (relationType != null) { RelationTypeRepository relationTypeRepository = repositoryFactory.produceRepository(OrientDbRelationTypeRepository.class); if (relationTypeRepository != null) relation.setRelationType( relationTypeRepository.find(relationType.getIdentity().toString())); else logger.error("Could not produce RelationTypeRepository while converting relation."); } // rest is easy relation.setDescription(document.field("description", String.class)); relation.setDescriptionMarkup(document.field("descriptionMarkup", String.class)); // populate with data populateEntityWithBaseData(document, relation); populateEntityWithCreatedModified(document, relation); populateEntityWithColored(document, relation); populateEntityWithAnnotated(document, relation); populateEntityWithCore(document, relation); return relation; }
public static void fieldTypeToString( final StringBuilder iBuffer, OType iType, final Object iValue) { if (iValue == null) return; final long timer = PROFILER.startChrono(); if (iType == null) { if (iValue instanceof ORID) iType = OType.LINK; else iType = OType.EMBEDDED; } switch (iType) { case STRING: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.string2string"), "Serialize string to string", timer); break; case BOOLEAN: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.bool2string"), "Serialize boolean to string", timer); break; case INTEGER: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.int2string"), "Serialize integer to string", timer); break; case FLOAT: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.float2string"), "Serialize float to string", timer); break; case DECIMAL: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.decimal2string"), "Serialize decimal to string", timer); break; case LONG: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.long2string"), "Serialize long to string", timer); break; case DOUBLE: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.double2string"), "Serialize double to string", timer); break; case SHORT: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.short2string"), "Serialize short to string", timer); break; case BYTE: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.byte2string"), "Serialize byte to string", timer); break; case BINARY: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.binary2string"), "Serialize binary to string", timer); break; case DATE: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.date2string"), "Serialize date to string", timer); break; case DATETIME: simpleValueToStream(iBuffer, iType, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.datetime2string"), "Serialize datetime to string", timer); break; case LINK: if (iValue instanceof ORecordId) ((ORecordId) iValue).toString(iBuffer); else ((ORecord<?>) iValue).getIdentity().toString(iBuffer); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.link2string"), "Serialize link to string", timer); break; case EMBEDDEDSET: ORecordSerializerSchemaAware2CSV.INSTANCE.embeddedCollectionToStream( ODatabaseRecordThreadLocal.INSTANCE.getIfDefined(), null, iBuffer, null, null, iValue, null, true); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.embedSet2string"), "Serialize embeddedset to string", timer); break; case EMBEDDEDLIST: ORecordSerializerSchemaAware2CSV.INSTANCE.embeddedCollectionToStream( ODatabaseRecordThreadLocal.INSTANCE.getIfDefined(), null, iBuffer, null, null, iValue, null, true); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.embedList2string"), "Serialize embeddedlist to string", timer); break; case EMBEDDEDMAP: ORecordSerializerSchemaAware2CSV.INSTANCE.embeddedMapToStream( ODatabaseRecordThreadLocal.INSTANCE.getIfDefined(), null, iBuffer, null, null, iValue, null, true); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.embedMap2string"), "Serialize embeddedmap to string", timer); break; case EMBEDDED: OStringSerializerEmbedded.INSTANCE.toStream(iBuffer, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.embed2string"), "Serialize embedded to string", timer); break; case CUSTOM: OStringSerializerAnyStreamable.INSTANCE.toStream(iBuffer, iValue); PROFILER.stopChrono( PROFILER.getProcessMetric("serializer.record.string.custom2string"), "Serialize custom to string", timer); break; default: throw new IllegalArgumentException( "Type " + iType + " not supported to convert value: " + iValue); } }
private void addRecord( final ORecordInternal<?> iRecord, final byte iStatus, final String iClusterName) { checkTransaction(); if ((status == OTransaction.TXSTATUS.COMMITTING) && database.getStorage() instanceof OStorageEmbedded) { // I'M COMMITTING OR IT'S AN INDEX: BYPASS LOCAL BUFFER switch (iStatus) { case OTransactionRecordEntry.CREATED: case OTransactionRecordEntry.UPDATED: database.executeSaveRecord( iRecord, iClusterName, iRecord.getVersion(), iRecord.getRecordType()); break; case OTransactionRecordEntry.DELETED: database.executeDeleteRecord(iRecord, iRecord.getVersion()); break; } } else { final ORecordId rid = (ORecordId) iRecord.getIdentity(); if (!rid.isValid()) { // // TODO: NEED IT FOR REAL? // // NEW RECORD: CHECK IF IT'S ALREADY IN // for (OTransactionRecordEntry entry : recordEntries.values()) { // if (entry.getRecord() == iRecord) // return; // } 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 = newObjectCounter--; iRecord.onAfterIdentityChanged(iRecord); } else // REMOVE FROM THE DB'S CACHE database.getLevel1Cache().freeRecord(rid); OTransactionRecordEntry txEntry = getRecordEntry(rid); if (txEntry == null) { // NEW ENTRY: JUST REGISTER IT txEntry = new OTransactionRecordEntry(iRecord, iStatus, iClusterName); recordEntries.put(rid, txEntry); } else { // UPDATE PREVIOUS STATUS txEntry.setRecord(iRecord); switch (txEntry.status) { case OTransactionRecordEntry.LOADED: switch (iStatus) { case OTransactionRecordEntry.UPDATED: txEntry.status = OTransactionRecordEntry.UPDATED; break; case OTransactionRecordEntry.DELETED: txEntry.status = OTransactionRecordEntry.DELETED; break; } break; case OTransactionRecordEntry.UPDATED: switch (iStatus) { case OTransactionRecordEntry.DELETED: txEntry.status = OTransactionRecordEntry.DELETED; break; } break; case OTransactionRecordEntry.DELETED: break; case OTransactionRecordEntry.CREATED: switch (iStatus) { case OTransactionRecordEntry.DELETED: recordEntries.remove(rid); break; } break; } } } }
public class ORecordId implements ORID { private static final long serialVersionUID = 247070594054408657L; public static final ORecordId EMPTY_RECORD_ID = new ORecordId(); public static final byte[] EMPTY_RECORD_ID_STREAM = EMPTY_RECORD_ID.toStream(); public int clusterId = CLUSTER_ID_INVALID; // INT TO AVOID // JVM // PENALITY, BUT // IT'S STORED // AS SHORT public OClusterPosition clusterPosition = OClusterPosition.INVALID_POSITION; public static final int PERSISTENT_SIZE = OBinaryProtocol.SIZE_SHORT + OClusterPositionFactory.INSTANCE.getSerializedSize(); public ORecordId() {} public ORecordId(final int iClusterId, final OClusterPosition iPosition) { clusterId = iClusterId; checkClusterLimits(); clusterPosition = iPosition; } public ORecordId(final int iClusterIdId) { clusterId = iClusterIdId; checkClusterLimits(); } public ORecordId(final String iRecordId) { fromString(iRecordId); } /** * Copy constructor. * * @param parentRid Source object */ public ORecordId(final ORID parentRid) { clusterId = parentRid.getClusterId(); clusterPosition = parentRid.getClusterPosition(); } public void reset() { clusterId = CLUSTER_ID_INVALID; clusterPosition = CLUSTER_POS_INVALID; } public boolean isValid() { return clusterPosition.isValid(); } public boolean isPersistent() { return clusterId > -1 && clusterPosition.isPersistent(); } public boolean isNew() { return clusterPosition.isNew(); } public boolean isTemporary() { return clusterId != -1 && clusterPosition.isTemporary(); } @Override public String toString() { return generateString(clusterId, clusterPosition); } public StringBuilder toString(StringBuilder iBuffer) { if (iBuffer == null) iBuffer = new StringBuilder(); iBuffer.append(PREFIX); iBuffer.append(clusterId); iBuffer.append(SEPARATOR); iBuffer.append(clusterPosition); return iBuffer; } public static String generateString(final int iClusterId, final OClusterPosition iPosition) { final StringBuilder buffer = new StringBuilder(12); buffer.append(PREFIX); buffer.append(iClusterId); buffer.append(SEPARATOR); buffer.append(iPosition); return buffer.toString(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof OIdentifiable)) return false; final ORecordId other = (ORecordId) ((OIdentifiable) obj).getIdentity(); if (clusterId != other.clusterId) return false; if (!clusterPosition.equals(other.clusterPosition)) return false; return true; } @Override public int hashCode() { int result = clusterId; result = 31 * result + clusterPosition.hashCode(); return result; } public int compareTo(final OIdentifiable iOther) { if (iOther == this) return 0; if (iOther == null) return 1; final int otherClusterId = iOther.getIdentity().getClusterId(); if (clusterId == otherClusterId) { final OClusterPosition otherClusterPos = iOther.getIdentity().getClusterPosition(); return clusterPosition.compareTo(otherClusterPos); } else if (clusterId > otherClusterId) return 1; return -1; } public int compare(final OIdentifiable iObj1, final OIdentifiable iObj2) { if (iObj1 == iObj2) return 0; if (iObj1 != null) return iObj1.compareTo(iObj2); return -1; } public ORecordId copy() { return new ORecordId(clusterId, clusterPosition); } private void checkClusterLimits() { if (clusterId < -2) throw new ODatabaseException( "RecordId cannot support negative cluster id. You've used: " + clusterId); if (clusterId > CLUSTER_MAX) throw new ODatabaseException( "RecordId cannot support cluster id major than 32767. You've used: " + clusterId); } public ORecordId fromStream(final InputStream iStream) throws IOException { clusterId = OBinaryProtocol.bytes2short(iStream); clusterPosition = OClusterPositionFactory.INSTANCE.fromStream(iStream); return this; } public ORecordId fromStream(final OMemoryStream iStream) { clusterId = iStream.getAsShort(); clusterPosition = OClusterPositionFactory.INSTANCE.fromStream( iStream.getAsByteArrayFixed(OClusterPositionFactory.INSTANCE.getSerializedSize())); return this; } public ORecordId fromStream(final byte[] iBuffer) { if (iBuffer != null) { clusterId = OBinaryProtocol.bytes2short(iBuffer, 0); clusterPosition = OClusterPositionFactory.INSTANCE.fromStream(iBuffer, OBinaryProtocol.SIZE_SHORT); } return this; } public int toStream(final OutputStream iStream) throws IOException { final int beginOffset = OBinaryProtocol.short2bytes((short) clusterId, iStream); iStream.write(clusterPosition.toStream()); return beginOffset; } public int toStream(final OMemoryStream iStream) throws IOException { final int beginOffset = OBinaryProtocol.short2bytes((short) clusterId, iStream); iStream.write(clusterPosition.toStream()); return beginOffset; } public byte[] toStream() { final int serializedSize = OClusterPositionFactory.INSTANCE.getSerializedSize(); byte[] buffer = new byte[OBinaryProtocol.SIZE_SHORT + serializedSize]; OBinaryProtocol.short2bytes((short) clusterId, buffer, 0); System.arraycopy( clusterPosition.toStream(), 0, buffer, OBinaryProtocol.SIZE_SHORT, serializedSize); return buffer; } public int getClusterId() { return clusterId; } public OClusterPosition getClusterPosition() { return clusterPosition; } public void fromString(String iRecordId) { if (iRecordId != null) iRecordId = iRecordId.trim(); if (iRecordId == null || iRecordId.isEmpty()) { clusterId = CLUSTER_ID_INVALID; clusterPosition = CLUSTER_POS_INVALID; return; } if (!OStringSerializerHelper.contains(iRecordId, SEPARATOR)) throw new IllegalArgumentException( "Argument '" + iRecordId + "' is not a RecordId in form of string. Format must be: <cluster-id>:<cluster-position>"); final List<String> parts = OStringSerializerHelper.split(iRecordId, SEPARATOR, PREFIX); if (parts.size() != 2) throw new IllegalArgumentException( "Argument received '" + iRecordId + "' is not a RecordId in form of string. Format must be: #<cluster-id>:<cluster-position>. Example: #3:12"); clusterId = Integer.parseInt(parts.get(0)); checkClusterLimits(); clusterPosition = OClusterPositionFactory.INSTANCE.valueOf(parts.get(1)); } public void copyFrom(final ORID iSource) { if (iSource == null) throw new IllegalArgumentException("Source is null"); clusterId = iSource.getClusterId(); clusterPosition = iSource.getClusterPosition(); } public String next() { return generateString(clusterId, clusterPosition.inc()); } @Override public ORID nextRid() { return new ORecordId(clusterId, clusterPosition.inc()); } public ORID getIdentity() { return this; } @SuppressWarnings("unchecked") public <T extends ORecord<?>> T getRecord() { if (!isValid()) return null; final ODatabaseRecord db = ODatabaseRecordThreadLocal.INSTANCE.get(); if (db == null) throw new ODatabaseException( "No database found in current thread local space. If you manually control databases over threads assure to set the current database before to use it by calling: ODatabaseRecordThreadLocal.INSTANCE.set(db);"); return (T) db.load(this); } }
public void executeSaveRecord( final ORecordInternal<?> iRecord, String iClusterName, final int iVersion, final byte iRecordType) { checkOpeness(); if (!iRecord.isDirty()) return; final ORecordId rid = (ORecordId) iRecord.getIdentity(); if (rid == null) throw new ODatabaseException( "Cannot create record because it has no identity. Probably is not a regular record or contains projections of fields rather than a full record"); setCurrentDatabaseinThreadLocal(); try { final boolean wasNew = rid.isNew(); // STREAM.LENGTH == 0 -> RECORD IN STACK: WILL BE SAVED AFTER byte[] stream = iRecord.toStream(); final boolean isNew = rid.isNew(); if (isNew) // NOTIFY IDENTITY HAS CHANGED iRecord.onBeforeIdentityChanged(rid); else if (stream.length == 0) // ALREADY CREATED AND WAITING FOR THE RIGHT UPDATE (WE'RE IN A GRAPH) return; if (isNew && rid.clusterId < 0) rid.clusterId = iClusterName != null ? getClusterIdByName(iClusterName) : getDefaultClusterId(); if (rid.clusterId > -1 && iClusterName == null) iClusterName = getClusterNameById(rid.clusterId); if (stream != null && stream.length > 0) { if (wasNew) { // CHECK ACCESS ON CLUSTER checkSecurity(ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_CREATE, iClusterName); if (callbackHooks(TYPE.BEFORE_CREATE, iRecord)) // RECORD CHANGED IN TRIGGER, REACQUIRE IT stream = iRecord.toStream(); } else { // CHECK ACCESS ON CLUSTER checkSecurity(ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_UPDATE, iClusterName); if (callbackHooks(TYPE.BEFORE_UPDATE, iRecord)) // RECORD CHANGED IN TRIGGER, REACQUIRE IT stream = iRecord.toStream(); } if (!iRecord.isDirty()) { // RECORD SAVED DURING PREVIOUS STREAMING PHASE: THIS HAPPENS FOR CIRCULAR REFERENCED // RECORDS // ADD/UPDATE IT IN CACHE IF IT'S ACTIVE getLevel1Cache().updateRecord(iRecord); return; } } // GET THE LATEST VERSION. IT COULD CHANGE BECAUSE THE RECORD COULD BE BEEN LINKED FROM OTHERS final int realVersion = iVersion == -1 || !mvcc ? -1 : iRecord.getVersion(); // SAVE IT final long result = underlying.save(rid, stream, realVersion, iRecord.getRecordType()); if (isNew) { // UPDATE INFORMATION: CLUSTER ID+POSITION ((ORecordId) iRecord.getIdentity()).copyFrom(rid); // NOTIFY IDENTITY HAS CHANGED iRecord.onAfterIdentityChanged(iRecord); // UPDATE INFORMATION: CLUSTER ID+POSITION iRecord.fill(rid, 0, stream, stream == null || stream.length == 0); } else { // UPDATE INFORMATION: VERSION iRecord.fill(rid, (int) result, stream, stream == null || stream.length == 0); } callbackHooks(wasNew ? TYPE.AFTER_CREATE : TYPE.AFTER_UPDATE, iRecord); if (stream != null && stream.length > 0) // ADD/UPDATE IT IN CACHE IF IT'S ACTIVE getLevel1Cache().updateRecord(iRecord); } catch (OException e) { // RE-THROW THE EXCEPTION throw e; } catch (Throwable t) { // WRAP IT AS ODATABASE EXCEPTION throw new ODatabaseException( "Error on saving record in cluster #" + iRecord.getIdentity().getClusterId(), t); } }
public <RET extends ORecordInternal<?>> RET executeReadRecord( final ORecordId iRid, ORecordInternal<?> iRecord, final String iFetchPlan, final boolean iIgnoreCache) { checkOpeness(); // setCurrentDatabaseinThreadLocal(); try { checkSecurity( ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_READ, getClusterNameById(iRid.getClusterId())); // SEARCH IN LOCAL TX ORecordInternal<?> record = getTransaction().getRecord(iRid); if (record == null && !iIgnoreCache) // SEARCH INTO THE CACHE record = getLevel1Cache().findRecord(iRid); if (record != null) { OFetchHelper.checkFetchPlanValid(iFetchPlan); callbackHooks(TYPE.BEFORE_READ, record); if (record.getInternalStatus() == ORecordElement.STATUS.NOT_LOADED) record.reload(); callbackHooks(TYPE.AFTER_READ, record); return (RET) record; } final ORawBuffer recordBuffer = underlying.read(iRid, iFetchPlan); if (recordBuffer == null) return null; if (iRecord == null || iRecord.getRecordType() != recordBuffer.recordType) // NO SAME RECORD TYPE: CAN'T REUSE OLD ONE BUT CREATE A NEW ONE FOR IT iRecord = Orient.instance().getRecordFactoryManager().newInstance(recordBuffer.recordType); iRecord.fill(iRid, recordBuffer.version, recordBuffer.buffer, false); callbackHooks(TYPE.BEFORE_READ, iRecord); iRecord.fromStream(recordBuffer.buffer); iRecord.setInternalStatus(ORecordElement.STATUS.LOADED); callbackHooks(TYPE.AFTER_READ, iRecord); if (!iIgnoreCache) getLevel1Cache().updateRecord(iRecord); return (RET) iRecord; } catch (OException e) { // RE-THROW THE EXCEPTION throw e; } catch (Exception e) { // WRAP IT AS ODATABASE EXCEPTION OLogManager.instance() .exception("Error on retrieving record " + iRid, e, ODatabaseException.class); } return null; }
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); } }