use of com.orientechnologies.orient.core.storage.ORawBuffer in project orientdb by orientechnologies.
the class ODatabaseCompare method compareRecords.
@SuppressFBWarnings("NP_NULL_ON_SOME_PATH")
private boolean compareRecords(ODocumentHelper.RIDMapper ridMapper) {
listener.onMessage("\nStarting deep comparison record by record. This may take a few minutes. Wait please...");
Collection<String> clusterNames1 = makeDbCall(databaseOne, new ODbRelatedCall<Collection<String>>() {
@Override
public Collection<String> call(ODatabaseDocumentInternal database) {
return database.getClusterNames();
}
});
for (final String clusterName : clusterNames1) {
// CHECK IF THE CLUSTER IS INCLUDED
if (includeClusters != null) {
if (!includeClusters.contains(clusterName))
continue;
} else if (excludeClusters != null) {
if (excludeClusters.contains(clusterName))
continue;
}
final int clusterId1 = makeDbCall(databaseOne, new ODbRelatedCall<Integer>() {
@Override
public Integer call(ODatabaseDocumentInternal database) {
return database.getClusterIdByName(clusterName);
}
});
final long[] db1Range = makeDbCall(databaseOne, new ODbRelatedCall<long[]>() {
@Override
public long[] call(ODatabaseDocumentInternal database) {
return database.getStorage().getClusterDataRange(clusterId1);
}
});
final long[] db2Range = makeDbCall(databaseTwo, new ODbRelatedCall<long[]>() {
@Override
public long[] call(ODatabaseDocumentInternal database) {
return database.getStorage().getClusterDataRange(clusterId1);
}
});
final long db1Max = db1Range[1];
final long db2Max = db2Range[1];
databaseOne.activateOnCurrentThread();
final ODocument doc1 = new ODocument();
databaseTwo.activateOnCurrentThread();
final ODocument doc2 = new ODocument();
final ORecordId rid = new ORecordId(clusterId1);
// TODO why this maximums can be different?
final long clusterMax = Math.max(db1Max, db2Max);
final OStorage storage;
ODatabaseDocumentInternal selectedDatabase;
if (clusterMax == db1Max)
selectedDatabase = databaseOne;
else
selectedDatabase = databaseTwo;
OPhysicalPosition[] physicalPositions = makeDbCall(selectedDatabase, new ODbRelatedCall<OPhysicalPosition[]>() {
@Override
public OPhysicalPosition[] call(ODatabaseDocumentInternal database) {
return database.getStorage().ceilingPhysicalPositions(clusterId1, new OPhysicalPosition(0));
}
});
OStorageConfiguration configuration1 = makeDbCall(databaseOne, new ODbRelatedCall<OStorageConfiguration>() {
@Override
public OStorageConfiguration call(ODatabaseDocumentInternal database) {
return database.getStorage().getConfiguration();
}
});
OStorageConfiguration configuration2 = makeDbCall(databaseTwo, new ODbRelatedCall<OStorageConfiguration>() {
@Override
public OStorageConfiguration call(ODatabaseDocumentInternal database) {
return database.getStorage().getConfiguration();
}
});
String storageType1 = makeDbCall(databaseOne, new ODbRelatedCall<String>() {
@Override
public String call(ODatabaseDocumentInternal database) {
return database.getStorage().getType();
}
});
String storageType2 = makeDbCall(databaseTwo, new ODbRelatedCall<String>() {
@Override
public String call(ODatabaseDocumentInternal database) {
return database.getStorage().getType();
}
});
long recordsCounter = 0;
while (physicalPositions.length > 0) {
for (OPhysicalPosition physicalPosition : physicalPositions) {
try {
recordsCounter++;
final long position = physicalPosition.clusterPosition;
rid.setClusterPosition(position);
if (rid.equals(new ORecordId(configuration1.indexMgrRecordId)) && rid.equals(new ORecordId(configuration2.indexMgrRecordId)))
continue;
if (rid.equals(new ORecordId(configuration1.schemaRecordId)) && rid.equals(new ORecordId(configuration2.schemaRecordId)))
continue;
if (rid.getClusterId() == 0 && rid.getClusterPosition() == 0) {
// Skip the compare of raw structure if the storage type are different, due the fact that are different by definition.
if (!storageType1.equals(storageType2))
continue;
}
final ORecordId rid2;
if (ridMapper == null)
rid2 = rid;
else {
final ORID newRid = ridMapper.map(rid);
if (newRid == null)
rid2 = rid;
else
rid2 = new ORecordId(newRid);
}
final ORawBuffer buffer1 = makeDbCall(databaseOne, new ODbRelatedCall<ORawBuffer>() {
@Override
public ORawBuffer call(ODatabaseDocumentInternal database) {
return database.getStorage().readRecord(rid, null, true, false, null).getResult();
}
});
final ORawBuffer buffer2 = makeDbCall(databaseTwo, new ODbRelatedCall<ORawBuffer>() {
@Override
public ORawBuffer call(ODatabaseDocumentInternal database) {
return database.getStorage().readRecord(rid2, null, true, false, null).getResult();
}
});
if (buffer1 == null && buffer2 == null)
// BOTH RECORD NULL, OK
continue;
else if (buffer1 == null && buffer2 != null) {
// REC1 NULL
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " is null in DB1");
++differences;
} else if (buffer1 != null && buffer2 == null) {
// REC2 NULL
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " is null in DB2");
++differences;
} else {
if (buffer1.recordType != buffer2.recordType) {
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " recordType is different: " + (char) buffer1.recordType + " <-> " + (char) buffer2.recordType);
++differences;
}
if (buffer1.buffer == null && buffer2.buffer == null) {
} else if (buffer1.buffer == null && buffer2.buffer != null) {
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " content is different: null <-> " + buffer2.buffer.length);
++differences;
} else if (buffer1.buffer != null && buffer2.buffer == null) {
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " content is different: " + buffer1.buffer.length + " <-> null");
++differences;
} else {
if (buffer1.recordType == ODocument.RECORD_TYPE) {
// DOCUMENT: TRY TO INSTANTIATE AND COMPARE
makeDbCall(databaseOne, new ODocumentHelper.ODbRelatedCall<Object>() {
public Object call(ODatabaseDocumentInternal database) {
doc1.reset();
doc1.fromStream(buffer1.buffer);
return null;
}
});
makeDbCall(databaseTwo, new ODocumentHelper.ODbRelatedCall<Object>() {
public Object call(ODatabaseDocumentInternal database) {
doc2.reset();
doc2.fromStream(buffer2.buffer);
return null;
}
});
if (rid.toString().equals(configuration1.schemaRecordId) && rid.toString().equals(configuration2.schemaRecordId)) {
makeDbCall(databaseOne, new ODocumentHelper.ODbRelatedCall<java.lang.Object>() {
public Object call(ODatabaseDocumentInternal database) {
convertSchemaDoc(doc1);
return null;
}
});
makeDbCall(databaseTwo, new ODocumentHelper.ODbRelatedCall<java.lang.Object>() {
public Object call(ODatabaseDocumentInternal database) {
convertSchemaDoc(doc2);
return null;
}
});
}
if (!ODocumentHelper.hasSameContentOf(doc1, databaseOne, doc2, databaseTwo, ridMapper)) {
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " document content is different");
listener.onMessage("\n--- REC1: " + new String(buffer1.buffer));
listener.onMessage("\n--- REC2: " + new String(buffer2.buffer));
listener.onMessage("\n");
++differences;
}
} else {
if (buffer1.buffer.length != buffer2.buffer.length) {
// CHECK IF THE TRIMMED SIZE IS THE SAME
final String rec1 = new String(buffer1.buffer).trim();
final String rec2 = new String(buffer2.buffer).trim();
if (rec1.length() != rec2.length()) {
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " content length is different: " + buffer1.buffer.length + " <-> " + buffer2.buffer.length);
if (buffer1.recordType == ODocument.RECORD_TYPE)
listener.onMessage("\n--- REC1: " + rec1);
if (buffer2.recordType == ODocument.RECORD_TYPE)
listener.onMessage("\n--- REC2: " + rec2);
listener.onMessage("\n");
++differences;
}
} else {
// CHECK BYTE PER BYTE
for (int b = 0; b < buffer1.buffer.length; ++b) {
if (buffer1.buffer[b] != buffer2.buffer[b]) {
listener.onMessage("\n- ERR: RID=" + clusterId1 + ":" + position + " content is different at byte #" + b + ": " + buffer1.buffer[b] + " <-> " + buffer2.buffer[b]);
listener.onMessage("\n--- REC1: " + new String(buffer1.buffer));
listener.onMessage("\n--- REC2: " + new String(buffer2.buffer));
listener.onMessage("\n");
++differences;
break;
}
}
}
}
}
}
} catch (RuntimeException e) {
OLogManager.instance().error(this, "Error during data comparison of records with rid " + rid);
throw e;
}
}
final OPhysicalPosition[] curPosition = physicalPositions;
physicalPositions = makeDbCall(selectedDatabase, new ODbRelatedCall<OPhysicalPosition[]>() {
@Override
public OPhysicalPosition[] call(ODatabaseDocumentInternal database) {
return database.getStorage().higherPhysicalPositions(clusterId1, curPosition[curPosition.length - 1]);
}
});
if (recordsCounter % 10000 == 0)
listener.onMessage("\n" + recordsCounter + " records were processed for cluster " + clusterName + " ...");
}
listener.onMessage("\nCluster comparison was finished, " + recordsCounter + " records were processed for cluster " + clusterName + " ...");
}
return true;
}
use of com.orientechnologies.orient.core.storage.ORawBuffer in project orientdb by orientechnologies.
the class OAutoMergeRecordConflictStrategy method onUpdate.
@Override
public byte[] onUpdate(OStorage storage, byte iRecordType, final ORecordId rid, final int iRecordVersion, final byte[] iRecordContent, final AtomicInteger iDatabaseVersion) {
if (iRecordType == ODocument.RECORD_TYPE) {
// No need lock, is already inside a lock. Use database to read temporary objects too
OStorageOperationResult<ORawBuffer> res = storage.readRecord(rid, null, false, false, null);
final ODocument storedRecord = new ODocument(rid).fromStream(res.getResult().getBuffer());
ODocument newRecord = (ODocument) ORecordSaveThreadLocal.getLast();
if (newRecord == null || !newRecord.getIdentity().equals(rid))
newRecord = new ODocument(rid).fromStream(iRecordContent);
storedRecord.merge(newRecord, true, true);
iDatabaseVersion.set(Math.max(iDatabaseVersion.get(), iRecordVersion) + 1);
return storedRecord.toStream();
} else
// NO DOCUMENT, CANNOT MERGE SO RELY TO THE VERSION CHECK
checkVersions(rid, iRecordVersion, iDatabaseVersion.get());
return null;
}
use of com.orientechnologies.orient.core.storage.ORawBuffer in project orientdb by orientechnologies.
the class OContentRecordConflictStrategy method onUpdate.
@Override
public byte[] onUpdate(OStorage storage, final byte iRecordType, final ORecordId rid, final int iRecordVersion, final byte[] iRecordContent, final AtomicInteger iDatabaseVersion) {
final boolean hasSameContent;
if (iRecordType == ODocument.RECORD_TYPE) {
// No need lock, is already inside a lock.
OStorageOperationResult<ORawBuffer> res = storage.readRecord(rid, null, false, false, null);
final ODocument storedRecord = new ODocument(rid).fromStream(res.getResult().getBuffer());
final ODocument newRecord = new ODocument().fromStream(iRecordContent);
final ODatabaseDocumentInternal currentDb = ODatabaseRecordThreadLocal.INSTANCE.get();
hasSameContent = ODocumentHelper.hasSameContentOf(storedRecord, currentDb, newRecord, currentDb, null, false);
} else {
// CHECK BYTE PER BYTE
final ORecordAbstract storedRecord = rid.getRecord();
hasSameContent = Arrays.equals(storedRecord.toStream(), iRecordContent);
}
if (hasSameContent)
// OK
iDatabaseVersion.set(Math.max(iDatabaseVersion.get(), iRecordVersion));
else
// NO DOCUMENT, CANNOT MERGE SO RELY TO THE VERSION CHECK
checkVersions(rid, iRecordVersion, iDatabaseVersion.get());
return null;
}
use of com.orientechnologies.orient.core.storage.ORawBuffer in project orientdb by orientechnologies.
the class OCreateRecordTask method executeRecordTask.
@Override
public Object executeRecordTask(final ODistributedRequestId requestId, final OServer iServer, final ODistributedServerManager iManager, final ODatabaseDocumentInternal database) throws Exception {
if (ODistributedServerLog.isDebugEnabled())
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.IN, "Creating record %s/%s v.%d reqId=%s...", database.getName(), rid.toString(), version, requestId);
if (!rid.isPersistent())
throw new ODistributedException("Record " + rid + " has not been saved on owner node first (temporary rid)");
final OPaginatedCluster cluster = (OPaginatedCluster) ODatabaseRecordThreadLocal.INSTANCE.get().getStorage().getClusterById(rid.getClusterId());
final OPaginatedCluster.RECORD_STATUS recordStatus = cluster.getRecordStatus(rid.getClusterPosition());
switch(recordStatus) {
case REMOVED:
// RECYCLE THE RID AND OVERWRITE IT WITH THE NEW CONTENT
ODatabaseRecordThreadLocal.INSTANCE.get().getStorage().recyclePosition(rid, new byte[] {}, version, recordType);
// CREATE A RECORD TO CALL ALL THE HOOKS (LIKE INDEXES FOR UNIQUE CONSTRAINTS)
final ORecord loadedRecordInstance = Orient.instance().getRecordFactoryManager().newInstance(recordType);
ORecordInternal.fill(loadedRecordInstance, rid, version, content, true);
loadedRecordInstance.save();
return new OPlaceholder(rid, loadedRecordInstance.getVersion());
case ALLOCATED:
case PRESENT:
final OStorageOperationResult<ORawBuffer> loadedRecord = ODatabaseRecordThreadLocal.INSTANCE.get().getStorage().readRecord(rid, null, true, false, null);
if (loadedRecord.getResult() != null) {
// ALREADY PRESENT
record = forceUpdate(iManager, database, requestId, loadedRecord.getResult());
return new OPlaceholder(record);
}
case NOT_EXISTENT:
// try {
ORecordId newRid;
do {
getRecord();
if (clusterId > -1)
record.save(database.getClusterNameById(clusterId), true);
else if (rid.getClusterId() != -1)
record.save(database.getClusterNameById(rid.getClusterId()), true);
else
record.save();
newRid = (ORecordId) record.getIdentity();
if (newRid.getClusterPosition() >= rid.getClusterPosition())
break;
// CREATE AN HOLE
record.delete();
record = null;
} while (newRid.getClusterPosition() < rid.getClusterPosition());
if (!rid.equals(newRid)) {
ODistributedServerLog.warn(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.IN, "Record %s has been saved with the RID %s instead of the expected %s reqId=%s", record, newRid, rid, requestId);
// DELETE THE INVALID RECORD FIRST
record.delete();
throw new ODistributedException("Record " + rid + " has been saved with the different RID " + newRid + " on server " + iManager.getLocalNodeName());
}
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.IN, "+-> assigned new rid %s/%s v.%d reqId=%s", database.getName(), rid.toString(), record.getVersion(), requestId);
}
// IMPROVED TRANSPORT BY AVOIDING THE RECORD CONTENT, BUT JUST RID + VERSION
return new OPlaceholder(record);
}
use of com.orientechnologies.orient.core.storage.ORawBuffer in project orientdb by orientechnologies.
the class OCreateRecordTask method getFixTask.
@Override
public ORemoteTask getFixTask(final ODistributedRequest iRequest, ORemoteTask iOriginalTask, final Object iBadResponse, final Object iGoodResponse, final String executorNode, final ODistributedServerManager dManager) {
if (iBadResponse == null || iBadResponse instanceof Throwable)
return null;
final OPlaceholder badResult = (OPlaceholder) iBadResponse;
final OPlaceholder goodResult = (OPlaceholder) iGoodResponse;
ORemoteTask result = null;
if (!badResult.equals(goodResult)) {
// CREATE RECORD FAILED TO HAVE THE SAME RIDS. FORCE REALIGNING OF DATA CLUSTERS
if (badResult.getIdentity().getClusterId() == goodResult.getIdentity().getClusterId() && badResult.getIdentity().getClusterPosition() < goodResult.getIdentity().getClusterPosition()) {
final long minPos = Math.max(badResult.getIdentity().getClusterPosition() - 1, 0);
for (long pos = minPos; pos < goodResult.getIdentity().getClusterPosition(); ++pos) {
// UPDATE INTERMEDIATE RECORDS
final ORecordId toUpdateRid = new ORecordId(goodResult.getIdentity().getClusterId(), pos);
final ORecord toUpdateRecord;
if (dManager.getLocalNodeName().equals(executorNode)) {
// SAME SERVER: LOAD THE RECORD FROM ANOTHER NODE
final ODistributedConfiguration dCfg = dManager.getDatabaseConfiguration(iRequest.getDatabaseName());
final List<String> nodes = dCfg.getServers(ODatabaseRecordThreadLocal.INSTANCE.get().getClusterNameById(clusterId), dManager.getLocalNodeName());
final ODistributedResponse response = dManager.sendRequest(iRequest.getDatabaseName(), null, nodes, new OReadRecordTask(toUpdateRid), dManager.getNextMessageIdCounter(), ODistributedRequest.EXECUTION_MODE.RESPONSE, null, null);
final ORawBuffer remoteReadRecord = (ORawBuffer) response.getPayload();
if (remoteReadRecord != null) {
toUpdateRecord = Orient.instance().getRecordFactoryManager().newInstance(recordType);
ORecordInternal.fill(toUpdateRecord, toUpdateRid, remoteReadRecord.version, remoteReadRecord.buffer, false);
} else
toUpdateRecord = null;
} else
// LOAD IT LOCALLY
toUpdateRecord = toUpdateRid.getRecord();
if (toUpdateRecord != null)
result = new OFixUpdateRecordTask(toUpdateRid, toUpdateRecord.toStream(), toUpdateRecord.getVersion(), ORecordInternal.getRecordType(toUpdateRecord));
}
// CREATE LAST RECORD
result = new OCreateRecordTask((ORecordId) goodResult.getIdentity(), content, version, recordType);
} else if (badResult.getIdentity().getClusterId() == goodResult.getIdentity().getClusterId() && badResult.getIdentity().getClusterPosition() > goodResult.getIdentity().getClusterPosition()) {
} else
// ANY OTHER CASE JUST DELETE IT
result = new OFixCreateRecordTask(new ORecordId(badResult.getIdentity()), badResult.getVersion());
}
return result;
}
Aggregations