Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
merge #2951 from trunk (r1151625, r1152416)
git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.8@1153190 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jbellis committed Aug 2, 2011
1 parent 8a79b64 commit 058a6ac
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGES.txt
Expand Up @@ -26,6 +26,8 @@
(CASSANDRA-2960)
* fix assertion error during compaction of counter CFs (CASSANDRA-2968)
* avoid trying to create index names, when no index exists (CASSANDRA-2867)
* fix potential use of free'd native memory in SerializingCache
(CASSANDRA-2951)


0.8.2
Expand Down
34 changes: 29 additions & 5 deletions src/java/org/apache/cassandra/cache/FreeableMemory.java
Expand Up @@ -22,19 +22,43 @@


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(1);

public FreeableMemory(long size)
{
super(size);
}

public void free()
/**
* @return true if we succeed in referencing before the reference count reaches zero.
* (A FreeableMemory object is created with a reference count of one.)
*/
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
Expand All @@ -46,8 +70,8 @@ public void free()
@Override
protected void finalize()
{
if (peer != 0)
super.finalize();
assert references.get() == 0;
assert peer == 0;
}

public byte getValidByte(long offset)
Expand Down
17 changes: 13 additions & 4 deletions src/java/org/apache/cassandra/cache/SerializingCache.java
Expand Up @@ -55,7 +55,7 @@ public SerializingCache(int capacity, ICompactSerializer3<V> serializer, String
{
public void onEviction(K k, FreeableMemory mem)
{
mem.free();
mem.unreference();
}
};
this.map = new ConcurrentLinkedHashMap.Builder<K, FreeableMemory>()
Expand Down Expand Up @@ -137,7 +137,16 @@ public V get(Object key)
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)
Expand All @@ -148,14 +157,14 @@ public void put(K key, V value)

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()
Expand Down
2 changes: 2 additions & 0 deletions test/unit/org/apache/cassandra/cache/CacheProviderTest.java
Expand Up @@ -48,6 +48,8 @@ public class CacheProviderTest extends SchemaLoader
private void simpleCase(ColumnFamily cf, ICache<String, ColumnFamily> cache)
{
cache.put(key1, cf);
assert cache.get(key1) != null;

assertDigests(cache.get(key1), cf);
cache.put(key2, cf);
cache.put(key3, cf);
Expand Down

0 comments on commit 058a6ac

Please sign in to comment.