You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2011/07/27 23:00:29 UTC

svn commit: r1151625 - in /cassandra/trunk: CHANGES.txt src/java/org/apache/cassandra/cache/FreeableMemory.java src/java/org/apache/cassandra/cache/SerializingCache.java

Author: jbellis
Date: Wed Jul 27 21:00:28 2011
New Revision: 1151625

URL: http://svn.apache.org/viewvc?rev=1151625&view=rev
Log:
fix potential use of free'd native memory interface/SerializingCache
patch by jbellis; reviewed by slebresne for CASSANDRA-2951

Modified:
    cassandra/trunk/CHANGES.txt
    cassandra/trunk/src/java/org/apache/cassandra/cache/FreeableMemory.java
    cassandra/trunk/src/java/org/apache/cassandra/cache/SerializingCache.java

Modified: cassandra/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=1151625&r1=1151624&r2=1151625&view=diff
==============================================================================
--- cassandra/trunk/CHANGES.txt (original)
+++ cassandra/trunk/CHANGES.txt Wed Jul 27 21:00:28 2011
@@ -22,6 +22,8 @@
  * check column family validity in nodetool repair (CASSANDRA-2933)
  * use lazy initialization instead of class initialization in NodeId
    (CASSANDRA-2953)
+ * fix potential use of free'd native memory in SerializingCache 
+   (CASSANDRA-1951)
 
 
 0.8.2

Modified: cassandra/trunk/src/java/org/apache/cassandra/cache/FreeableMemory.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cache/FreeableMemory.java?rev=1151625&r1=1151624&r2=1151625&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cache/FreeableMemory.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cache/FreeableMemory.java Wed Jul 27 21:00:28 2011
@@ -22,19 +22,40 @@ package org.apache.cassandra.cache;
 
 
 import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import com.sun.jna.Memory;
 
 public class FreeableMemory extends Memory
 {
-	protected volatile boolean valid = true;
-	
+    AtomicInteger references = new AtomicInteger(0);
+
     public FreeableMemory(long size)
     {
         super(size);
     }
 
-    public void free()
+    /** @return true if we succeed in referencing before the reference count reaches zero */
+    public boolean reference()
+    {
+        while (true)
+        {
+            int n = references.get();
+            if (n <= 0)
+                return false;
+            if (references.compareAndSet(n, n + 1))
+                return true;
+        }
+    }
+
+    /** decrement reference count.  if count reaches zero, the object is freed. */
+    public void unreference()
+    {
+        if (references.decrementAndGet() == 0)
+            free();
+    }
+
+    private void free()
     {
         assert peer != 0;
         super.finalize(); // calls free and sets peer to zero
@@ -46,8 +67,8 @@ public class FreeableMemory extends Memo
     @Override
     protected void finalize()
     {
-        if (peer != 0)
-            super.finalize();
+        assert references.get() == 0;
+        assert peer == 0;
     }
     
     public byte getValidByte(long offset)

Modified: cassandra/trunk/src/java/org/apache/cassandra/cache/SerializingCache.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cache/SerializingCache.java?rev=1151625&r1=1151624&r2=1151625&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cache/SerializingCache.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cache/SerializingCache.java Wed Jul 27 21:00:28 2011
@@ -55,7 +55,7 @@ public class SerializingCache<K, V> impl
         {
             public void onEviction(K k, FreeableMemory mem)
             {
-                mem.free();
+                mem.unreference();
             }
         };
         this.map = new ConcurrentLinkedHashMap.Builder<K, FreeableMemory>()
@@ -137,7 +137,16 @@ public class SerializingCache<K, V> impl
         FreeableMemory mem = map.get(key);
         if (mem == null)
             return null;
-        return deserialize(mem);
+        if (!mem.reference())
+            return null;
+        try
+        {
+            return deserialize(mem);
+        }
+        finally
+        {
+            mem.unreference();
+        }
     }
 
     public void put(K key, V value)
@@ -146,16 +155,17 @@ public class SerializingCache<K, V> impl
         if (mem == null)
             return; // out of memory.  never mind.
 
+        mem.reference();
         FreeableMemory old = map.put(key, mem);
         if (old != null)
-            old.free();
+            old.unreference();
     }
 
     public void remove(K key)
     {
         FreeableMemory mem = map.remove(key);
         if (mem != null)
-            mem.free();
+            mem.unreference();
     }
 
     public Set<K> keySet()