Author: amitj
Date: Mon Oct 24 04:53:21 2016
New Revision: 1766347

URL: http://svn.apache.org/viewvc?rev=1766347&view=rev
Log:
OAK-4870: Implement caching for S3DataStore

* Use fix for getReference() for S3DataStore
* Added test for reference when secret not available.
* Throwing exception when secret not available.

Modified:
    
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
    
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java
    
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DataStore.java

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java?rev=1766347&r1=1766346&r2=1766347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
 Mon Oct 24 04:53:21 2016
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.blob.c
 
 import java.io.File;
 import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -51,6 +52,7 @@ import com.amazonaws.services.s3.transfe
 import com.amazonaws.util.StringUtils;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
 import com.google.common.collect.AbstractIterator;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -58,7 +60,8 @@ import org.apache.jackrabbit.core.data.D
 import org.apache.jackrabbit.core.data.DataRecord;
 import org.apache.jackrabbit.core.data.DataStoreException;
 import org.apache.jackrabbit.core.data.util.NamedThreadFactory;
-import org.apache.jackrabbit.oak.spi.blob.SharedBackend;
+import org.apache.jackrabbit.oak.spi.blob.AbstractDataRecord;
+import org.apache.jackrabbit.oak.spi.blob.AbstractSharedBackend;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -68,7 +71,7 @@ import static java.lang.Thread.currentTh
 /**
  * A data store backend that stores data on Amazon S3.
  */
-public class S3Backend implements SharedBackend {
+public class S3Backend extends AbstractSharedBackend {
 
     /**
      * Logger instance.
@@ -83,6 +86,8 @@ public class S3Backend implements Shared
 
     private String bucket;
 
+    private String secret;
+
     private TransferManager tmx;
 
     private Properties properties;
@@ -105,9 +110,9 @@ public class S3Backend implements Shared
             if (bucket == null || "".equals(bucket.trim())) {
                 bucket = properties.getProperty(S3Constants.S3_BUCKET);
             }
-
+            secret = properties.getProperty("secret");
             String region = properties.getProperty(S3Constants.S3_REGION);
-            Region s3Region = null;
+            Region s3Region;
             if (StringUtils.isNullOrEmpty(region)) {
                 com.amazonaws.regions.Region ec2Region = 
Regions.getCurrentRegion();
                 if (ec2Region != null) {
@@ -232,9 +237,8 @@ public class S3Backend implements Shared
                 
Thread.currentThread().setContextClassLoader(contextClassLoader);
             }
         }
-        LOG.debug(
-            "write of [{}], length=[{}], in [{}]ms",
-            new Object[] { identifier, file.length(), 
(System.currentTimeMillis() - start) });
+        LOG.debug("write of [{}], length=[{}], in [{}]ms",
+            identifier, file.length(), (System.currentTimeMillis() - start));
     }
 
     /**
@@ -400,7 +404,7 @@ public class S3Backend implements Shared
             Thread.currentThread().setContextClassLoader(
                 getClass().getClassLoader());
             ObjectMetadata meta = s3service.getObjectMetadata(bucket, 
addMetaKeyPrefix(name));
-            return new S3DataRecord(s3service, bucket, name,
+            return new S3DataRecord(this, s3service, bucket, new 
DataIdentifier(name),
                 meta.getLastModified().getTime(), meta.getContentLength(), 
true);
         } finally {
             if (contextClassLoader != null) {
@@ -420,7 +424,8 @@ public class S3Backend implements Shared
                 new 
ListObjectsRequest().withBucketName(bucket).withPrefix(addMetaKeyPrefix(prefix));
             ObjectListing prevObjectListing = 
s3service.listObjects(listObjectsRequest);
             for (final S3ObjectSummary s3ObjSumm : 
prevObjectListing.getObjectSummaries()) {
-                metadataList.add(new S3DataRecord(s3service, bucket, 
stripMetaKeyPrefix(s3ObjSumm.getKey()),
+                metadataList.add(new S3DataRecord(this, s3service, bucket,
+                    new DataIdentifier(stripMetaKeyPrefix(s3ObjSumm.getKey())),
                     s3ObjSumm.getLastModified().getTime(), 
s3ObjSumm.getSize(), true));
             }
         } finally {
@@ -463,7 +468,7 @@ public class S3Backend implements Shared
             if (deleteList.size() > 0) {
                 DeleteObjectsRequest delObjsReq = new 
DeleteObjectsRequest(bucket);
                 delObjsReq.setKeys(deleteList);
-                DeleteObjectsResult dobjs = 
s3service.deleteObjects(delObjsReq);
+                s3service.deleteObjects(delObjsReq);
             }
         } finally {
             if (contextClassLoader != null) {
@@ -474,11 +479,13 @@ public class S3Backend implements Shared
 
     @Override
     public Iterator<DataRecord> getAllRecords() {
+        final AbstractSharedBackend backend = this;
         return new RecordsIterator<DataRecord>(
             new Function<S3ObjectSummary, DataRecord>() {
                 @Override
                 public DataRecord apply(S3ObjectSummary input) {
-                    return new S3DataRecord(s3service, bucket, 
getIdentifierName(input.getKey()),
+                    return new S3DataRecord(backend, s3service, bucket,
+                        new DataIdentifier(getIdentifierName(input.getKey())),
                         input.getLastModified().getTime(), input.getSize());
                 }
             });
@@ -493,10 +500,10 @@ public class S3Backend implements Shared
             
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
 
             ObjectMetadata object = s3service.getObjectMetadata(bucket, key);
-            S3DataRecord record = new S3DataRecord(s3service, bucket, 
identifier.toString(),
+            S3DataRecord record = new S3DataRecord(this, s3service, bucket, 
identifier,
                 object.getLastModified().getTime(), object.getContentLength());
             LOG.debug("Identifier [{}]'s getRecord = [{}] took [{}]ms.",
-                new Object[] {identifier, record, (System.currentTimeMillis() 
- start)});
+                identifier, record, (System.currentTimeMillis() - start));
 
             return record;
         } catch (AmazonServiceException e) {
@@ -513,6 +520,19 @@ public class S3Backend implements Shared
         }
     }
 
+    @Override
+    public byte[] getOrCreateReferenceKey() throws DataStoreException {
+        try {
+            if (!Strings.isNullOrEmpty(secret)) {
+                return secret.getBytes("UTF-8");
+            }
+            LOG.warn("secret not defined");
+            throw new DataStoreException("secret not defined");
+        } catch (UnsupportedEncodingException e) {
+            throw new DataStoreException(e);
+        }
+    }
+
     /**
      * Returns an iterator over the S3 objects
      * @param <T>
@@ -602,23 +622,24 @@ public class S3Backend implements Shared
     /**
      * S3DataRecord which lazily retrieves the input stream of the record.
      */
-    static class S3DataRecord implements DataRecord {
+    static class S3DataRecord extends AbstractDataRecord {
         private AmazonS3Client s3service;
-        private DataIdentifier identifier;
         private long length;
         private long lastModified;
         private String bucket;
         private boolean isMeta;
 
-        public S3DataRecord(AmazonS3Client s3service, String bucket, String 
key, long lastModified,
+        public S3DataRecord(AbstractSharedBackend backend, AmazonS3Client 
s3service, String bucket,
+            DataIdentifier key, long lastModified,
             long length) {
-            this(s3service, bucket, key, lastModified, length, false);
+            this(backend, s3service, bucket, key, lastModified, length, false);
         }
 
-        public S3DataRecord(AmazonS3Client s3service, String bucket, String 
key, long lastModified,
+        public S3DataRecord(AbstractSharedBackend backend, AmazonS3Client 
s3service, String bucket,
+            DataIdentifier key, long lastModified,
             long length, boolean isMeta) {
+            super(backend, key);
             this.s3service = s3service;
-            this.identifier = new DataIdentifier(key);
             this.lastModified = lastModified;
             this.length = length;
             this.bucket = bucket;
@@ -626,25 +647,15 @@ public class S3Backend implements Shared
         }
 
         @Override
-        public DataIdentifier getIdentifier() {
-            return identifier;
-        }
-
-        @Override
-        public String getReference() {
-            return identifier.toString();
-        }
-
-        @Override
         public long getLength() throws DataStoreException {
             return length;
         }
 
         @Override
         public InputStream getStream() throws DataStoreException {
-            String id = getKeyName(identifier);
+            String id = getKeyName(getIdentifier());
             if (isMeta) {
-                id = addMetaKeyPrefix(identifier.toString());
+                id = addMetaKeyPrefix(getIdentifier().toString());
             }
             return s3service.getObject(bucket, id).getObjectContent();
         }
@@ -657,7 +668,7 @@ public class S3Backend implements Shared
         @Override
         public String toString() {
             return "S3DataRecord{" +
-                "identifier=" + identifier +
+                "identifier=" + getIdentifier() +
                 ", length=" + length +
                 ", lastModified=" + lastModified +
                 ", bucket='" + bucket + '\'' +
@@ -723,10 +734,8 @@ public class S3Backend implements Shared
                     
delObjsReq.setKeys(Collections.unmodifiableList(deleteList.subList(
                         startIndex, endIndex)));
                     DeleteObjectsResult dobjs = 
s3service.deleteObjects(delObjsReq);
-                    LOG.info(
-                        "Records[{}] deleted in datastore from index [{}] to 
[{}]",
-                        new Object[] { dobjs.getDeletedObjects().size(),
-                            startIndex, (endIndex - 1) });
+                    LOG.info("Records[{}] deleted in datastore from index [{}] 
to [{}]",
+                        dobjs.getDeletedObjects().size(), startIndex, 
(endIndex - 1));
                     if (endIndex == size) {
                         break;
                     } else {
@@ -799,8 +808,7 @@ public class S3Backend implements Shared
                     copy.waitForCopyResult();
                     LOG.debug("[{}] renamed to [{}] ", oldKey, newS3Key);
                 } catch (InterruptedException ie) {
-                    LOG.error(" Exception in renaming [{}] to [{}] ",
-                        new Object[] { ie, oldKey, newS3Key });
+                    LOG.error(" Exception in renaming [{}] to [{}] ", ie, 
oldKey, newS3Key);
                 }
 
             } finally {

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java?rev=1766347&r1=1766346&r2=1766347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataStore.java
 Mon Oct 24 04:53:21 2016
@@ -18,10 +18,8 @@ package org.apache.jackrabbit.oak.blob.c
 
 import java.util.Properties;
 
-import com.google.common.base.Strings;
-import org.apache.jackrabbit.core.data.DataIdentifier;
-import org.apache.jackrabbit.core.data.DataStoreException;
 import org.apache.jackrabbit.oak.plugins.blob.AbstractSharedCachingDataStore;
+import org.apache.jackrabbit.oak.spi.blob.AbstractSharedBackend;
 import org.apache.jackrabbit.oak.spi.blob.SharedBackend;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,7 +44,7 @@ public class S3DataStore extends Abstrac
     private String secret;
 
     @Override
-    protected SharedBackend createBackend() {
+    protected AbstractSharedBackend createBackend() {
         S3Backend backend = new S3Backend();
         if(properties != null){
             backend.setProperties(properties);
@@ -54,36 +52,6 @@ public class S3DataStore extends Abstrac
         return backend;
     }
 
-    @Override
-    protected byte[] getOrCreateReferenceKey() throws DataStoreException {
-        try {
-            return secret.getBytes("UTF-8");
-        } catch (Exception e) {
-            LOG.info("Error in creating reference key", e);
-            throw new DataStoreException(e);
-        }
-    }
-
-    /**
-     * Look in the backend for a record matching the given identifier.  
Returns true
-     * if such a record exists.
-     *
-     * @param identifier - An identifier for the record.
-     * @return true if a record for the provided identifier can be found.
-     */
-    public boolean haveRecordForIdentifier(final String identifier) {
-        try {
-            if (!Strings.isNullOrEmpty(identifier)) {
-                return backend.exists(new DataIdentifier(identifier));
-            }
-        }
-        catch (DataStoreException e) {
-            LOG.warn(String.format("Data Store Exception caught checking for 
%s in pending uploads",
-                identifier), e);
-        }
-        return false;
-    }
-
     /**------------------------------------------- Getters & 
Setters-----------------------------**/
 
     /**
@@ -105,8 +73,4 @@ public class S3DataStore extends Abstrac
     public void setMinRecordLength(int minRecordLength) {
         this.minRecordLength = minRecordLength;
     }
-
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
 }

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DataStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DataStore.java?rev=1766347&r1=1766346&r2=1766347&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DataStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/TestS3DataStore.java
 Mon Oct 24 04:53:21 2016
@@ -16,14 +16,17 @@
  */
 package org.apache.jackrabbit.oak.blob.cloud.s3;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.util.Date;
 import java.util.List;
 import java.util.Properties;
+import java.util.Random;
 
 import javax.jcr.RepositoryException;
 
+import org.apache.jackrabbit.core.data.DataRecord;
 import org.apache.jackrabbit.core.data.DataStore;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -36,6 +39,9 @@ import org.slf4j.LoggerFactory;
 
 import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3DataStoreUtils.getFixtures;
 import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3DataStoreUtils.getS3DataStore;
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3DataStoreUtils.isS3Configured;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Simple tests for S3DataStore.
@@ -44,15 +50,13 @@ import static org.apache.jackrabbit.oak.
 public class TestS3DataStore {
     protected static final Logger LOG = 
LoggerFactory.getLogger(TestS3Ds.class);
 
-    private Date startTime = null;
-
     @Rule
     public ExpectedException expectedEx = ExpectedException.none();
 
     @Rule
     public TemporaryFolder folder = new TemporaryFolder(new File("target"));
 
-    protected Properties props;
+    private Properties props;
 
     @Parameterized.Parameter
     public String s3Class;
@@ -70,7 +74,6 @@ public class TestS3DataStore {
     public void setUp() throws Exception {
         dataStoreDir = folder.newFolder();
         props = new Properties();
-        startTime = new Date();
     }
 
     @Test
@@ -83,4 +86,18 @@ public class TestS3DataStore {
         props.put(S3Constants.S3_REGION, "us-standard");
         ds = getS3DataStore(s3Class, props, dataStoreDir.getAbsolutePath());
     }
+
+    @Test
+    public void testNoSecretDefined() throws Exception {
+        assumeTrue(isS3Configured());
+        Random randomGen = new Random();
+
+        props = S3DataStoreUtils.getS3Config();
+        ds = getS3DataStore(s3Class, props, dataStoreDir.getAbsolutePath());
+        byte[] data = new byte[4096];
+        randomGen.nextBytes(data);
+        DataRecord rec = ds.addRecord(new ByteArrayInputStream(data));
+        Assert.assertEquals(data.length, rec.getLength());
+        assertNull(rec.getReference());
+    }
 }


Reply via email to