/** * Starts the operation if operation with such nonce has not already succeeded. If the operation * is in progress, waits for it to end and checks whether it has succeeded. * * @param group Nonce group. * @param nonce Nonce. * @param stoppable Stoppable that terminates waiting (if any) when the server is stopped. * @return true if the operation has not already succeeded and can proceed; false otherwise. */ public boolean startOperation(long group, long nonce, Stoppable stoppable) throws InterruptedException { if (nonce == HConstants.NO_NONCE) return true; NonceKey nk = new NonceKey(group, nonce); OperationContext ctx = new OperationContext(); while (true) { OperationContext oldResult = nonces.putIfAbsent(nk, ctx); if (oldResult == null) return true; // Collision with some operation - should be extremely rare. synchronized (oldResult) { int oldState = oldResult.getState(); LOG.debug("Conflict detected by nonce: " + nk + ", " + oldResult); if (oldState != OperationContext.WAIT) { return oldState == OperationContext.PROCEED; // operation ended } oldResult.setHasWait(); oldResult.wait(this.conflictWaitIterationMs); // operation is still active... wait and loop if (stoppable.isStopped()) { throw new InterruptedException("Server stopped"); } } } }
@After public void teardown() throws IOException, KeeperException { stopper.stop(""); slm.stop(); TEST_UTIL.shutdownMiniZKCluster(); }
/** @throws java.lang.Exception */ @AfterClass public static void tearDownAfterClass() throws Exception { STOPPABLE.stop("Shutting down"); TEST_UTIL.shutdownMiniCluster(); }