You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2014/01/28 09:36:05 UTC

svn commit: r1561997 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugi...

Author: thomasm
Date: Tue Jan 28 08:36:04 2014
New Revision: 1561997

URL: http://svn.apache.org/r1561997
Log:
OAK-1359 BlobStore implementation improvements

Added:
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/GarbageCollectableBlobStore.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/MongoBlobStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/CommandExecutor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/DefaultCommandExecutor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/MongoGridFSBlobStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/rdbpersistence/RDBBlobStore.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/AbstractBlobStoreTest.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStore.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStoreInputStream.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java
    jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/MongoBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/MongoBlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/MongoBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/MongoBlobStore.java Tue Jan 28 08:36:04 2014
@@ -60,7 +60,7 @@ public class MongoBlobStore extends Abst
     }
 
     @Override
-    protected void storeBlock(byte[] digest, int level, byte[] data) throws Exception {
+    protected void storeBlock(byte[] digest, int level, byte[] data) throws IOException {
         String id = StringUtils.convertBytesToHex(digest);
         // Check if it already exists?
         MongoBlob mongoBlob = new MongoBlob();
@@ -102,7 +102,7 @@ public class MongoBlobStore extends Abst
     }
 
     @Override
-    public void startMark() throws Exception {
+    public void startMark() throws IOException {
         minLastModified = System.currentTimeMillis();
         markInUse();
     }
@@ -128,7 +128,7 @@ public class MongoBlobStore extends Abst
     }
 
     @Override
-    public int sweep() throws Exception {
+    public int sweep() throws IOException {
         DBObject query = getBlobQuery(null, minLastModified);
         long countBefore = getBlobCollection().count(query);
         WriteResult writeResult = getBlobCollection().remove(query);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/CommandExecutor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/CommandExecutor.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/CommandExecutor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/CommandExecutor.java Tue Jan 28 08:36:04 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.plugins.mongomk.blob.gridfs;
 
+import java.io.IOException;
+
 /**
  * The executor part of the <a href="http://en.wikipedia.org/wiki/Command_pattern">Command Pattern</a>.
  *
@@ -38,7 +40,7 @@ public interface CommandExecutor {
      * @param <T> the command type
      * @param command
      * @return The result of the execution.
-     * @throws Exception If an error occurred while executing.
+     * @throws IOException If an error occurred while executing.
      */
-    <T> T execute(Command<T> command) throws Exception;
+    <T> T execute(Command<T> command) throws IOException;
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/DefaultCommandExecutor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/DefaultCommandExecutor.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/DefaultCommandExecutor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/DefaultCommandExecutor.java Tue Jan 28 08:36:04 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.plugins.mongomk.blob.gridfs;
 
+import java.io.IOException;
+
 
 /**
  * Implementation of the {@link CommandExecutor} interface.
@@ -23,7 +25,15 @@ package org.apache.jackrabbit.oak.plugin
 public class DefaultCommandExecutor implements CommandExecutor {
 
     @Override
-    public <T> T execute(Command<T> command) throws Exception {
+    public <T> T execute(Command<T> command) throws IOException {
+        try {
+            return executeCommand(command);
+        } catch (Exception e) {
+            throw new IOException(e);
+        }
+    }
+        
+    public <T> T executeCommand(Command<T> command) throws Exception {
         T result = null;
 
         int numOfRetries = command.getNumOfRetries();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/MongoGridFSBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/MongoGridFSBlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/MongoGridFSBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/gridfs/MongoGridFSBlobStore.java Tue Jan 28 08:36:04 2014
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.oak.plugins.mongomk.blob.gridfs;
 
+import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.jackrabbit.mk.blobs.BlobStore;
@@ -43,20 +44,20 @@ public class MongoGridFSBlobStore implem
     }
 
     @Override
-    public long getBlobLength(String blobId) throws Exception {
+    public long getBlobLength(String blobId) throws IOException {
         Command<Long> command = new GetBlobLengthCommandGridFS(gridFS, blobId);
         return commandExecutor.execute(command);
     }
 
     @Override
-    public int readBlob(String blobId, long blobOffset, byte[] buffer, int bufferOffset, int length) throws Exception {
+    public int readBlob(String blobId, long blobOffset, byte[] buffer, int bufferOffset, int length) throws IOException {
         Command<Integer> command = new ReadBlobCommandGridFS(gridFS, blobId, blobOffset,
                 buffer, bufferOffset, length);
         return commandExecutor.execute(command);
     }
 
     @Override
-    public String writeBlob(InputStream is) throws Exception {
+    public String writeBlob(InputStream is) throws IOException {
         Command<String> command = new WriteBlobCommandGridFS(gridFS, is);
         return commandExecutor.execute(command);
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/rdbpersistence/RDBBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/rdbpersistence/RDBBlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/rdbpersistence/RDBBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/rdbpersistence/RDBBlobStore.java Tue Jan 28 08:36:04 2014
@@ -99,7 +99,15 @@ public class RDBBlobStore extends Abstra
     private long minLastModified;
 
     @Override
-    protected void storeBlock(byte[] digest, int level, byte[] data) throws SQLException {
+    protected void storeBlock(byte[] digest, int level, byte[] data) throws IOException {
+        try {
+            storeBlockInDatabase(digest, level, data);
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+    
+    private void storeBlockInDatabase(byte[] digest, int level, byte[] data) throws SQLException {
         try {
             String id = StringUtils.convertBytesToHex(digest);
             long now = System.currentTimeMillis();
@@ -177,7 +185,7 @@ public class RDBBlobStore extends Abstra
     }
 
     @Override
-    public void startMark() throws Exception {
+    public void startMark() throws IOException {
         minLastModified = System.currentTimeMillis();
         markInUse();
     }
@@ -207,7 +215,15 @@ public class RDBBlobStore extends Abstra
     }
 
     @Override
-    public int sweep() throws Exception {
+    public int sweep() throws IOException {
+        try {
+            return sweepFromDatabase();
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+        
+    private int sweepFromDatabase() throws SQLException {
         try {
             int count = 0;
             PreparedStatement prep = connection.prepareStatement("select id from datastore_meta where lastMod < ?");

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/AbstractBlobStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/AbstractBlobStoreTest.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/AbstractBlobStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/blob/AbstractBlobStoreTest.java Tue Jan 28 08:36:04 2014
@@ -33,9 +33,10 @@ import java.util.HashMap;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.jackrabbit.mk.blobs.AbstractBlobStore;
+import org.apache.jackrabbit.mk.blobs.BlobStore;
 import org.apache.jackrabbit.mk.blobs.BlobStoreInputStream;
 import org.apache.jackrabbit.mk.blobs.FileBlobStore;
+import org.apache.jackrabbit.mk.blobs.GarbageCollectableBlobStore;
 import org.apache.jackrabbit.mk.json.JsopBuilder;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
 import org.junit.After;
@@ -49,7 +50,7 @@ import org.junit.Test;
  */
 public abstract class AbstractBlobStoreTest {
 
-    public AbstractBlobStore store;
+    public GarbageCollectableBlobStore store;
 
     /**
      * Should be overridden by subclasses to set the {@link #store} variable.
@@ -301,7 +302,7 @@ public abstract class AbstractBlobStoreT
 
     }
 
-    public static void extractFiles(AbstractBlobStore store, String listingId, String target) throws IOException {
+    public static void extractFiles(BlobStore store, String listingId, String target) throws IOException {
         String listing = new String(BlobStoreInputStream.readFully(store, listingId), "UTF-8");
         JsopTokenizer t = new JsopTokenizer(listing);
         File targetDir = new File(target);
@@ -326,7 +327,7 @@ public abstract class AbstractBlobStoreT
         t.read('}');
     }
 
-    public static String addFiles(AbstractBlobStore store, String dir) throws Exception {
+    public static String addFiles(BlobStore store, String dir) throws Exception {
         ArrayList<String> list = new ArrayList<String>();
         String root = new File(dir).getAbsolutePath();
         String parent = new File(dir).getParentFile().getAbsolutePath();

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/AbstractBlobStore.java Tue Jan 28 08:36:04 2014
@@ -28,6 +28,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -62,7 +63,7 @@ import java.util.concurrent.atomic.Atomi
  * long), size of data store id (variable size long), hash code length (variable
  * size int), hash code.
  */
-public abstract class AbstractBlobStore implements BlobStore, Cache.Backend<AbstractBlobStore.BlockId, AbstractBlobStore.Data> {
+public abstract class AbstractBlobStore implements GarbageCollectableBlobStore, Cache.Backend<AbstractBlobStore.BlockId, AbstractBlobStore.Data> {
 
     protected static final String HASH_ALGORITHM = "SHA-256";
 
@@ -103,10 +104,12 @@ public abstract class AbstractBlobStore 
         this.blockSizeMin = x;
     }
 
+    @Override
     public long getBlockSizeMin() {
         return blockSizeMin;
     }
 
+    @Override
     public void setBlockSize(int x) {
         validateBlockSize(x);
         this.blockSize = x;
@@ -124,15 +127,8 @@ public abstract class AbstractBlobStore 
         return blockSize;
     }
 
-    /**
-     * Write a blob from a temporary file. The temporary file is removed
-     * afterwards. A file based blob stores might simply rename the file, so
-     * that no additional writes are necessary.
-     *
-     * @param tempFilePath the temporary file
-     * @return the blob id
-     */
-    public String writeBlob(String tempFilePath) throws Exception {
+    @Override
+    public String writeBlob(String tempFilePath) throws IOException {
         File file = new File(tempFilePath);
         InputStream in = null;
         try {
@@ -147,7 +143,7 @@ public abstract class AbstractBlobStore 
     }
 
     @Override
-    public String writeBlob(InputStream in) throws Exception {
+    public String writeBlob(InputStream in) throws IOException {
         try {
             ByteArrayOutputStream idStream = new ByteArrayOutputStream();
             convertBlobToId(in, idStream, 0, 0);
@@ -169,15 +165,17 @@ public abstract class AbstractBlobStore 
         inUse.put(blobId, new WeakReference<String>(blobId));
     }
 
+    @Override
     public void clearInUse() {
         inUse.clear();
     }
 
+    @Override
     public void clearCache() {
         cache.clear();
     }
 
-    private void convertBlobToId(InputStream in, ByteArrayOutputStream idStream, int level, long totalLength) throws Exception {
+    private void convertBlobToId(InputStream in, ByteArrayOutputStream idStream, int level, long totalLength) throws IOException {
         int count = 0;
         // try to re-use the block (but not concurrently)
         byte[] block = blockBuffer.getAndSet(null);
@@ -197,7 +195,12 @@ public abstract class AbstractBlobStore 
                 idStream.write(block, 0, blockLen);
                 totalLength += blockLen;
             } else {
-                MessageDigest messageDigest = MessageDigest.getInstance(HASH_ALGORITHM);
+                MessageDigest messageDigest;
+                try {
+                    messageDigest = MessageDigest.getInstance(HASH_ALGORITHM);
+                } catch (NoSuchAlgorithmException e) {
+                    throw new IOException(e);
+                }
                 messageDigest.update(block, 0, blockLen);
                 byte[] digest = messageDigest.digest();
                 idStream.write(TYPE_HASH);
@@ -244,24 +247,26 @@ public abstract class AbstractBlobStore 
      *            unless that's easy to achieve
      * @param data the data to be stored
      */
-    protected abstract void storeBlock(byte[] digest, int level, byte[] data) throws Exception;
+    protected abstract void storeBlock(byte[] digest, int level, byte[] data) throws IOException;
 
-    public abstract void startMark() throws Exception;
+    @Override
+    public abstract void startMark() throws IOException;
 
-    public abstract int sweep() throws Exception;
+    @Override
+    public abstract int sweep() throws IOException;
 
     protected abstract boolean isMarkEnabled();
 
     protected abstract void mark(BlockId id) throws Exception;
 
-    protected void markInUse() throws Exception {
+    protected void markInUse() throws IOException {
         for (String id : new ArrayList<String>(inUse.keySet())) {
             mark(id);
         }
     }
 
     @Override
-    public int readBlob(String blobId, long pos, byte[] buff, int off, int length) throws Exception {
+    public int readBlob(String blobId, long pos, byte[] buff, int off, int length) throws IOException {
         if (isMarkEnabled()) {
             mark(blobId);
         }
@@ -313,7 +318,7 @@ public abstract class AbstractBlobStore 
         }
     }
 
-    private byte[] readBlock(byte[] digest, long pos) throws Exception {
+    private byte[] readBlock(byte[] digest, long pos) {
         BlockId id = new BlockId(digest, pos);
         return cache.get(id).data;
     }

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStore.java Tue Jan 28 08:36:04 2014
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.mk.blobs;
 
+import java.io.IOException;
 import java.io.InputStream;
 
 /**
@@ -30,7 +31,7 @@ public interface BlobStore {
      * @param in the input stream
      * @return the blob id
      */
-    String writeBlob(InputStream in) throws Exception;
+    String writeBlob(InputStream in) throws IOException;
 
     /**
      * Read a number of bytes from a blob.
@@ -42,7 +43,7 @@ public interface BlobStore {
      * @param length the number of bytes to read
      * @return the number of bytes read
      */
-    int readBlob(String blobId, long pos, byte[] buff, int off, int length) throws Exception;
+    int readBlob(String blobId, long pos, byte[] buff, int off, int length) throws IOException;
 
     /**
      * Get the length of the blob.
@@ -50,6 +51,6 @@ public interface BlobStore {
      * @param blobId the blob id
      * @return the length
      */
-    long getBlobLength(String blobId) throws Exception;
+    long getBlobLength(String blobId) throws IOException;
 
 }

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStoreInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStoreInputStream.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStoreInputStream.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/BlobStoreInputStream.java Tue Jan 28 08:36:04 2014
@@ -65,7 +65,7 @@ public class BlobStoreInputStream extend
         return oneByteBuff[0] & 0xff;
     }
 
-    public static byte[] readFully(AbstractBlobStore store, String id) throws IOException {
+    public static byte[] readFully(BlobStore store, String id) throws IOException {
         int len = (int) store.getBlobLength(id);
         byte[] buff = new byte[len];
         BlobStoreInputStream in = new BlobStoreInputStream(store, id, 0);

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/DbBlobStore.java Tue Jan 28 08:36:04 2014
@@ -48,7 +48,15 @@ public class DbBlobStore extends Abstrac
     }
 
     @Override
-    protected synchronized void storeBlock(byte[] digest, int level, byte[] data) throws SQLException {
+    protected synchronized void storeBlock(byte[] digest, int level, byte[] data) throws IOException {
+        try {
+            storeBlockToDatabase(digest, level, data);
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+    
+    private void storeBlockToDatabase(byte[] digest, int level, byte[] data) throws SQLException {
         Connection conn = cp.getConnection();
         try {
             String id = StringUtils.convertBytesToHex(digest);
@@ -131,7 +139,7 @@ public class DbBlobStore extends Abstrac
     }
 
     @Override
-    public void startMark() throws Exception {
+    public void startMark() throws IOException {
         minLastModified = System.currentTimeMillis();
         markInUse();
     }
@@ -162,7 +170,15 @@ public class DbBlobStore extends Abstrac
     }
 
     @Override
-    public int sweep() throws Exception {
+    public int sweep() throws IOException {
+        try {
+            return sweepFromDatabase();
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+    
+    private int sweepFromDatabase() throws SQLException {
         int count = 0;
         Connection conn = cp.getConnection();
         try {

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/FileBlobStore.java Tue Jan 28 08:36:04 2014
@@ -28,6 +28,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.DigestInputStream;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 
 /**
  * A file blob store.
@@ -48,10 +49,15 @@ public class FileBlobStore extends Abstr
     }
 
     @Override
-    public String writeBlob(String tempFilePath) throws Exception {
+    public String writeBlob(String tempFilePath) throws IOException {
         File file = new File(tempFilePath);
         InputStream in = new FileInputStream(file);
-        MessageDigest messageDigest = MessageDigest.getInstance(HASH_ALGORITHM);
+        MessageDigest messageDigest;
+        try {
+            messageDigest = MessageDigest.getInstance(HASH_ALGORITHM);
+        } catch (NoSuchAlgorithmException e) {
+            throw new IOException(e);
+        }
         DigestInputStream din = new DigestInputStream(in, messageDigest);
         long length = file.length();
         try {
@@ -136,7 +142,7 @@ public class FileBlobStore extends Abstr
     }
 
     @Override
-    public void startMark() throws Exception {
+    public void startMark() throws IOException {
         mark = true;
         for (int j = 0; j < 256; j++) {
             String sub1 = StringUtils.convertBytesToHex(new byte[] { (byte) j });

Added: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/GarbageCollectableBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/GarbageCollectableBlobStore.java?rev=1561997&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/GarbageCollectableBlobStore.java (added)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/GarbageCollectableBlobStore.java Tue Jan 28 08:36:04 2014
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.mk.blobs;
+
+import java.io.IOException;
+
+/**
+ * A blob store that support garbage collection.
+ */
+public interface GarbageCollectableBlobStore extends BlobStore {
+
+    /**
+     * Set the block size used by this blob store, if the blob store splits
+     * binaries into blocks. If not, this setting is ignored.
+     * 
+     * @param x the block size in bytes.
+     */
+    void setBlockSize(int x);
+
+    /**
+     * Write a blob from a temporary file. The temporary file is removed
+     * afterwards. A file based blob stores might simply rename the file, so
+     * that no additional writes are necessary.
+     *
+     * @param tempFilePath the temporary file
+     * @return the blob id
+     */
+    String writeBlob(String tempFileName) throws IOException;
+
+    /**
+     * Remove all unused blocks.
+     * 
+     * @return the number of removed blocks
+     */
+    int sweep() throws IOException;
+    
+    /**
+     * Start the mark phase.
+     */
+    void startMark() throws IOException;
+    
+    /**
+     * Clear all objects marked as "transiently in use".
+     */
+    void clearInUse();
+
+    /**
+     * Clear the cache.
+     */
+    void clearCache();
+
+    /**
+     * Get the minimum block size (if there is any).
+     * 
+     * @return the block size
+     */
+    long getBlockSizeMin();
+
+}

Modified: jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java?rev=1561997&r1=1561996&r2=1561997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java (original)
+++ jackrabbit/oak/trunk/oak-mk/src/main/java/org/apache/jackrabbit/mk/blobs/MemoryBlobStore.java Tue Jan 28 08:36:04 2014
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.mk.blobs;
 
+import java.io.IOException;
 import java.util.HashMap;
 
 /**
@@ -42,7 +43,7 @@ public class MemoryBlobStore extends Abs
     }
 
     @Override
-    public void startMark() throws Exception {
+    public void startMark() throws IOException {
         mark = true;
         old = map;
         map = new HashMap<BlockId, byte[]>();
@@ -55,7 +56,7 @@ public class MemoryBlobStore extends Abs
     }
 
     @Override
-    protected void mark(BlockId id) throws Exception {
+    protected void mark(BlockId id) {
         byte[] data = map.get(id);
         if (data == null) {
             data = old.get(id);