@Override protected Transaction commitAndBeginTx(boolean readOnly) { commitTx(true); return beginWithActiveRecord(readOnly, null); }
private void manualAbort() { ReadWriteTransaction parent = getRWParent(); while (parent != null) { for (ParallelNestedTransaction mergedIntoParent : parent.mergedTxs) { for (VBox vboxMergedIntoParent : mergedIntoParent.boxesWrittenInPlace) { revertOverwrite(vboxMergedIntoParent); } } for (VBox vboxMergedIntoParent : parent.boxesWrittenInPlace) { revertOverwrite(vboxMergedIntoParent); } parent = parent.getRWParent(); } this.orec.version = OwnershipRecord.ABORTED; for (ReadWriteTransaction child : mergedTxs) { child.orec.version = OwnershipRecord.ABORTED; } super.boxesWritten = null; int i = 0; for (ReadBlock block : globalReads) { block.free = true; i++; } blocksFree.get().addAndGet(i); this.globalReads = null; this.nestedReads = null; super.mergedTxs = null; }
protected void validateNestedRead(Map.Entry<VBox, InplaceWrite> read) { InplaceWrite inplaceRead = read.getValue(); InplaceWrite iter = read.getKey().inplace; do { if (iter == inplaceRead) { break; } int maxVersion = retrieveAncestorVersion(iter.orec.owner); if (maxVersion >= 0) { manualAbort(); TransactionSignaller.SIGNALLER.signalCommitFail(iter.orec.owner); } iter = iter.next; } while (iter != null); }
@Override protected void snapshotValidation(int lastSeenNumber) { if (retrieveAncestorVersion(parent) == lastSeenNumber) { return; } for (Map.Entry<VBox, InplaceWrite> read : nestedReads.entrySet()) { validateNestedRead(read); } for (ParallelNestedTransaction mergedTx : mergedTxs) { for (Map.Entry<VBox, InplaceWrite> read : mergedTx.nestedReads.entrySet()) { validateNestedRead(read); } } if (!this.globalReads.isEmpty()) { validateGlobalReads(globalReads, next); } for (ParallelNestedTransaction mergedTx : mergedTxs) { if (!mergedTx.globalReads.isEmpty()) { validateGlobalReads(mergedTx.globalReads, mergedTx.next); } } }
@Override protected void tryCommit() { ReadWriteTransaction parent = getRWParent(); NestedCommitRecord lastSeen; NestedCommitRecord newCommit; do { lastSeen = helpCommitAll(parent.nestedCommitQueue); snapshotValidation(lastSeen.commitNumber); Cons<VArrayEntry<?>> varrayReadsToPropagate = validateNestedArrayReads(); newCommit = new NestedCommitRecord(this, this.mergedTxs, parent.mergedTxs, varrayReadsToPropagate, arrayWrites, arrayWritesCount, lastSeen.commitNumber + 1); } while (!lastSeen.next.compareAndSet(null, newCommit)); lastSeen = parent.nestedCommitQueue; while ((lastSeen != null) && (lastSeen.commitNumber <= newCommit.commitNumber)) { if (!lastSeen.recordCommitted) { lastSeen.helpCommit(); parent.nestedCommitQueue = lastSeen; } lastSeen = lastSeen.next.get(); } }
value = readGlobal(vbox); return value; int versionOnAnc = retrieveAncestorVersion(inplaceOrec.owner); if (versionOnAnc >= 0) { if (entryNestedVersion > versionOnAnc) { manualAbort(); TransactionSignaller.SIGNALLER.signalCommitFail(inplaceOrec.owner); value = readGlobal(vbox); return value;
protected Cons<VArrayEntry<?>> validateNestedArrayReads() { Map<VArrayEntry<?>, VArrayEntry<?>> parentArrayWrites = getRWParent().arrayWrites; Cons<VArrayEntry<?>> parentArrayReads = getRWParent().arraysRead; int maxVersionOnParent = retrieveAncestorVersion(parent); for (VArrayEntry<?> entry : arraysRead) { // If the read was performed on an ancestor of the parent, then // propagate it for further validation if (entry.owner != parent) { parentArrayReads = parentArrayReads.cons(entry); } synchronized (parent) { if (parentArrayWrites != EMPTY_MAP) { // Verify if the parent contains a more recent write for the // read that we performed somewhere in our ancestors VArrayEntry<?> parentWrite = parentArrayWrites.get(entry); if (parentWrite == null) { continue; } if (parentWrite.nestedVersion > maxVersionOnParent) { TransactionSignaller.SIGNALLER.signalCommitFail(parent); } } } } return parentArrayReads; } }
ReadWriteTransaction parent = committer.getRWParent();
private Transaction retrieveLowestCommonAncestor(Transaction tx) { Transaction current = tx; while (current != null) { if (retrieveAncestorVersion(current) >= 0) { return current; } current = current.parent; } return null; }
@Override public void abortTx() { if (this.orec.version != OwnershipRecord.ABORTED) { manualAbort(); } Transaction.current.set(parent); }
protected void cleanUp() { if (mergedTxs != Cons.<ParallelNestedTransaction> empty()) { for (ParallelNestedTransaction mergedTx : mergedTxs) { mergedTx.cleanUp(); } mergedTxs = null; } }
@Override public Transaction makeParallelNestedTransaction(boolean readOnly) { if (readOnly) { return new ParallelNestedReadOnlyTransaction(this); } else { return new ParallelNestedTransaction(this); } }
@Override protected <T> T getLocalArrayValue(VArrayEntry<T> entry) { if (this.arrayWrites != EMPTY_MAP) { VArrayEntry<T> wsEntry = (VArrayEntry<T>) this.arrayWrites.get(entry); if (wsEntry != null) { return (wsEntry.getWriteValue() == null ? (T) NULL_VALUE : wsEntry.getWriteValue()); } } ReadWriteTransaction iter = getRWParent(); while (iter != null) { synchronized (iter) { if (iter.arrayWrites != EMPTY_MAP) { VArrayEntry<T> wsEntry = (VArrayEntry<T>) iter.arrayWrites.get(entry); if (wsEntry == null) { iter = iter.getRWParent(); continue; } if (wsEntry.nestedVersion <= retrieveAncestorVersion(iter)) { this.arraysRead = this.arraysRead.cons(entry); entry.setReadOwner(iter); return (wsEntry.getWriteValue() == null ? (T) NULL_VALUE : wsEntry.getWriteValue()); } else { TransactionSignaller.SIGNALLER.signalCommitFail(iter); } } } iter = iter.getRWParent(); } return null; }
public void helpCommit() { ReadWriteTransaction parent = committer.getRWParent(); Cons<ParallelNestedTransaction> currentParentOrecs = parent.mergedTxs; if (currentParentOrecs == expectedParentOrecs) { committer.orec.nestedVersion = commitNumber; committer.orec.owner = parent; currentParentOrecs = currentParentOrecs.cons(committer); for (ParallelNestedTransaction childrenCommit : childrenToPropagate) { childrenCommit.orec.nestedVersion = commitNumber; childrenCommit.orec.owner = parent; currentParentOrecs = currentParentOrecs.cons(childrenCommit); } propagateVArraysFootprint(); parent.CASmergedTxs(expectedParentOrecs, currentParentOrecs); } }
protected void validateGlobalReads(Cons<ReadBlock> reads, int startIdx) { VBox[] array = reads.first().entries; // the first may not be full for (int i = startIdx + 1; i < array.length; i++) { InplaceWrite iter = array[i].inplace; do { int maxVersion = retrieveAncestorVersion(iter.orec.owner); if (maxVersion >= 0) { manualAbort(); TransactionSignaller.SIGNALLER.signalCommitFail(iter.orec.owner); } iter = iter.next; } while (iter != null); } // the rest are full for (ReadBlock block : reads.rest()) { array = block.entries; for (int i = 0; i < array.length; i++) { InplaceWrite iter = array[i].inplace; do { int maxVersion = retrieveAncestorVersion(iter.orec.owner); if (maxVersion >= 0) { manualAbort(); TransactionSignaller.SIGNALLER.signalCommitFail(iter.orec.owner); } iter = iter.next; } while (iter != null); } } }
if (retrieveAncestorVersion(currentOwner.owner) >= 0) { if (vbox.CASinplace(inplaceWrite, new InplaceWrite<T>(this.orec, (value == null ? (T) NULL_VALUE : value), inplaceWrite))) { manualAbort(); throw EXECUTE_SEQUENTIALLY_EXCEPTION;