//JAVA TO C# CONVERTER WARNING: 'final' parameters are ignored unless the option to convert to C# 7.2 'in' parameters is selected: //ORIGINAL LINE: private java.util.concurrent.Callable<Void> slaveCommitter(final org.neo4j.kernel.ha.com.master.Slave slave, final long txId, final CompletionNotifier notifier) private Callable <Void> SlaveCommitter(Slave slave, long txId, CompletionNotifier notifier) { return(() => { try { // TODO Bypass the CommitPusher, now that we have a single thread pulling updates on each slave // The CommitPusher is all about batching transaction pushing to slaves, to reduce the overhead // of multiple threads pulling the same transactions on each slave. That should be fine now. // slave.pullUpdates( txId ); _pusher.queuePush(slave, txId); return null; } finally { notifier.Completed(); } }); }
/// /// <param name="txId"> transaction id to replicate </param> /// <param name="authorId"> author id for such transaction id </param> /// <returns> the number of missed replicas (e.g., desired replication factor - number of successful replications) </returns> public virtual int Committed(long txId, int authorId) { int replicationFactor = _desiredReplicationFactor; // If the author is not this instance, then we need to push to one less - the committer already has it bool isAuthoredBySlave = _config.ServerId.toIntegerIndex() != authorId; if (isAuthoredBySlave) { replicationFactor--; } if (replicationFactor == 0) { return(replicationFactor); } ICollection <ReplicationContext> committers = new HashSet <ReplicationContext>(); try { // TODO: Move this logic into {@link CommitPusher} // Commit at the configured amount of slaves in parallel. int successfulReplications = 0; IEnumerator <Slave> slaveList = Filter(_replicationStrategy.prioritize(_slaves.getSlaves()).GetEnumerator(), authorId); CompletionNotifier notifier = new CompletionNotifier(); // Start as many initial committers as needed //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: for (int i = 0; i < replicationFactor && slaveList.hasNext(); i++) { //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: Slave slave = slaveList.next(); Callable <Void> slaveCommitter = slaveCommitter(slave, txId, notifier); committers.Add(new ReplicationContext(_slaveCommitters.submit(slaveCommitter), slave)); } // Wait for them and perhaps spawn new ones for failing committers until we're done // or until we have no more slaves to try out. ICollection <ReplicationContext> toAdd = new List <ReplicationContext>(); ICollection <ReplicationContext> toRemove = new List <ReplicationContext>(); while (committers.Count > 0 && successfulReplications < replicationFactor) { toAdd.Clear(); toRemove.Clear(); foreach (ReplicationContext context in committers) { if (!context.Future.Done) { continue; } if (IsSuccessful(context)) { // This committer was successful, increment counter successfulReplications++; } //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: else if (slaveList.hasNext()) { // This committer failed, spawn another one //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: Slave newSlave = slaveList.next(); Callable <Void> slaveCommitter; try { slaveCommitter = slaveCommitter(newSlave, txId, notifier); } catch (Exception t) { _log.error("Unknown error commit master transaction at slave", t); return(_desiredReplicationFactor); } toAdd.Add(new ReplicationContext(_slaveCommitters.submit(slaveCommitter), newSlave)); } toRemove.Add(context); } // Incorporate the results into committers collection if (toAdd.Count > 0) { committers.addAll(toAdd); } if (toRemove.Count > 0) { //JAVA TO C# CONVERTER TODO TASK: There is no .NET equivalent to the java.util.Collection 'removeAll' method: committers.removeAll(toRemove); } if (committers.Count > 0) // There are committers doing work right now, so go and wait for // any of the committers to be done so that we can reevaluate // the situation again. { notifier.WaitForAnyCompletion(); } } // We did the best we could, have we committed successfully on enough slaves? if (successfulReplications < replicationFactor) { _pushedToTooFewSlaveLogger.info("Transaction " + txId + " couldn't commit on enough slaves, desired " + replicationFactor + ", but could only commit at " + successfulReplications); } return(replicationFactor - successfulReplications); } finally { // Cancel all ongoing committers in the executor foreach (ReplicationContext committer in committers) { committer.Future.cancel(false); } } }