Author: mattryan
Date: Wed Aug 28 19:28:11 2019
New Revision: 1866044

URL: http://svn.apache.org/viewvc?rev=1866044&view=rev
Log:
OAK-8552: Add data store config to skip exists check on download URI generation

This change adds a new optional configuration parameter for AzureDataStore and 
S3DataStore.  The new parameter, named "presignedHttpDownloadURIVerifyExists", 
has a default value of true which means the createHttpDownloadURI() method will 
ensure the requested blob exists in blob storage before creating the signed 
download URI.  If this parameter is set to false, the exists check will be 
skipped, resulting in higher signed download URI generation performance but 
potentially returning a URI to a nonexistent blob in some cases (see OAK-7998).

Modified:
    
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
    
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java
    
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderTest.java
    
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/S3Constants.java
    
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataRecordAccessProviderTest.java
    
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
    
jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java?rev=1866044&r1=1866043&r2=1866044&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureBlobStoreBackend.java
 Wed Aug 28 19:28:11 2019
@@ -114,6 +114,7 @@ public class AzureBlobStoreBackend exten
     private int httpDownloadURIExpirySeconds = 0; // disabled by default
     private int httpUploadURIExpirySeconds = 0; // disabled by default
     private boolean createBlobContainer = true;
+    private boolean presignedDownloadURIVerifyExists = true;
 
     private Cache<DataIdentifier, URI> httpDownloadURICache;
 
@@ -163,6 +164,8 @@ public class AzureBlobStoreBackend exten
                 if 
(properties.getProperty(AzureConstants.AZURE_BLOB_REQUEST_TIMEOUT) != null) {
                     requestTimeout = 
PropertiesUtil.toInteger(properties.getProperty(AzureConstants.AZURE_BLOB_REQUEST_TIMEOUT),
 RetryPolicy.DEFAULT_CLIENT_RETRY_COUNT);
                 }
+                presignedDownloadURIVerifyExists =
+                        
PropertiesUtil.toBoolean(properties.get(AzureConstants.PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS),
 true);
 
                 CloudBlobContainer azureContainer = getAzureContainer();
 
@@ -767,23 +770,24 @@ public class AzureBlobStoreBackend exten
         
         if (httpDownloadURIExpirySeconds > 0) {
 
-            // Check if this identifier exists.  If not, we want to return null
-            // even if the identifier is in the download URI cache.
-            try {
-                if (! exists(identifier)) {
-                    LOG.warn("Cannot create download URI for nonexistent blob 
{}; returning null", getKeyName(identifier));
-                    return null;
-                }
-            }
-            catch (DataStoreException e) {
-                LOG.warn("Cannot create download URI for blob {} (caught 
DataStoreException); returning null", getKeyName(identifier), e);
-                return null;
-            }
-
             if (null != httpDownloadURICache) {
                 uri = httpDownloadURICache.getIfPresent(identifier);
             }
             if (null == uri) {
+                if (presignedDownloadURIVerifyExists) {
+                    // Check if this identifier exists.  If not, we want to 
return null
+                    // even if the identifier is in the download URI cache.
+                    try {
+                        if (!exists(identifier)) {
+                            LOG.warn("Cannot create download URI for 
nonexistent blob {}; returning null", getKeyName(identifier));
+                            return null;
+                        }
+                    } catch (DataStoreException e) {
+                        LOG.warn("Cannot create download URI for blob {} 
(caught DataStoreException); returning null", getKeyName(identifier), e);
+                        return null;
+                    }
+                }
+
                 String key = getKeyName(identifier);
                 SharedAccessBlobHeaders headers = new 
SharedAccessBlobHeaders();
                 headers.setCacheControl(String.format("private, max-age=%d, 
immutable", httpDownloadURIExpirySeconds));

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java?rev=1866044&r1=1866043&r2=1866044&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/main/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureConstants.java
 Wed Aug 28 19:28:11 2019
@@ -95,5 +95,17 @@ public final class AzureConstants {
      */
     public static final String PRESIGNED_HTTP_DOWNLOAD_URI_CACHE_MAX_SIZE = 
"presignedHttpDownloadURICacheMaxSize";
 
+    /**
+     * Boolean flag to allow disabling of verification check on download URI
+     * generation.  Default is true (the existence check is performed).
+     *
+     * Some installations may prefer to disable async uploads, in which case it
+     * is possible to disable the existence check and thus greatly speed up the
+     * generation of presigned download URIs.  See OAK-7998 which describes why
+     * the existence check was added to understand how async uploading relates
+     * to this feature.
+     */
+    public static final String PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS = 
"presignedHttpDownloadURIVerifyExists";
+
     private AzureConstants() { }
 }

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderTest.java?rev=1866044&r1=1866043&r2=1866044&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud-azure/src/test/java/org/apache/jackrabbit/oak/blob/cloud/azure/blobstorage/AzureDataRecordAccessProviderTest.java
 Wed Aug 28 19:28:11 2019
@@ -18,6 +18,9 @@
  */
 package org.apache.jackrabbit.oak.blob.cloud.azure.blobstorage;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -38,14 +41,12 @@ import org.apache.jackrabbit.oak.plugins
 import 
org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
 import 
org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
 import org.apache.jackrabbit.oak.spi.blob.BlobOptions;
+import org.jetbrains.annotations.NotNull;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assume.assumeTrue;
-
 public class AzureDataRecordAccessProviderTest extends 
AbstractDataRecordAccessProviderTest {
     @ClassRule
     public static TemporaryFolder homeDir = new TemporaryFolder(new 
File("target"));
@@ -55,20 +56,40 @@ public class AzureDataRecordAccessProvid
     @BeforeClass
     public static void setupDataStore() throws Exception {
         assumeTrue(AzureDataStoreUtils.isAzureConfigured());
-        Properties props = AzureDataStoreUtils.getAzureConfig();
-        props.setProperty("cacheSize", "0");
         dataStore = (AzureDataStore) AzureDataStoreUtils
-            .getAzureDataStore(props, homeDir.newFolder().getAbsolutePath());
+            .getAzureDataStore(getProperties(), 
homeDir.newFolder().getAbsolutePath());
         dataStore.setDirectDownloadURIExpirySeconds(expirySeconds);
         dataStore.setDirectUploadURIExpirySeconds(expirySeconds);
     }
 
+    private static Properties getProperties() {
+        Properties props = AzureDataStoreUtils.getAzureConfig();
+        props.setProperty("cacheSize", "0");
+        return props;
+    }
+
+    private static AzureDataStore createDataStore(@NotNull Properties 
properties) throws Exception {
+        AzureDataStore ds = (AzureDataStore) AzureDataStoreUtils
+                .getAzureDataStore(properties, 
homeDir.newFolder().getAbsolutePath());
+        ds.setDirectDownloadURIExpirySeconds(expirySeconds);
+        ds.setDirectUploadURIExpirySeconds(expirySeconds);
+        return ds;
+    }
+
     @Override
     protected ConfigurableDataRecordAccessProvider getDataStore() {
         return dataStore;
     }
 
     @Override
+    protected ConfigurableDataRecordAccessProvider getDataStore(@NotNull 
Properties overrideProperties) throws Exception {
+        Properties mergedProperties = new Properties();
+        mergedProperties.putAll(getProperties());
+        mergedProperties.putAll(overrideProperties);
+        return createDataStore(mergedProperties);
+    }
+
+    @Override
     protected DataRecord doGetRecord(DataStore ds, DataIdentifier identifier) 
throws DataStoreException {
         return ds.getRecord(identifier);
     }

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=1866044&r1=1866043&r2=1866044&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
 Wed Aug 28 19:28:11 2019
@@ -86,6 +86,7 @@ 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.commons.PropertiesUtil;
 import 
org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
 import 
org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
 import 
org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
@@ -147,6 +148,8 @@ public class S3Backend extends AbstractS
     private int httpUploadURIExpirySeconds = 0;
     private int httpDownloadURIExpirySeconds = 0;
 
+    private boolean presignedDownloadURIVerifyExists = true;
+
     public void init() throws DataStoreException {
         ClassLoader contextClassLoader = 
Thread.currentThread().getContextClassLoader();
 
@@ -238,6 +241,9 @@ public class S3Backend extends AbstractS
             String enablePresignedAccelerationStr = 
properties.getProperty(S3Constants.PRESIGNED_URI_ENABLE_ACCELERATION);
             
setBinaryTransferAccelerationEnabled(enablePresignedAccelerationStr != null && 
"true".equals(enablePresignedAccelerationStr));
 
+            presignedDownloadURIVerifyExists =
+                    
PropertiesUtil.toBoolean(properties.get(S3Constants.PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS),
 true);
+
             LOG.debug("S3 Backend initialized in [{}] ms",
                 +(System.currentTimeMillis() - startTime.getTime()));
         } catch (Exception e) {
@@ -744,23 +750,24 @@ public class S3Backend extends AbstractS
         if (null == identifier) throw new NullPointerException("identifier");
         if (null == downloadOptions) throw new 
NullPointerException("downloadOptions");
 
-        try {
-            if (! exists(identifier)) {
-                LOG.warn("Cannot create download URI for nonexistent blob {}; 
returning null", getKeyName(identifier));
-                return null;
-            }
-        }
-        catch (DataStoreException e) {
-            LOG.warn("Cannot create download URI for blob {} (caught 
DataStoreException); returning null", getKeyName(identifier), e);
-            return null;
-        }
-
         URI uri = null;
         // if cache is enabled, check the cache
         if (httpDownloadURICache != null) {
             uri = httpDownloadURICache.getIfPresent(identifier);
         }
-        if (uri == null) {
+        if (null == uri) {
+            if (presignedDownloadURIVerifyExists) {
+                try {
+                    if (!exists(identifier)) {
+                        LOG.warn("Cannot create download URI for nonexistent 
blob {}; returning null", getKeyName(identifier));
+                        return null;
+                    }
+                } catch (DataStoreException e) {
+                    LOG.warn("Cannot create download URI for blob {} (caught 
DataStoreException); returning null", getKeyName(identifier), e);
+                    return null;
+                }
+            }
+
             Map<String, String> requestParams = Maps.newHashMap();
             requestParams.put("response-cache-control",
                     String.format("private, max-age=%d, immutable",

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java?rev=1866044&r1=1866043&r2=1866044&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Constants.java
 Wed Aug 28 19:28:11 2019
@@ -126,6 +126,18 @@ public final class S3Constants {
     public static final String PRESIGNED_URI_ENABLE_ACCELERATION = 
"presignedURIEnableTransferAcceleration";
 
     /**
+     * Boolean flag to allow disabling of verification check on download URI
+     * generation.  Default is true (the existence check is performed).
+     *
+     * Some installations may prefer to disable async uploads, in which case it
+     * is possible to disable the existence check and thus greatly speed up the
+     * generation of presigned download URIs.  See OAK-7998 which describes why
+     * the existence check was added to understand how async uploading relates
+     * to this feature.
+     */
+    public static final String PRESIGNED_HTTP_DOWNLOAD_URI_VERIFY_EXISTS = 
"presignedHttpDownloadURIVerifyExists";
+
+    /**
      * private constructor so that class cannot initialized from outside.
      */
     private S3Constants() {

Modified: 
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataRecordAccessProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataRecordAccessProviderTest.java?rev=1866044&r1=1866043&r2=1866044&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataRecordAccessProviderTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-cloud/src/test/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3DataRecordAccessProviderTest.java
 Wed Aug 28 19:28:11 2019
@@ -18,11 +18,20 @@
  */
 package org.apache.jackrabbit.oak.blob.cloud.s3;
 
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3DataStoreUtils.getFixtures;
+import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3DataStoreUtils.getS3Config;
+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.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 import java.util.Map;
+import java.util.Properties;
 
 import javax.net.ssl.HttpsURLConnection;
 
@@ -35,19 +44,12 @@ import org.apache.jackrabbit.oak.plugins
 import 
org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
 import 
org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
 import org.apache.jackrabbit.oak.spi.blob.BlobOptions;
+import org.jetbrains.annotations.NotNull;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
-import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3DataStoreUtils.getFixtures;
-import static 
org.apache.jackrabbit.oak.blob.cloud.s3.S3DataStoreUtils.getS3Config;
-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.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
 public class S3DataRecordAccessProviderTest extends 
AbstractDataRecordAccessProviderTest {
     @ClassRule
     public static TemporaryFolder homeDir = new TemporaryFolder(new 
File("target"));
@@ -57,11 +59,17 @@ public class S3DataRecordAccessProviderT
     @BeforeClass
     public static void setupDataStore() throws Exception {
         assumeTrue(isS3Configured());
-        dataStore = (S3DataStore) getS3DataStore(getFixtures().get(0), 
getS3Config(),
-            homeDir.newFolder().getAbsolutePath());
+        dataStore = createDataStore(getS3Config());
+    }
 
-        dataStore.setDirectDownloadURIExpirySeconds(expirySeconds);
-        dataStore.setDirectUploadURIExpirySeconds(expirySeconds);
+    private static S3DataStore createDataStore(@NotNull final Properties 
properties) throws Exception {
+        S3DataStore ds = (S3DataStore) getS3DataStore(getFixtures().get(0), 
properties,
+                homeDir.newFolder().getAbsolutePath());
+
+        ds.setDirectDownloadURIExpirySeconds(expirySeconds);
+        ds.setDirectUploadURIExpirySeconds(expirySeconds);
+
+        return ds;
     }
 
     @Override
@@ -70,6 +78,14 @@ public class S3DataRecordAccessProviderT
     }
 
     @Override
+    protected ConfigurableDataRecordAccessProvider getDataStore(@NotNull 
Properties overrideProperties) throws Exception {
+        Properties mergedProperties = new Properties();
+        mergedProperties.putAll(getS3Config());
+        mergedProperties.putAll(overrideProperties);
+        return createDataStore(mergedProperties);
+    }
+
+    @Override
     protected DataRecord doGetRecord(DataStore ds, DataIdentifier identifier) 
throws DataStoreException {
         return ds.getRecord(identifier);
     }

Modified: 
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java?rev=1866044&r1=1866043&r2=1866044&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
 Wed Aug 28 19:28:11 2019
@@ -36,6 +36,7 @@ import java.net.URLDecoder;
 import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.Map;
+import java.util.Properties;
 
 import javax.net.ssl.HttpsURLConnection;
 
@@ -49,6 +50,7 @@ import org.apache.jackrabbit.core.data.D
 import org.apache.jackrabbit.core.data.DataStoreException;
 import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
 import org.apache.jackrabbit.util.Base64;
+import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -57,6 +59,7 @@ public abstract class AbstractDataRecord
     protected static final Logger LOG = 
LoggerFactory.getLogger(AbstractDataRecordAccessProviderTest.class);
 
     protected abstract ConfigurableDataRecordAccessProvider getDataStore();
+    protected abstract ConfigurableDataRecordAccessProvider 
getDataStore(@NotNull Properties overrideProperties) throws Exception;
     protected abstract long getProviderMinPartSize();
     protected abstract long getProviderMaxPartSize();
     protected abstract long getProviderMaxSinglePutSize();
@@ -101,7 +104,23 @@ public abstract class AbstractDataRecord
     }
 
     @Test
-    public void testGetDownloadURIRequiresValidIdentifier() {
+    public void testGetDownloadURIWithExistsDisabled() throws Exception {
+        DataIdentifier id = new DataIdentifier("identifier");
+        Properties overrideProperties = new Properties();
+        overrideProperties.put("presignedHttpDownloadURIVerifyExists", 
"false");
+        ConfigurableDataRecordAccessProvider ds = 
getDataStore(overrideProperties);
+        assertNotNull(ds.getDownloadURI(id, 
DataRecordDownloadOptions.DEFAULT));
+    }
+
+    @Test
+    public void testGetDownloadURIRequiresValidIdentifierByDefault() {
+        DataIdentifier id = new DataIdentifier("identifier");
+        ConfigurableDataRecordAccessProvider ds = getDataStore();
+        assertNull(ds.getDownloadURI(id, DataRecordDownloadOptions.DEFAULT));
+    }
+
+    @Test
+    public void testGetDownloadURIRequiresNonNullIdentifier() {
         try {
             getDataStore().getDownloadURI(null, 
DataRecordDownloadOptions.DEFAULT);
             fail();

Modified: 
jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md?rev=1866044&r1=1866043&r2=1866044&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md 
(original)
+++ 
jackrabbit/oak/trunk/oak-doc/src/site/markdown/features/direct-binary-access.md 
Wed Aug 28 19:28:11 2019
@@ -51,6 +51,7 @@ The feature has to be explicitly enabled
 | `presignedHttpUploadURIExpirySeconds`   | Integer  | 0 (disabled)     | Time 
limit for upload URLs, in seconds. Choose a value long enough for clients to 
upload larger binaries and possibly retry, but not unlimited to ensure access 
control. Setting to 0 disables the direct upload feature. |
 | `presignedHttpDownloadURIExpirySeconds` | Integer  | 0 (disabled)     | Time 
limit for download URLs, in seconds. Choose a value long enough for clients to 
download larger binaries and possibly retry, but not unlimited to ensure access 
control. Setting to 0 disables the direct download feature. |
 | `presignedHttpDownloadURICacheMaxSize`  | Integer  | 0 (disabled)     | 
**Experimental.** Cache size for reusing download URLs. Expired URLs will be 
cached for half their expiry time, hence if this feature is enabled, clients 
might get URLs that expire after half of 
`presignedHttpDownloadURIExpirySeconds`. Setting to 0 disables the cache. |
+| `presignedHttpDownloadURIVerifyExists` | Boolean | true | Flag to determine 
whether to check that a binary exists in blob storage before issuing a 
presigned download URI.  The default is to verify existence first, providing 
assurance that the signed URI references an existing binary.  If this flag is 
set to false, the existence check is skipped.  This makes generating the signed 
URI anywhere from 100 to 1000 times faster since no network API calls are made, 
but means it is possible in some cases to return a signed URI that doesn't 
reference an existing blob.  See 
[OAK-7998](https://issues.apache.org/jira/browse/OAK-7998) and 
[OAK-8552](https://issues.apache.org/jira/browse/OAK-8552) for more details. |
 | S3:&nbsp;`presignedURIEnableTransferAcceleration` <br/>Azure:&nbsp;n/a       
                              | Boolean  | false (disabled) | **Experimental.** 
Enables [S3 Transfer 
Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html)
 for both upload and download URLs. Transfer acceleration must be enabled on 
the S3 bucket before Oak starts. |
 
 ## API Javadoc


Reply via email to