/** * This method calculates the minimum view ID known by the current node. This method is only used * in a clustered cache, and only invoked when either a view change is detected, or a transaction * whose view ID is not the same as the current view ID. * * <p>This method is guarded by minViewRecalculationLock to prevent concurrent updates to the * minimum view ID field. * * @param idOfRemovedTransaction the view ID associated with the transaction that triggered this * recalculation, or -1 if triggered by a view change event. */ @GuardedBy("minViewRecalculationLock") private void calculateMinViewId(int idOfRemovedTransaction) { minViewRecalculationLock.lock(); try { // We should only need to re-calculate the minimum view ID if the transaction being completed // has the same ID as the smallest known transaction ID, to check what the new smallest is. // We do this check // again here, since this is now within a synchronized method. if (idOfRemovedTransaction == -1 || (idOfRemovedTransaction == minTxViewId && idOfRemovedTransaction < currentViewId)) { int minViewIdFound = currentViewId; for (CacheTransaction ct : localTransactions.values()) { int viewId = ct.getViewId(); if (viewId < minViewIdFound) minViewIdFound = viewId; } for (CacheTransaction ct : remoteTransactions.values()) { int viewId = ct.getViewId(); if (viewId < minViewIdFound) minViewIdFound = viewId; } if (minViewIdFound > minTxViewId) { log.tracef("Changing minimum view ID from %s to %s", minTxViewId, minViewIdFound); minTxViewId = minViewIdFound; } else { log.tracef("Minimum view ID still is %s; nothing to change", minViewIdFound); } } } finally { minViewRecalculationLock.unlock(); } }
private void releaseResources(CacheTransaction cacheTransaction) { if (cacheTransaction != null) { if (clustered) { recalculateMinViewIdIfNeeded(cacheTransaction); } log.tracef("Removed %s from transaction table.", cacheTransaction); cacheTransaction.notifyOnTransactionFinished(); } }
private void applyTransactions(Address sender, Collection<TransactionInfo> transactions) { log.debugf( "Applying %d transactions for cache %s transferred from node %s", transactions.size(), cacheName, sender); if (isTransactional) { for (TransactionInfo transactionInfo : transactions) { CacheTransaction tx = transactionTable.getLocalTransaction(transactionInfo.getGlobalTransaction()); if (tx == null) { tx = transactionTable.getRemoteTransaction(transactionInfo.getGlobalTransaction()); if (tx == null) { tx = transactionTable.getOrCreateRemoteTransaction( transactionInfo.getGlobalTransaction(), transactionInfo.getModifications()); ((RemoteTransaction) tx).setMissingLookedUpEntries(true); } } for (Object key : transactionInfo.getLockedKeys()) { tx.addBackupLockForKey(key); } } } }
private EntryVersionsMap clusteredCreateNewVersionsAndCheckForWriteSkews( VersionGenerator versionGenerator, TxInvocationContext context, VersionedPrepareCommand prepareCommand) { // Perform a write skew check on mapped entries. EntryVersionsMap uv = performWriteSkewCheckAndReturnNewVersions( prepareCommand, dataContainer, persistenceManager, versionGenerator, context, keySpecificLogic, timeService); CacheTransaction cacheTransaction = context.getCacheTransaction(); EntryVersionsMap uvOld = cacheTransaction.getUpdatedEntryVersions(); if (uvOld != null && !uvOld.isEmpty()) { uvOld.putAll(uv); uv = uvOld; } cacheTransaction.setUpdatedEntryVersions(uv); return (uv.isEmpty()) ? null : uv; }
protected final void recalculateMinViewIdIfNeeded(CacheTransaction removedTransaction) { if (removedTransaction == null) throw new IllegalArgumentException("Transaction cannot be null!"); if (currentViewId != CACHE_STOPPED_VIEW_ID) { // Assume that we only get here if we are clustered. int removedTransactionViewId = removedTransaction.getViewId(); if (removedTransactionViewId < minTxViewId) { log.tracef( "A transaction has a view ID (%s) that is smaller than the smallest transaction view ID (%s) this node knows about! This can happen if a concurrent thread recalculates the minimum view ID after the current transaction has been removed from the transaction table.", removedTransactionViewId, minTxViewId); } else if (removedTransactionViewId == minTxViewId && removedTransactionViewId < currentViewId) { // We should only need to re-calculate the minimum view ID if the transaction being // completed // has the same ID as the smallest known transaction ID, to check what the new smallest is, // and this is // not the current view ID. calculateMinViewId(removedTransactionViewId); } } }
private static int preComputeHashCode(final CacheTransaction cacheTx) { return 31 + cacheTx.hashCode(); }