/// <exception cref="System.Exception"/> public virtual void TestQuorums() { IDictionary <string, SettableFuture <string> > futures = ImmutableMap.Of("f1", SettableFuture .Create <string>(), "f2", SettableFuture.Create <string>(), "f3", SettableFuture.Create <string>()); QuorumCall <string, string> q = QuorumCall.Create(futures); NUnit.Framework.Assert.AreEqual(0, q.CountResponses()); futures["f1"].Set("first future"); q.WaitFor(1, 0, 0, 100000, "test"); // wait for 1 response q.WaitFor(0, 1, 0, 100000, "test"); // wait for 1 success NUnit.Framework.Assert.AreEqual(1, q.CountResponses()); futures["f2"].SetException(new Exception("error")); NUnit.Framework.Assert.AreEqual(2, q.CountResponses()); futures["f3"].Set("second future"); q.WaitFor(3, 0, 100, 100000, "test"); // wait for 3 responses q.WaitFor(0, 2, 100, 100000, "test"); // 2 successes NUnit.Framework.Assert.AreEqual(3, q.CountResponses()); NUnit.Framework.Assert.AreEqual("f1=first future,f3=second future", Joiner.On("," ).WithKeyValueSeparator("=").Join(new SortedDictionary <string, string>(q.GetResults ()))); try { q.WaitFor(0, 4, 100, 10, "test"); NUnit.Framework.Assert.Fail("Didn't time out waiting for more responses than came back" ); } catch (TimeoutException) { } }
/// <exception cref="System.IO.IOException"/> public virtual bool HasSomeData() { QuorumCall <AsyncLogger, bool> call = loggers.IsFormatted(); try { call.WaitFor(loggers.Size(), 0, 0, HasdataTimeoutMs, "hasSomeData"); } catch (Exception) { throw new IOException("Interrupted while determining if JNs have data"); } catch (TimeoutException) { throw new IOException("Timed out waiting for response from loggers"); } if (call.CountExceptions() > 0) { call.RethrowException("Unable to check if JNs are ready for formatting"); } // If any of the loggers returned with a non-empty manifest, then // we should prompt for format. foreach (bool hasData in call.GetResults().Values) { if (hasData) { return(true); } } // Otherwise, none were formatted, we can safely format. return(false); }
/// <summary>Wait for a quorum of loggers to respond to the given call.</summary> /// <remarks> /// Wait for a quorum of loggers to respond to the given call. If a quorum /// can't be achieved, throws a QuorumException. /// </remarks> /// <param name="q">the quorum call</param> /// <param name="timeoutMs">the number of millis to wait</param> /// <param name="operationName">textual description of the operation, for logging</param> /// <returns>a map of successful results</returns> /// <exception cref="QuorumException">if a quorum doesn't respond with success</exception> /// <exception cref="System.IO.IOException">if the thread is interrupted or times out /// </exception> internal virtual IDictionary <AsyncLogger, V> WaitForWriteQuorum <V>(QuorumCall <AsyncLogger , V> q, int timeoutMs, string operationName) { int majority = GetMajoritySize(); try { q.WaitFor(loggers.Count, majority, majority, timeoutMs, operationName); } catch (Exception) { // either all respond // or we get a majority successes // or we get a majority failures, Sharpen.Thread.CurrentThread().Interrupt(); throw new IOException("Interrupted waiting " + timeoutMs + "ms for a " + "quorum of nodes to respond." ); } catch (TimeoutException) { throw new IOException("Timed out waiting " + timeoutMs + "ms for a " + "quorum of nodes to respond." ); } if (q.CountSuccesses() < majority) { q.RethrowException("Got too many exceptions to achieve quorum size " + GetMajorityString ()); } return(q.GetResults()); }
/// <exception cref="System.IO.IOException"/> public override bool CanRollBack(StorageInfo storage, StorageInfo prevStorage, int targetLayoutVersion) { QuorumCall <AsyncLogger, bool> call = loggers.CanRollBack(storage, prevStorage, targetLayoutVersion ); try { call.WaitFor(loggers.Size(), loggers.Size(), 0, CanRollBackTimeoutMs, "lockSharedStorage" ); if (call.CountExceptions() > 0) { call.RethrowException("Could not check if roll back possible for" + " one or more JournalNodes" ); } // Either they all return the same thing or this call fails, so we can // just return the first result. try { DFSUtil.AssertAllResultsEqual(call.GetResults().Values); } catch (Exception ae) { throw new IOException("Results differed for canRollBack", ae); } foreach (bool result in call.GetResults().Values) { return(result); } } catch (Exception) { throw new IOException("Interrupted waiting for lockSharedStorage() " + "response" ); } catch (TimeoutException) { throw new IOException("Timed out waiting for lockSharedStorage() " + "response"); } throw new Exception("Unreachable code."); }
/// <exception cref="System.IO.IOException"/> public override void DoRollback() { QuorumCall <AsyncLogger, Void> call = loggers.DoRollback(); try { call.WaitFor(loggers.Size(), loggers.Size(), 0, RollBackTimeoutMs, "doRollback"); if (call.CountExceptions() > 0) { call.RethrowException("Could not perform rollback of one or more JournalNodes"); } } catch (Exception) { throw new IOException("Interrupted waiting for doFinalize() response"); } catch (TimeoutException) { throw new IOException("Timed out waiting for doFinalize() response"); } }
/// <exception cref="System.IO.IOException"/> public override void DoUpgrade(Storage storage) { QuorumCall <AsyncLogger, Void> call = loggers.DoUpgrade(storage); try { call.WaitFor(loggers.Size(), loggers.Size(), 0, UpgradeTimeoutMs, "doUpgrade"); if (call.CountExceptions() > 0) { call.RethrowException("Could not perform upgrade of one or more JournalNodes"); } } catch (Exception) { throw new IOException("Interrupted waiting for doUpgrade() response"); } catch (TimeoutException) { throw new IOException("Timed out waiting for doUpgrade() response"); } }
/// <exception cref="System.IO.IOException"/> public override void Format(NamespaceInfo nsInfo) { QuorumCall <AsyncLogger, Void> call = loggers.Format(nsInfo); try { call.WaitFor(loggers.Size(), loggers.Size(), 0, FormatTimeoutMs, "format"); } catch (Exception) { throw new IOException("Interrupted waiting for format() response"); } catch (TimeoutException) { throw new IOException("Timed out waiting for format() response"); } if (call.CountExceptions() > 0) { call.RethrowException("Could not format one or more JournalNodes"); } }
/// <exception cref="System.IO.IOException"/> public override void DiscardSegments(long startTxId) { QuorumCall <AsyncLogger, Void> call = loggers.DiscardSegments(startTxId); try { call.WaitFor(loggers.Size(), loggers.Size(), 0, DiscardSegmentsTimeoutMs, "discardSegments" ); if (call.CountExceptions() > 0) { call.RethrowException("Could not perform discardSegments of one or more JournalNodes" ); } } catch (Exception) { throw new IOException("Interrupted waiting for discardSegments() response"); } catch (TimeoutException) { throw new IOException("Timed out waiting for discardSegments() response"); } }
/// <exception cref="System.IO.IOException"/> public override long GetJournalCTime() { QuorumCall <AsyncLogger, long> call = loggers.GetJournalCTime(); try { call.WaitFor(loggers.Size(), loggers.Size(), 0, GetJournalCtimeTimeoutMs, "getJournalCTime" ); if (call.CountExceptions() > 0) { call.RethrowException("Could not journal CTime for one " + "more JournalNodes"); } // Either they all return the same thing or this call fails, so we can // just return the first result. try { DFSUtil.AssertAllResultsEqual(call.GetResults().Values); } catch (Exception ae) { throw new IOException("Results differed for getJournalCTime", ae); } foreach (long result in call.GetResults().Values) { return(result); } } catch (Exception) { throw new IOException("Interrupted waiting for getJournalCTime() " + "response"); } catch (TimeoutException) { throw new IOException("Timed out waiting for getJournalCTime() " + "response"); } throw new Exception("Unreachable code."); }