/** Test where two locks are "passing over" to each other the lock ownership. */ @Test public void twoLocksPassingOver() throws Exception { final File lockFile = util.createTempFile(); final LockFile lf1 = new LockFile(lockFile, "lf1".getBytes()); final LockFile lf2 = new LockFile(lockFile, "lf2".getBytes()); try { // lf1 will obtain lock, lf2 should fail assertThat(lf1.lock(), is(true)); assertThat(lf2.lock(), is(false)); // verify who holds the lock assertThat(lf1.readBytes(), equalTo(lf1.getPayload())); // pass over the lock lf1.release(); assertThat(lf2.lock(), is(true)); // verify who holds the lock assertThat(lf2.readBytes(), equalTo(lf2.getPayload())); // repeating same step should be idempotent assertThat(lf1.lock(), is(false)); assertThat(lf2.lock(), is(true)); // verify who holds the lock assertThat(lf2.readBytes(), equalTo(lf2.getPayload())); } finally { // cleanup lf1.release(); lf2.release(); } }
@Override public Integer call() throws Exception { for (int i = 0; i < attempts; i++) { barrier.await(); // start together try { if (lockFile.lock()) { locked++; // verify that content of the file equals to our payload, as we own the lock assertThat(lockFile.readBytes(), equalTo(lockFile.getPayload())); } barrier .await(); // wait for others to attempt, and the one won should hold the lock during // that } catch (Exception e) { // If an exception gets thrown, hang on to it so that it can be reported by the test // Unconventional, but it seems the cyclic barrier rules out normal approach of getting // the exception from Future.get() this.caughtException = e; } finally { lockFile.release(); // the one locked should release for next attempt } } return locked; }