use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OTransactionOptimistic method invokeCallbacks.
private void invokeCallbacks() {
if (recordCreatedCallback != null || recordUpdatedCallback != null) {
for (ORecordOperation operation : allEntries.values()) {
final ORecord record = operation.getRecord();
final ORID identity = record.getIdentity();
if (operation.type == ORecordOperation.CREATED && recordCreatedCallback != null)
recordCreatedCallback.call(new ORecordId(identity), identity.getClusterPosition());
else if (operation.type == ORecordOperation.UPDATED && recordUpdatedCallback != null)
recordUpdatedCallback.call(new ORecordId(identity), record.getVersion());
}
}
}
use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OTransactionRealAbstract method updateIdentityAfterCommit.
public void updateIdentityAfterCommit(final ORID oldRid, final ORID newRid) {
if (oldRid.equals(newRid))
// NO CHANGE, IGNORE IT
return;
// XXX: Identity update may mutate the index keys, so we have to identify and reinsert potentially affected index keys to keep
// the OTransactionIndexChanges.changesPerKey in a consistent state.
final List<KeyChangesUpdateRecord> keyRecordsToReinsert = new ArrayList<KeyChangesUpdateRecord>();
final OIndexManager indexManager = getDatabase().getMetadata().getIndexManager();
for (Entry<String, OTransactionIndexChanges> entry : indexEntries.entrySet()) {
final OIndex<?> index = indexManager.getIndex(entry.getKey());
if (index == null)
throw new OTransactionException("Cannot find index '" + entry.getValue() + "' while committing transaction");
final Dependency[] fieldRidDependencies = getIndexFieldRidDependencies(index);
if (!isIndexMayDependOnRids(fieldRidDependencies))
continue;
final OTransactionIndexChanges indexChanges = entry.getValue();
for (final Iterator<OTransactionIndexChangesPerKey> iterator = indexChanges.changesPerKey.values().iterator(); iterator.hasNext(); ) {
final OTransactionIndexChangesPerKey keyChanges = iterator.next();
if (isIndexKeyMayDependOnRid(keyChanges.key, oldRid, fieldRidDependencies)) {
keyRecordsToReinsert.add(new KeyChangesUpdateRecord(keyChanges, indexChanges));
iterator.remove();
}
}
}
// Update the identity.
final ORecordOperation rec = getRecordEntry(oldRid);
if (rec != null) {
updatedRids.put(newRid.copy(), oldRid.copy());
if (!rec.getRecord().getIdentity().equals(newRid)) {
ORecordInternal.onBeforeIdentityChanged(rec.getRecord());
final ORecordId recordId = (ORecordId) rec.getRecord().getIdentity();
if (recordId == null) {
ORecordInternal.setIdentity(rec.getRecord(), new ORecordId(newRid));
} else {
recordId.setClusterPosition(newRid.getClusterPosition());
recordId.setClusterId(newRid.getClusterId());
}
ORecordInternal.onAfterIdentityChanged(rec.getRecord());
}
}
for (KeyChangesUpdateRecord record : keyRecordsToReinsert) record.indexChanges.changesPerKey.put(record.keyChanges.key, record.keyChanges);
// Update the indexes.
final List<OTransactionRecordIndexOperation> transactionIndexOperations = recordIndexOperations.get(translateRid(oldRid));
if (transactionIndexOperations != null) {
for (final OTransactionRecordIndexOperation indexOperation : transactionIndexOperations) {
OTransactionIndexChanges indexEntryChanges = indexEntries.get(indexOperation.index);
if (indexEntryChanges == null)
continue;
final OTransactionIndexChangesPerKey keyChanges = indexEntryChanges.changesPerKey.get(indexOperation.key);
if (keyChanges != null)
updateChangesIdentity(oldRid, newRid, keyChanges);
}
}
}
use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OAbstractPaginatedStorage method commit.
public List<ORecordOperation> commit(final OTransaction clientTx, Runnable callback) {
checkOpeness();
checkLowDiskSpaceFullCheckpointRequestsAndBackgroundDataFlushExceptions();
txBegun.incrementAndGet();
final ODatabaseDocumentInternal databaseRecord = (ODatabaseDocumentInternal) clientTx.getDatabase();
final OIndexManagerProxy indexManager = databaseRecord.getMetadata().getIndexManager();
final TreeMap<String, OTransactionIndexChanges> indexesToCommit = getSortedIndexEntries(clientTx);
final Map<ORecordOperation, Integer> clusterOverrides = new IdentityHashMap<ORecordOperation, Integer>();
databaseRecord.getMetadata().makeThreadLocalSchemaSnapshot();
if (OLogManager.instance().isDebugEnabled())
OLogManager.instance().debug(this, "%d Committing transaction %d on database '%s' (items=%d)...", Thread.currentThread().getId(), clientTx.getId(), databaseRecord.getName(), clientTx.getEntryCount());
final Iterable<ORecordOperation> entries = (Iterable<ORecordOperation>) clientTx.getAllRecordEntries();
final TreeMap<Integer, OCluster> clustersToLock = new TreeMap<Integer, OCluster>();
final Set<ORecordOperation> newRecords = new TreeSet<ORecordOperation>(new Comparator<ORecordOperation>() {
@Override
public int compare(final ORecordOperation o1, final ORecordOperation o2) {
return o1.getRecord().getIdentity().compareTo(o2.getRecord().getIdentity());
}
});
for (ORecordOperation txEntry : entries) {
if (txEntry.type == ORecordOperation.CREATED || txEntry.type == ORecordOperation.UPDATED) {
final ORecord record = txEntry.getRecord();
if (record instanceof ODocument)
((ODocument) record).validate();
}
if (txEntry.type == ORecordOperation.UPDATED || txEntry.type == ORecordOperation.DELETED) {
final int clusterId = txEntry.getRecord().getIdentity().getClusterId();
clustersToLock.put(clusterId, getClusterById(clusterId));
} else if (txEntry.type == ORecordOperation.CREATED) {
newRecords.add(txEntry);
final ORecord record = txEntry.getRecord();
final ORID rid = record.getIdentity();
int clusterId = rid.getClusterId();
if (record.isDirty() && clusterId == ORID.CLUSTER_ID_INVALID && record instanceof ODocument) {
// TRY TO FIX CLUSTER ID TO THE DEFAULT CLUSTER ID DEFINED IN SCHEMA CLASS
final OImmutableClass class_ = ODocumentInternal.getImmutableSchemaClass(((ODocument) record));
if (class_ != null) {
clusterId = class_.getClusterForNewInstance((ODocument) record);
clusterOverrides.put(txEntry, clusterId);
}
}
clustersToLock.put(clusterId, getClusterById(clusterId));
}
}
final List<ORecordOperation> result = new ArrayList<ORecordOperation>();
final List<Lock[]> indexKeyLockList = new ArrayList<Lock[]>(indexesToCommit.size());
stateLock.acquireReadLock();
try {
try {
try {
checkOpeness();
lockIndexKeys(indexManager, indexesToCommit, indexKeyLockList);
makeStorageDirty();
startStorageTx(clientTx);
lockClusters(clustersToLock);
lockRidBags(clustersToLock, indexesToCommit);
lockIndexes(indexesToCommit);
Map<ORecordOperation, OPhysicalPosition> positions = new IdentityHashMap<ORecordOperation, OPhysicalPosition>();
for (ORecordOperation txEntry : newRecords) {
ORecord rec = txEntry.getRecord();
if (rec.isDirty()) {
ORecordId rid = (ORecordId) rec.getIdentity().copy();
ORecordId oldRID = rid.copy();
final Integer clusterOverride = clusterOverrides.get(txEntry);
final int clusterId = clusterOverride == null ? rid.getClusterId() : clusterOverride;
final OCluster cluster = getClusterById(clusterId);
OPhysicalPosition ppos = cluster.allocatePosition(ORecordInternal.getRecordType(rec));
rid.setClusterId(cluster.getId());
if (rid.getClusterPosition() > -1) {
// RECORD HAVING A HIGHER CLUSTER POSITION
while (rid.getClusterPosition() > ppos.clusterPosition) {
ppos = cluster.allocatePosition(ORecordInternal.getRecordType(rec));
}
if (rid.getClusterPosition() != ppos.clusterPosition)
throw new OConcurrentCreateException(rid, new ORecordId(rid.getClusterId(), ppos.clusterPosition));
}
positions.put(txEntry, ppos);
rid.setClusterPosition(ppos.clusterPosition);
clientTx.updateIdentityAfterCommit(oldRID, rid);
}
}
for (ORecordOperation txEntry : entries) {
commitEntry(txEntry, positions.get(txEntry));
result.add(txEntry);
}
commitIndexes(indexesToCommit);
endStorageTx();
OTransactionAbstract.updateCacheFromEntries(clientTx, entries, true);
txCommit.incrementAndGet();
} catch (IOException ioe) {
makeRollback(clientTx, ioe);
} catch (RuntimeException e) {
makeRollback(clientTx, e);
} finally {
unlockIndexKeys(indexesToCommit, indexKeyLockList);
transaction.set(null);
}
} finally {
databaseRecord.getMetadata().clearThreadLocalSchemaSnapshot();
}
} finally {
stateLock.releaseReadLock();
}
if (OLogManager.instance().isDebugEnabled())
OLogManager.instance().debug(this, "%d Committed transaction %d on database '%s' (result=%s)", Thread.currentThread().getId(), clientTx.getId(), databaseRecord.getName(), result);
return result;
}
use of com.orientechnologies.orient.core.db.record.ORecordOperation in project orientdb by orientechnologies.
the class OLiveQueryTest method testLiveInsert.
@Test
public void testLiveInsert() throws InterruptedException {
ODatabaseDocumentTx db = new ODatabaseDocumentTx("memory:OLiveQueryTest");
db.activateOnCurrentThread();
db.create();
try {
db.getMetadata().getSchema().createClass("test");
db.getMetadata().getSchema().createClass("test2");
MyLiveQueryListener listener = new MyLiveQueryListener();
OResultSet<ODocument> tokens = db.query(new OLiveQuery<ODocument>("live select from test", listener));
Assert.assertEquals(tokens.size(), 1);
ODocument tokenDoc = tokens.get(0);
Integer token = tokenDoc.field("token");
Assert.assertNotNull(token);
db.command(new OCommandSQL("insert into test set name = 'foo', surname = 'bar'")).execute();
db.command(new OCommandSQL("insert into test set name = 'foo', surname = 'baz'")).execute();
db.command(new OCommandSQL("insert into test2 set name = 'foo'")).execute();
latch.await(1, TimeUnit.MINUTES);
db.command(new OCommandSQL("live unsubscribe " + token)).execute();
db.command(new OCommandSQL("insert into test set name = 'foo', surname = 'bax'")).execute();
db.command(new OCommandSQL("insert into test2 set name = 'foo'"));
db.command(new OCommandSQL("insert into test set name = 'foo', surname = 'baz'")).execute();
Assert.assertEquals(listener.ops.size(), 2);
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 OLiveCommandResultListenerTest method testSimpleMessageSend.
@Test
public void testSimpleMessageSend() throws IOException {
OLiveCommandResultListener listener = new OLiveCommandResultListener(server, connection, 20, new TestResultListener());
ORecordOperation op = new ORecordOperation(new ODocument(), ORecordOperation.CREATED);
listener.onLiveResult(10, op);
Mockito.verify(channelBinary, VerificationModeFactory.atLeastOnce()).writeBytes(Mockito.any(byte[].class));
}
Aggregations