public static ActiveTransactionsRecord tryToApplyRemoteCommits(ActiveTransactionsRecord record) { logger.debug("Try to apply remote commits if any."); // avoid locking if queue is empty if (ClusterUtils.getRemoteCommits().isEmpty()) { // logger.debug("No remote commits to apply. Great."); /* we need to always return the most recent committed number: - if inside a commit (already holding the commit lock), this ensures that we're able to detect record advances caused by the processing of the remote commits queue (e.g. while we were waiting to acquire the global lock) - if starting a new transaction, it attempts to improve on the version we see (here it would be acceptable to just return the record had) */ return findActiveRecordForNumber(record, Transaction.getMostRecentCommitedNumber()); } // COMMIT_LOCK.lock(); // change to tryLock to allow the starting transactions to begin without waiting for a long commit (which in fact may already have processed the queue :-)) if (COMMIT_LOCK.tryLock()) { try { return applyRemoteCommits(record); } finally { COMMIT_LOCK.unlock(); } } else { return findActiveRecordForNumber(record, Transaction.getMostRecentCommitedNumber()); } }
private static ActiveTransactionsRecord applyRemoteCommits(ActiveTransactionsRecord record) { int currentCommittedNumber = Transaction.getMostRecentCommitedNumber(); RemoteCommit remoteCommit; while ((remoteCommit = ClusterUtils.getRemoteCommits().poll()) != null) { int txNum = remoteCommit.getTxNumber(); /* this may occur only when booting. It happens when remote commit messages arrive between the time the topic channel is established, but the most recent committed version hasn't been initialized yet. When it gets initialized, it is typically to a greater value than the one from the txs that are enqueued. */ if (txNum <= currentCommittedNumber) { logger.info("Ignoring outdated remote commit txNum={} <= mostRecentNum={}.", txNum, currentCommittedNumber); continue; } if (txNum <= debug_hazelcast_last_commit_seen) { logger.error("The remote commit has a number({}) <= last_seen({})", txNum, debug_hazelcast_last_commit_seen); System.exit(-1); throw new Error("Inconsistent remote commit. This should not happen"); } else { logger.debug("remove me :-)"); debug_hazelcast_last_commit_seen = txNum; } applyRemoteCommit(remoteCommit); currentCommittedNumber = remoteCommit.getTxNumber(); } return findActiveRecordForNumber(record, currentCommittedNumber); }
private void updateServerRecord() { int currentTxNumber = Transaction.getMostRecentCommitedNumber();
@Override public void init(JVSTMConfig jvstmConfig) { JvstmClusterConfig thisConfig = (JvstmClusterConfig) jvstmConfig; logger.info("initializeGroupCommunication()"); ClusterUtils.initializeGroupCommunication(thisConfig); int serverId = obtainNewServerId(); boolean firstNode = (serverId == 0); if (firstNode) { logger.info("This is the first node!"); localInit(thisConfig, serverId, firstNode); // initialize the global lock value to the most recent commit tx number ClusterUtils.initGlobalLockNumber(Transaction.getMostRecentCommitedNumber()); // any necessary distributed communication infrastructures must be configured/set before notifying others to proceed ClusterUtils.notifyStartupComplete(); /* alternatively we can now use the initGlobalLockNumber as the notification mechanism. Otherwise, we're assuming that other nodes will see the correct value in the lock number when they get the message about startup being complete */ } else { logger.info("This is NOT the first node."); ClusterUtils.waitForStartupFromFirstNode(); localInit(thisConfig, serverId, firstNode); } }
int currentCommittedNumber = Transaction.getMostRecentCommitedNumber();