protected void validateCommitAndEnqueue(ActiveTransactionsRecord lastCheck) { ProcessPerTxBoxesTransaction commitTx = speculatePerTxBoxes(lastCheck.transactionNumber); WriteSet writeSet = makeWriteSet(); writeSet.addPerTxBoxesWrites(commitTx.specWriteSet); assignCommitRecord(lastCheck.transactionNumber + 1, writeSet); enqueueValidCommit(lastCheck, writeSet); // At this point we no longer need the values we wrote in the VBox's // tempValue slot, so we update the ownership record's version to // allow reuse of the slot. updateOrecVersion(); // after validating, upgrade the transaction's valid read state // upgradeTx(lastValid); }
@Override protected void tryCommit() { if (isWriteTransaction()) { validate(); ensureCommitStatus(); upgradeTx(getCommitTxRecord()); } }
@Override public Transaction makeTopLevelTransaction(ActiveTransactionsRecord record) { return new TopLevelTransaction(record); }
/** * Enqueue a valid commit (just after the record lastCheck). If enqueue fails then, revalidate, upgrade the transaction and retry to enqueue. * * @param lastCheck The last record up to where validation succeeded. * @param writeSet The writeSet of this commit. * @return */ /* This code was extracted from validateCommitAndEnqueue, to enable overriding it in subclasses that wish to reuse the remainder of the algorithm coded in validateCommitAndEnqueue. */ protected void enqueueValidCommit(ActiveTransactionsRecord lastCheck, WriteSet writeSet) { ProcessPerTxBoxesTransaction commitTx; while (!lastCheck.trySetNext(getCommitTxRecord())) { // Failed enqueue, at least some other transaction succeeded in the meantime lastCheck = helpCommitAll(); snapshotValidation(lastCheck.transactionNumber); // Re-execute the perTxBoxes speculatively. They are supposed to be a point of contention, thus // any validation to check if previous speculative reads are still up-to-date should most of the time // lead to the conclusion that they are not. This way we avoid registering those reads and skip the validation. commitTx = speculatePerTxBoxes(lastCheck.transactionNumber); writeSet.addPerTxBoxesWrites(commitTx.specWriteSet); assignCommitRecord(lastCheck.transactionNumber + 1, writeSet); } }
protected void ensureCommitStatus() { ActiveTransactionsRecord recordToCommit = Transaction.mostRecentCommittedRecord.getNext(); while ((recordToCommit != null) && (recordToCommit.transactionNumber <= getCommitTxRecord().transactionNumber)) { helpCommit(recordToCommit); recordToCommit = recordToCommit.getNext(); } }
protected ActiveTransactionsRecord helpCommitAll() { ActiveTransactionsRecord lastSeenCommitted = Transaction.mostRecentCommittedRecord; ActiveTransactionsRecord recordToCommit = lastSeenCommitted.getNext(); while (recordToCommit != null) { helpCommit(recordToCommit); lastSeenCommitted = recordToCommit; recordToCommit = recordToCommit.getNext(); } return lastSeenCommitted; }
@Override protected Transaction commitAndBeginTx(boolean readOnly) { context().inCommitAndBegin = true; try { commitTx(true); } finally { context().inCommitAndBegin = false; } // at this point activeTxRecord and commitTxRecord are the same... return Transaction.beginWithActiveRecord(readOnly, this.activeTxRecord); }
@Override protected void assignCommitRecord(int txNumber, WriteSet writeSet) { // Must set the correct commit number **BEFORE** setting the valid status super.assignCommitRecord(txNumber, writeSet); this.commitRequest.setValid(); }
@Override protected void validate() { logger.debug("Validating commit request: {}", this.commitRequest.getId()); // // some other helper may have already done the work for us // ValidationStatus validationStatus = this.commitRequest.getValidationStatus(); // boolean alreadyValidated = validationStatus != ValidationStatus.UNSET; // // if (alreadyValidated) { // logger.debug("Commit request {} is already {}", this.commitRequest.getId(), // (validationStatus == ValidationStatus.VALID ? "VALID" : "INVALID")); // return; // } super.validate(); }
@Override public <T> T getBoxValue(VBox<T> vbox) { return super.getBoxValue(vbox); }
/** * Help to commit a transaction as much as possible. * * @param recordToCommit * the record to help commit */ protected void helpCommit(ActiveTransactionsRecord recordToCommit) { if (!recordToCommit.isCommitted()) { // We must check whether recordToCommit.getWriteSet() could, in the // meanwhile, have // become null. This occurs when this recordToCommit was already // committed and even // cleaned while this thread was waiting to be scheduled WriteSet writeSet = recordToCommit.getWriteSet(); if (writeSet != null) { writeSet.helpWriteBack(recordToCommit.transactionNumber); // the thread that commits the last body will handle the rest of // the commit finishCommit(recordToCommit); } } }
@Override protected void helpCommit(ActiveTransactionsRecord recordToCommit) { if (!recordToCommit.isCommitted()) { logger.debug("Helping to commit version {}", recordToCommit.transactionNumber); int txVersion = recordToCommit.transactionNumber; UUID commitId = CommitOnlyTransaction.txVersionToCommitIdMap.get(txVersion); if (commitId != null) { // may be null if it was already persisted JvstmLockFreeBackEnd.getInstance().getRepository().mapTxVersionToCommitId(txVersion, commitId); CommitOnlyTransaction.txVersionToCommitIdMap.remove(txVersion); } super.helpCommit(recordToCommit); } else { logger.debug("Version {} was already fully committed", recordToCommit.transactionNumber); } }