Author: jbellis
Date: Thu Feb  4 20:04:20 2010
New Revision: 906631

URL: http://svn.apache.org/viewvc?rev=906631&view=rev
Log:
only gc if there are undeleted sstables that gc-ing could free
patch by jbellis; tested by Brandon Williams for CASSANDRA-724

Modified:
    
incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
    incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
    
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableDeletingReference.java
    
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java
    
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableTracker.java
    
incubator/cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java

Modified: 
incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: 
http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=906631&r1=906630&r2=906631&view=diff
==============================================================================
--- 
incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
 (original)
+++ 
incubator/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
 Thu Feb  4 20:04:20 2010
@@ -1144,24 +1144,19 @@
         }
     }
 
+    public boolean hasUnreclaimedSpace()
+    {
+        return ssTables_.getLiveSize() < ssTables_.getTotalSize();
+    }
+
     public long getTotalDiskSpaceUsed()
     {
-        long n = 0;
-        for (File file : files())
-        {
-            n += file.length();
-        }
-        return n;
+        return ssTables_.getTotalSize();
     }
 
     public long getLiveDiskSpaceUsed()
     {
-        long n = 0;
-        for (SSTableReader sstable : ssTables_)
-        {
-            n += sstable.bytesOnDisk();
-        }
-        return n;
+        return ssTables_.getLiveSize();
     }
 
     public int getLiveSSTableCount()

Modified: incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: 
http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=906631&r1=906630&r2=906631&view=diff
==============================================================================
--- incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java 
(original)
+++ incubator/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Thu 
Feb  4 20:04:20 2010
@@ -208,7 +208,7 @@
         return tableMetadata.getColumnFamilies();
     }
 
-    Collection<ColumnFamilyStore> getColumnFamilyStores()
+    public Collection<ColumnFamilyStore> getColumnFamilyStores()
     {
         return Collections.unmodifiableCollection(columnFamilyStores.values());
     }
@@ -479,7 +479,7 @@
         if (path == null)
         {
             // retry after GCing to force unmap of compacted SSTables so they 
can be deleted
-            StorageService.requestGC();
+            StorageService.instance.requestGC();
             try
             {
                 Thread.sleep(SSTableDeletingReference.RETRY_DELAY * 2);

Modified: 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableDeletingReference.java
URL: 
http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableDeletingReference.java?rev=906631&r1=906630&r2=906631&view=diff
==============================================================================
--- 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableDeletingReference.java
 (original)
+++ 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableDeletingReference.java
 Thu Feb  4 20:04:20 2010
@@ -1,6 +1,7 @@
 package org.apache.cassandra.io;
 
 import java.io.File;
+import java.io.IOError;
 import java.io.IOException;
 import java.lang.ref.PhantomReference;
 import java.lang.ref.ReferenceQueue;
@@ -9,6 +10,8 @@
 
 import org.apache.log4j.Logger;
 
+import org.apache.cassandra.io.util.FileUtils;
+
 public class SSTableDeletingReference extends PhantomReference<SSTableReader>
 {
     private static final Logger logger = 
Logger.getLogger(SSTableDeletingReference.class);
@@ -16,13 +19,17 @@
     private static final Timer timer = new Timer("SSTABLE-CLEANUP-TIMER");
     public static final int RETRY_DELAY = 10000;
 
+    private final SSTableTracker tracker;
     public final String path;
+    private final long size;
     private boolean deleteOnCleanup;
 
-    SSTableDeletingReference(SSTableReader referent, ReferenceQueue<? super 
SSTableReader> q)
+    SSTableDeletingReference(SSTableTracker tracker, SSTableReader referent, 
ReferenceQueue<? super SSTableReader> q)
     {
         super(referent, q);
+        this.tracker = tracker;
         this.path = referent.path;
+        this.size = referent.bytesOnDisk();
     }
 
     public void deleteOnCleanup()
@@ -62,10 +69,18 @@
                     throw new RuntimeException("Unable to delete " + path);
                 }
             }
+            try
+            {
+                FileUtils.deleteWithConfirm(new 
File(SSTable.indexFilename(path)));
+                FileUtils.deleteWithConfirm(new 
File(SSTable.filterFilename(path)));
+                FileUtils.deleteWithConfirm(new 
File(SSTable.compactedFilename(path)));
+            }
+            catch (IOException e)
+            {
+                throw new IOError(e);
+            }
+            tracker.spaceReclaimed(size);
             logger.info("Deleted " + path);
-            DeletionService.submitDeleteWithRetry(SSTable.indexFilename(path));
-            
DeletionService.submitDeleteWithRetry(SSTable.filterFilename(path));
-            
DeletionService.submitDeleteWithRetry(SSTable.compactedFilename(path));
         }
     }
 }

Modified: 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java
URL: 
http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java?rev=906631&r1=906630&r2=906631&view=diff
==============================================================================
--- 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java 
(original)
+++ 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableReader.java 
Thu Feb  4 20:04:20 2010
@@ -135,7 +135,7 @@
         return sstable;
     }
 
-    SSTableDeletingReference phantomReference;
+    private volatile SSTableDeletingReference phantomReference;
     // jvm can only map up to 2GB at a time, so we split index/data into 
segments of that size when using mmap i/o
     private final MappedByteBuffer[] indexBuffers;
     private final MappedByteBuffer[] buffers;
@@ -196,11 +196,15 @@
         this.indexPositions = indexPositions;
         this.spannedIndexDataPositions = spannedIndexDataPositions;
         this.bf = bloomFilter;
-        phantomReference = new SSTableDeletingReference(this, finalizerQueue);
-        finalizers.add(phantomReference);
         this.keyCache = keyCache;
     }
 
+    public void addFinalizingReference(SSTableTracker tracker)
+    {
+        phantomReference = new SSTableDeletingReference(tracker, this, 
finalizerQueue);
+        finalizers.add(phantomReference);
+    }
+
     private static MappedByteBuffer mmap(String filename, long start, int 
size) throws IOException
     {
         RandomAccessFile raf;

Modified: 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableTracker.java
URL: 
http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableTracker.java?rev=906631&r1=906630&r2=906631&view=diff
==============================================================================
--- 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableTracker.java 
(original)
+++ 
incubator/cassandra/trunk/src/java/org/apache/cassandra/io/SSTableTracker.java 
Thu Feb  4 20:04:20 2010
@@ -23,11 +23,14 @@
 
 import java.util.*;
 import java.io.IOException;
+import java.util.concurrent.atomic.AtomicLong;
 
 
 public class SSTableTracker implements Iterable<SSTableReader>
 {
     private volatile Set<SSTableReader> sstables;
+    private final AtomicLong liveSize = new AtomicLong();
+    private final AtomicLong totalSize = new AtomicLong();
 
     public SSTableTracker(Collection<SSTableReader> sstables)
     {
@@ -42,12 +45,17 @@
         {
             assert sstable.getIndexPositions() != null;
             sstablesNew.add(sstable);
+            long size = sstable.bytesOnDisk();
+            liveSize.addAndGet(size);
+            totalSize.addAndGet(size);
+            sstable.addFinalizingReference(this);
         }
 
         for (SSTableReader sstable : oldSSTables)
         {
             sstablesNew.remove(sstable);
             sstable.markCompacted();
+            liveSize.addAndGet(-sstable.bytesOnDisk());
         }
 
         sstables = Collections.unmodifiableSet(sstablesNew);
@@ -102,4 +110,20 @@
         }
         return n;
     }
+
+    public long getLiveSize()
+    {
+        return liveSize.get();
+    }
+
+    public long getTotalSize()
+    {
+        return totalSize.get();
+    }
+
+    public void spaceReclaimed(long size)
+    {
+        totalSize.addAndGet(-size);
+    }
 }
+

Modified: 
incubator/cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java
URL: 
http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java?rev=906631&r1=906630&r2=906631&view=diff
==============================================================================
--- 
incubator/cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java
 (original)
+++ 
incubator/cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java
 Thu Feb  4 20:04:20 2010
@@ -1472,10 +1472,31 @@
         return isClientMode;
     }
 
-    public static void requestGC()
+    public synchronized void requestGC()
     {
-        logger_.info("requesting GC to free disk space");
-        System.gc();
+        if (hasUnreclaimedSpace())
+        {
+            logger_.info("requesting GC to free disk space");
+            System.gc();
+            try
+            {
+                Thread.sleep(1000);
+            }
+            catch (InterruptedException e)
+            {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+    private boolean hasUnreclaimedSpace()
+    {
+        for (ColumnFamilyStore cfs : ColumnFamilyStore.all())
+        {
+            if (cfs.hasUnreclaimedSpace())
+                return true;
+        }
+        return false;
     }
 
     // Never ever do this at home. Used by tests.


Reply via email to