From: <tho...@us...> - 2011-06-09 16:50:55
|
Revision: 4659 http://bigdata.svn.sourceforge.net/bigdata/?rev=4659&view=rev Author: thompsonbry Date: 2011-06-09 16:50:47 +0000 (Thu, 09 Jun 2011) Log Message: ----------- Working w/ Martyn on finalization logic and release of buffers to the direct buffer pool. Modified Paths: -------------- branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/io/DirectBufferPool.java branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/TemporaryStoreFactory.java branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/service/TestReceiveBuffer.java Modified: branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/io/DirectBufferPool.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/io/DirectBufferPool.java 2011-06-09 16:05:46 UTC (rev 4658) +++ branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/io/DirectBufferPool.java 2011-06-09 16:50:47 UTC (rev 4659) @@ -160,28 +160,45 @@ } - protected void finalize() { - if (buf != null) { - try { - if (DEBUG) { - /* - * Note: This code path WILL NOT return the buffer to - * the pool. This is deliberate. When DEBUG is true we - * do not permit a buffer which was not correctly - * release to be reused. - */ - log.error( - "Buffer release on finalize: AllocationStack", - allocationStack); - } else { - log.error("Buffer release on finalize."); - DirectBufferPool.this.release(buf); - } - } catch (InterruptedException e) { - // ignore - } - } - } + protected void finalize() throws Throwable { + /* + * Ultra paranoid block designed to ensure that we do not double + * release the ByteBuffer to the owning pool via the action of + * another finalized. + */ + final ByteBuffer buf; + synchronized(this) { + buf = this.buf; + this.buf = null; + } + if (buf == null) + return; + if (DEBUG) { + /* + * Note: This code path WILL NOT return the buffer to the pool. + * This is deliberate. When DEBUG is true we do not permit a + * buffer which was not correctly release to be reused. + * + * Note: A common cause of this is that the caller is holding + * onto the acquired ByteBuffer object rather than the + * IBufferAccess object. This permits the IBufferAccess + * reference to be finalized. When the IBufferAccess object is + * finalized, it will attempt to release the buffer (except in + * DEBUG mode). However, if the caller is holding onto the + * ByteBuffer then this is an error which can rapidly lead to + * corrupt data through concurrent modification (what happens is + * that the ByteBuffer is handed out to another thread in + * response to another acquire() and we now have two threads + * using the same ByteBuffer, each of which believes that they + * "own" the reference). + */ + log.error("Buffer release on finalize: AllocationStack", + allocationStack); + } else { + log.error("Buffer release on finalize."); + DirectBufferPool.this.release(buf); + } + } } Modified: branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java 2011-06-09 16:05:46 UTC (rev 4658) +++ branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java 2011-06-09 16:50:47 UTC (rev 4659) @@ -236,7 +236,7 @@ /** * Optional {@link WriteCache}. */ - private WriteCache writeCache = null; + final private WriteCache writeCache; /** * The next offset at which data in the {@link #writeCache} will be written Modified: branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/TemporaryStoreFactory.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/TemporaryStoreFactory.java 2011-06-09 16:05:46 UTC (rev 4658) +++ branches/QUADS_QUERY_BRANCH/bigdata/src/java/com/bigdata/journal/TemporaryStoreFactory.java 2011-06-09 16:50:47 UTC (rev 4659) @@ -40,6 +40,7 @@ import com.bigdata.cache.ConcurrentWeakValueCache; import com.bigdata.rawstore.Bytes; import com.bigdata.rawstore.WormAddressManager; +import com.bigdata.util.InnerCause; /** * Helper class for {@link IIndexStore#getTempStore()}. This class is very light @@ -302,6 +303,8 @@ */ synchronized public void closeAll() { + boolean interrupted = false; + final Iterator<Map.Entry<UUID,WeakReference<TemporaryStore>>> itr = stores.entryIterator(); while(itr.hasNext()) { @@ -318,14 +321,24 @@ } // close the temporary store (it will be deleted synchronously). - if(store.isOpen()) { + if (store.isOpen()) { - store.close(); - + try { + store.close(); + } catch (Throwable t) { + if (InnerCause.isInnerCause(t, InterruptedException.class)) + interrupted = true; + } + } - + } + if (interrupted) { + // Propagate the interrupt. + Thread.currentThread().interrupt(); + } + } - + } Modified: branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/service/TestReceiveBuffer.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/service/TestReceiveBuffer.java 2011-06-09 16:05:46 UTC (rev 4658) +++ branches/QUADS_QUERY_BRANCH/bigdata/src/test/com/bigdata/service/TestReceiveBuffer.java 2011-06-09 16:50:47 UTC (rev 4659) @@ -85,11 +85,13 @@ final UUID allowedUUID = UUID.randomUUID(); - final IBufferAccess allowedBufferdb = DirectBufferPool.INSTANCE.acquire(1, - TimeUnit.SECONDS); - final ByteBuffer allowedBuffer = allowedBufferdb.buffer(); + final IBufferAccess allowedBufferdb = DirectBufferPool.INSTANCE + .acquire(); + try { + final ByteBuffer allowedBuffer = allowedBufferdb.buffer(); + // populate with some random data. fillBufferWithRandomData(allowedBuffer); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |