public static void main(String[] args) throws Throwable { final ReentrantLock lock = new ReentrantLock(); lock.lock(); final ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock(); final ReentrantReadWriteLock.ReadLock readLock = rwlock.readLock(); final ReentrantReadWriteLock.WriteLock writeLock = rwlock.writeLock(); rwlock.writeLock().lock(); final BlockingQueue<Object> q = new LinkedBlockingQueue<Object>(); final Semaphore fairSem = new Semaphore(0, true); final Semaphore unfairSem = new Semaphore(0, false); // final int threads = // rnd.nextInt(Runtime.getRuntime().availableProcessors() + 1) + 1; final int threads = 3; // On Linux, this test runs very slowly for some reason, // so use a smaller number of iterations. // Solaris can handle 1 << 18. // On the other hand, jmap is much slower on Solaris... final int iterations = 1 << 8; final CyclicBarrier cb = new CyclicBarrier(threads + 1); for (int i = 0; i < threads; i++) new Thread() { public void run() { try { final Random rnd = new Random(); for (int j = 0; j < iterations; j++) { if (j == iterations / 10 || j == iterations - 1) { cb.await(); // Quiesce cb.await(); // Resume } // int t = rnd.nextInt(2000); int t = rnd.nextInt(900); check(!lock.tryLock(t, NANOSECONDS)); check(!readLock.tryLock(t, NANOSECONDS)); check(!writeLock.tryLock(t, NANOSECONDS)); equal(null, q.poll(t, NANOSECONDS)); check(!fairSem.tryAcquire(t, NANOSECONDS)); check(!unfairSem.tryAcquire(t, NANOSECONDS)); } } catch (Throwable t) { unexpected(t); } } }.start(); cb.await(); // Quiesce rendezvousChild(); // Measure cb.await(); // Resume cb.await(); // Quiesce rendezvousChild(); // Measure cb.await(); // Resume System.exit(failed); }
@Override public void setChainHead(StoredBlock chainHead) throws BlockStoreException { final MappedByteBuffer buffer = this.buffer; if (buffer == null) throw new BlockStoreException("Store closed"); lock.lock(); try { lastChainHead = chainHead; byte[] headHash = chainHead.getHeader().getHash().getBytes(); buffer.position(8); buffer.put(headHash); } finally { lock.unlock(); } }
private void initNewStore(NetworkParameters params) throws Exception { byte[] header; header = HEADER_MAGIC.getBytes("US-ASCII"); buffer.put(header); // Insert the genesis block. lock.lock(); try { setRingCursor(buffer, FILE_PROLOGUE_BYTES); } finally { lock.unlock(); } Block genesis = params.getGenesisBlock().cloneAsHeader(); StoredBlock storedGenesis = new StoredBlock(genesis, genesis.getWork(), 0); put(storedGenesis); setChainHead(storedGenesis); }
@Override @Nullable public StoredBlock get(Sha256Hash hash) throws BlockStoreException { final MappedByteBuffer buffer = this.buffer; if (buffer == null) throw new BlockStoreException("Store closed"); lock.lock(); try { StoredBlock cacheHit = blockCache.get(hash); if (cacheHit != null) return cacheHit; if (notFoundCache.get(hash) != null) return null; // Starting from the current tip of the ring work backwards until we have either found the // block or // wrapped around. int cursor = getRingCursor(buffer); final int startingPoint = cursor; final int fileSize = getFileSize(); final byte[] targetHashBytes = hash.getBytes(); byte[] scratch = new byte[32]; do { cursor -= RECORD_SIZE; if (cursor < FILE_PROLOGUE_BYTES) { // We hit the start, so wrap around. cursor = fileSize - RECORD_SIZE; } // Cursor is now at the start of the next record to check, so read the hash and compare it. buffer.position(cursor); buffer.get(scratch); if (Arrays.equals(scratch, targetHashBytes)) { // Found the target. StoredBlock storedBlock = StoredBlock.deserializeCompact(params, buffer); blockCache.put(hash, storedBlock); return storedBlock; } } while (cursor != startingPoint); // Not found. notFoundCache.put(hash, notFoundMarker); return null; } catch (ProtocolException e) { throw new RuntimeException(e); // Cannot happen. } finally { lock.unlock(); } }
protected static boolean wasCalledDuringClassLoading() { if (LOCK.isHeldByCurrentThread()) return true; LOCK.lock(); try { StackTrace st = new StackTrace(new Throwable()); int n = st.getDepth(); for (int i = 3; i < n; i++) { StackTraceElement ste = st.getElement(i); if ("ClassLoader.java".equals(ste.getFileName()) && "loadClass".equals(ste.getMethodName())) { return true; } } return false; } finally { LOCK.unlock(); } }
@Override public StoredBlock getChainHead() throws BlockStoreException { final MappedByteBuffer buffer = this.buffer; if (buffer == null) throw new BlockStoreException("Store closed"); lock.lock(); try { if (lastChainHead == null) { byte[] headHash = new byte[32]; buffer.position(8); buffer.get(headHash); Sha256Hash hash = new Sha256Hash(headHash); StoredBlock block = get(hash); if (block == null) throw new BlockStoreException( "Corrupted block store: could not find chain head: " + hash); lastChainHead = block; } return lastChainHead; } finally { lock.unlock(); } }
@Override public void put(StoredBlock block) throws BlockStoreException { final MappedByteBuffer buffer = this.buffer; if (buffer == null) throw new BlockStoreException("Store closed"); lock.lock(); try { int cursor = getRingCursor(buffer); if (cursor == getFileSize()) { // Wrapped around. cursor = FILE_PROLOGUE_BYTES; } buffer.position(cursor); Sha256Hash hash = block.getHeader().getHash(); notFoundCache.remove(hash); buffer.put(hash.getBytes()); block.serializeCompact(buffer); setRingCursor(buffer, buffer.position()); blockCache.put(hash, block); } finally { lock.unlock(); } }