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 mi...@apache.org on 2023/12/21 14:55:53 UTC
(jackrabbit-oak) branch trunk updated: Issue/oak 10573 azure write timeout (#1244)
This is an automated email from the ASF dual-hosted git repository.
miroslav pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new e2da4d7f84 Issue/oak 10573 azure write timeout (#1244)
e2da4d7f84 is described below
commit e2da4d7f84fcf2c4a6e729fe073529e87f6062f7
Author: Miroslav Smiljanic <sm...@gmail.com>
AuthorDate: Thu Dec 21 15:55:48 2023 +0100
Issue/oak 10573 azure write timeout (#1244)
* OAK-10573 request options optimised for write operations
* OAK-10573 introduce AzureRequestOptions util class
* OAK-10573 adding license header
* OAK-10573 add write check in AzureArchiveManager
* OAK-10573 remove unused imports
---------
Co-authored-by: Miroslav Smiljanic <mi...@apache.com>
---
.../oak/segment/azure/AzureArchiveManager.java | 2 +
.../oak/segment/azure/AzureJournalFile.java | 15 +++-
.../oak/segment/azure/AzurePersistence.java | 37 +--------
.../segment/azure/AzureSegmentArchiveWriter.java | 13 ++-
.../segment/azure/util/AzureRequestOptions.java | 96 ++++++++++++++++++++++
.../azure/util/AzureRequestOptionsTest.java | 78 ++++++++++++++++++
6 files changed, 198 insertions(+), 43 deletions(-)
diff --git a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
index 10c5ce485f..13eeab83d9 100644
--- a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
+++ b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureArchiveManager.java
@@ -139,6 +139,7 @@ public class AzureArchiveManager implements SegmentArchiveManager {
getBlobs(archiveName)
.forEach(cloudBlob -> {
try {
+ writeAccessController.checkWritingAllowed();
cloudBlob.delete();
} catch (StorageException e) {
log.error("Can't delete segment {}", cloudBlob.getUri().getPath(), e);
@@ -158,6 +159,7 @@ public class AzureArchiveManager implements SegmentArchiveManager {
getBlobs(from)
.forEach(cloudBlob -> {
try {
+ writeAccessController.checkWritingAllowed();
renameBlob(cloudBlob, targetDirectory);
} catch (IOException e) {
log.error("Can't rename segment {}", cloudBlob.getUri().getPath(), e);
diff --git a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureJournalFile.java b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureJournalFile.java
index b468e42b44..76b52de113 100644
--- a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureJournalFile.java
+++ b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureJournalFile.java
@@ -22,6 +22,9 @@ import com.microsoft.azure.storage.blob.CloudAppendBlob;
import com.microsoft.azure.storage.blob.CloudBlob;
import com.microsoft.azure.storage.blob.CloudBlobDirectory;
import com.microsoft.azure.storage.blob.ListBlobItem;
+import com.microsoft.azure.storage.blob.DeleteSnapshotsOption;
+import com.microsoft.azure.storage.blob.BlobRequestOptions;
+import org.apache.jackrabbit.oak.segment.azure.util.AzureRequestOptions;
import org.apache.jackrabbit.oak.segment.azure.util.CaseInsensitiveKeysMapAccess;
import org.apache.jackrabbit.oak.segment.remote.WriteAccessController;
import org.apache.jackrabbit.oak.segment.spi.persistence.JournalFile;
@@ -162,7 +165,11 @@ public class AzureJournalFile implements JournalFile {
private int lineCount;
+ private final BlobRequestOptions writeOptimisedBlobRequestOptions;
+
public AzureJournalWriter() throws IOException {
+ writeOptimisedBlobRequestOptions = AzureRequestOptions.optimiseForWriteOperations(directory.getServiceClient().getDefaultRequestOptions());
+
List<CloudAppendBlob> blobs = getJournalBlobs();
if (blobs.isEmpty()) {
try {
@@ -190,7 +197,7 @@ public class AzureJournalFile implements JournalFile {
writeAccessController.checkWritingAllowed();
for (CloudAppendBlob cloudAppendBlob : getJournalBlobs()) {
- cloudAppendBlob.delete();
+ cloudAppendBlob.delete(DeleteSnapshotsOption.NONE, null, writeOptimisedBlobRequestOptions, null);
}
createNextFile(0);
@@ -229,11 +236,11 @@ public class AzureJournalFile implements JournalFile {
text.append(line).append("\n");
}
try {
- currentBlob.appendText(text.toString());
+ currentBlob.appendText(text.toString(), null, null, writeOptimisedBlobRequestOptions, null);
currentBlob.getMetadata().put("lastEntry", entries.get(entries.size() - 1));
lineCount += entries.size();
currentBlob.getMetadata().put("lineCount", Integer.toString(lineCount));
- currentBlob.uploadMetadata();
+ currentBlob.uploadMetadata(null, writeOptimisedBlobRequestOptions, null);
} catch (StorageException e) {
throw new IOException(e);
}
@@ -243,7 +250,7 @@ public class AzureJournalFile implements JournalFile {
private void createNextFile(int suffix) throws IOException {
try {
currentBlob = directory.getAppendBlobReference(getJournalFileName(suffix + 1));
- currentBlob.createOrReplace();
+ currentBlob.createOrReplace(null, writeOptimisedBlobRequestOptions, null);
lineCount = 0;
} catch (URISyntaxException | StorageException e) {
throw new IOException(e);
diff --git a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java
index eed07004e5..dc41fbff1e 100644
--- a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java
+++ b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzurePersistence.java
@@ -25,15 +25,14 @@ import java.util.concurrent.TimeUnit;
import com.microsoft.azure.storage.OperationContext;
import com.microsoft.azure.storage.RequestCompletedEvent;
-import com.microsoft.azure.storage.RetryLinearRetry;
import com.microsoft.azure.storage.StorageEvent;
import com.microsoft.azure.storage.StorageException;
import com.microsoft.azure.storage.blob.BlobListingDetails;
-import com.microsoft.azure.storage.blob.BlobRequestOptions;
import com.microsoft.azure.storage.blob.CloudAppendBlob;
import com.microsoft.azure.storage.blob.CloudBlobDirectory;
import com.microsoft.azure.storage.blob.CloudBlockBlob;
import com.microsoft.azure.storage.blob.ListBlobItem;
+import org.apache.jackrabbit.oak.segment.azure.util.AzureRequestOptions;
import org.apache.jackrabbit.oak.segment.remote.WriteAccessController;
import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitor;
import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitor;
@@ -48,19 +47,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AzurePersistence implements SegmentNodeStorePersistence {
-
- private static final String RETRY_ATTEMPTS_PROP = "segment.azure.retry.attempts";
- private static final int DEFAULT_RETRY_ATTEMPTS = 5;
-
- private static final String RETRY_BACKOFF_PROP = "segment.azure.retry.backoff";
- private static final int DEFAULT_RETRY_BACKOFF_SECONDS = 5;
-
- private static final String TIMEOUT_EXECUTION_PROP = "segment.timeout.execution";
- private static final int DEFAULT_TIMEOUT_EXECUTION = 30;
-
- private static final String TIMEOUT_INTERVAL_PROP = "segment.timeout.interval";
- private static final int DEFAULT_TIMEOUT_INTERVAL = 1;
-
private static final Logger log = LoggerFactory.getLogger(AzurePersistence.class);
protected final CloudBlobDirectory segmentstoreDirectory;
@@ -70,26 +56,7 @@ public class AzurePersistence implements SegmentNodeStorePersistence {
public AzurePersistence(CloudBlobDirectory segmentStoreDirectory) {
this.segmentstoreDirectory = segmentStoreDirectory;
- BlobRequestOptions defaultRequestOptions = segmentStoreDirectory.getServiceClient().getDefaultRequestOptions();
- if (defaultRequestOptions.getRetryPolicyFactory() == null) {
- int retryAttempts = Integer.getInteger(RETRY_ATTEMPTS_PROP, DEFAULT_RETRY_ATTEMPTS);
- if (retryAttempts > 0) {
- Integer retryBackoffSeconds = Integer.getInteger(RETRY_BACKOFF_PROP, DEFAULT_RETRY_BACKOFF_SECONDS);
- defaultRequestOptions.setRetryPolicyFactory(new RetryLinearRetry((int) TimeUnit.SECONDS.toMillis(retryBackoffSeconds), retryAttempts));
- }
- }
- if (defaultRequestOptions.getMaximumExecutionTimeInMs() == null) {
- int timeoutExecution = Integer.getInteger(TIMEOUT_EXECUTION_PROP, DEFAULT_TIMEOUT_EXECUTION);
- if (timeoutExecution > 0) {
- defaultRequestOptions.setMaximumExecutionTimeInMs((int) TimeUnit.SECONDS.toMillis(timeoutExecution));
- }
- }
- if (defaultRequestOptions.getTimeoutIntervalInMs() == null) {
- int timeoutInterval = Integer.getInteger(TIMEOUT_INTERVAL_PROP, DEFAULT_TIMEOUT_INTERVAL);
- if (timeoutInterval > 0) {
- defaultRequestOptions.setTimeoutIntervalInMs((int) TimeUnit.SECONDS.toMillis(timeoutInterval));
- }
- }
+ AzureRequestOptions.applyDefaultRequestOptions(segmentStoreDirectory.getServiceClient().getDefaultRequestOptions());
}
@Override
diff --git a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureSegmentArchiveWriter.java b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureSegmentArchiveWriter.java
index 3df0eaafa6..e9bbbb322a 100644
--- a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureSegmentArchiveWriter.java
+++ b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/AzureSegmentArchiveWriter.java
@@ -25,12 +25,14 @@ import java.io.IOException;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
+import com.microsoft.azure.storage.blob.BlobRequestOptions;
import org.apache.jackrabbit.guava.common.base.Stopwatch;
import com.microsoft.azure.storage.StorageException;
import com.microsoft.azure.storage.blob.CloudBlobDirectory;
import com.microsoft.azure.storage.blob.CloudBlockBlob;
import org.apache.jackrabbit.oak.commons.Buffer;
+import org.apache.jackrabbit.oak.segment.azure.util.AzureRequestOptions;
import org.apache.jackrabbit.oak.segment.remote.WriteAccessController;
import org.apache.jackrabbit.oak.segment.azure.util.Retrier;
import org.apache.jackrabbit.oak.segment.remote.AbstractRemoteSegmentArchiveWriter;
@@ -47,10 +49,13 @@ public class AzureSegmentArchiveWriter extends AbstractRemoteSegmentArchiveWrite
Integer.getInteger("azure.segment.archive.writer.retries.intervalMs", 5000)
);
+ private final BlobRequestOptions writeOptimisedBlobRequestOptions;
+
public AzureSegmentArchiveWriter(CloudBlobDirectory archiveDirectory, IOMonitor ioMonitor, FileStoreMonitor monitor, WriteAccessController writeAccessController) {
super(ioMonitor, monitor);
this.archiveDirectory = archiveDirectory;
this.writeAccessController = writeAccessController;
+ this.writeOptimisedBlobRequestOptions = AzureRequestOptions.optimiseForWriteOperations(archiveDirectory.getServiceClient().getDefaultRequestOptions());
}
@Override
@@ -71,8 +76,8 @@ public class AzureSegmentArchiveWriter extends AbstractRemoteSegmentArchiveWrite
Stopwatch stopwatch = Stopwatch.createStarted();
try {
blob.setMetadata(AzureBlobMetadata.toSegmentMetadata(indexEntry));
- blob.uploadFromByteArray(data, offset, size);
- blob.uploadMetadata();
+ blob.uploadFromByteArray(data, offset, size, null, writeOptimisedBlobRequestOptions, null);
+ blob.uploadMetadata(null, writeOptimisedBlobRequestOptions, null);
} catch (StorageException e) {
throw new IOException(e);
}
@@ -97,7 +102,7 @@ public class AzureSegmentArchiveWriter extends AbstractRemoteSegmentArchiveWrite
try {
writeAccessController.checkWritingAllowed();
- getBlob(getName() + extension).uploadFromByteArray(data, 0, data.length);
+ getBlob(getName() + extension).uploadFromByteArray(data, 0, data.length, null, writeOptimisedBlobRequestOptions, null);
} catch (StorageException e) {
throw new IOException(e);
}
@@ -110,7 +115,7 @@ public class AzureSegmentArchiveWriter extends AbstractRemoteSegmentArchiveWrite
try {
writeAccessController.checkWritingAllowed();
- getBlob("closed").uploadFromByteArray(new byte[0], 0, 0);
+ getBlob("closed").uploadFromByteArray(new byte[0], 0, 0, null, writeOptimisedBlobRequestOptions, null);
} catch (StorageException e) {
throw new IOException(e);
}
diff --git a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/util/AzureRequestOptions.java b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/util/AzureRequestOptions.java
new file mode 100644
index 0000000000..24452d15ea
--- /dev/null
+++ b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/util/AzureRequestOptions.java
@@ -0,0 +1,96 @@
+/*
+ * 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.oak.segment.azure.util;
+
+import com.microsoft.azure.storage.RetryLinearRetry;
+import com.microsoft.azure.storage.blob.BlobRequestOptions;
+
+import java.util.concurrent.TimeUnit;
+
+public class AzureRequestOptions {
+
+ static final String RETRY_ATTEMPTS_PROP = "segment.azure.retry.attempts";
+ static final int DEFAULT_RETRY_ATTEMPTS = 5;
+
+ static final String RETRY_BACKOFF_PROP = "segment.azure.retry.backoff";
+ static final int DEFAULT_RETRY_BACKOFF_SECONDS = 5;
+
+ static final String TIMEOUT_EXECUTION_PROP = "segment.timeout.execution";
+ static final int DEFAULT_TIMEOUT_EXECUTION = 30;
+
+ static final String TIMEOUT_INTERVAL_PROP = "segment.timeout.interval";
+ static final int DEFAULT_TIMEOUT_INTERVAL = 1;
+
+ static final String WRITE_TIMEOUT_EXECUTION_PROP = "segment.write.timeout.execution";
+
+ static final String WRITE_TIMEOUT_INTERVAL_PROP = "segment.write.timeout.interval";
+
+ private AzureRequestOptions() {
+ }
+
+ /**
+ * Apply default request options to the blobRequestOptions if they are not already set.
+ * @param blobRequestOptions
+ */
+ public static void applyDefaultRequestOptions(BlobRequestOptions blobRequestOptions) {
+ if (blobRequestOptions.getRetryPolicyFactory() == null) {
+ int retryAttempts = Integer.getInteger(RETRY_ATTEMPTS_PROP, DEFAULT_RETRY_ATTEMPTS);
+ if (retryAttempts > 0) {
+ Integer retryBackoffSeconds = Integer.getInteger(RETRY_BACKOFF_PROP, DEFAULT_RETRY_BACKOFF_SECONDS);
+ blobRequestOptions.setRetryPolicyFactory(new RetryLinearRetry((int) TimeUnit.SECONDS.toMillis(retryBackoffSeconds), retryAttempts));
+ }
+ }
+ if (blobRequestOptions.getMaximumExecutionTimeInMs() == null) {
+ int timeoutExecution = Integer.getInteger(TIMEOUT_EXECUTION_PROP, DEFAULT_TIMEOUT_EXECUTION);
+ if (timeoutExecution > 0) {
+ blobRequestOptions.setMaximumExecutionTimeInMs((int) TimeUnit.SECONDS.toMillis(timeoutExecution));
+ }
+ }
+ if (blobRequestOptions.getTimeoutIntervalInMs() == null) {
+ int timeoutInterval = Integer.getInteger(TIMEOUT_INTERVAL_PROP, DEFAULT_TIMEOUT_INTERVAL);
+ if (timeoutInterval > 0) {
+ blobRequestOptions.setTimeoutIntervalInMs((int) TimeUnit.SECONDS.toMillis(timeoutInterval));
+ }
+ }
+ }
+
+ /**
+ * Optimise the blob request options for write operations. This method does not change the original blobRequestOptions.
+ * This method also applies the default request options if they are not already set, by calling {@link #applyDefaultRequestOptions(BlobRequestOptions)}
+ * @param blobRequestOptions
+ * @return write optimised blobRequestOptions
+ */
+ public static BlobRequestOptions optimiseForWriteOperations(BlobRequestOptions blobRequestOptions) {
+ BlobRequestOptions writeOptimisedBlobRequestOptions = new BlobRequestOptions(blobRequestOptions);
+ applyDefaultRequestOptions(writeOptimisedBlobRequestOptions);
+
+ Integer writeTimeoutExecution = Integer.getInteger(WRITE_TIMEOUT_EXECUTION_PROP);
+ if (writeTimeoutExecution != null) {
+ writeOptimisedBlobRequestOptions.setMaximumExecutionTimeInMs((int) TimeUnit.SECONDS.toMillis(writeTimeoutExecution));
+ }
+
+ Integer writeTimeoutInterval = Integer.getInteger(WRITE_TIMEOUT_INTERVAL_PROP);
+ if (writeTimeoutInterval != null) {
+ writeOptimisedBlobRequestOptions.setTimeoutIntervalInMs((int) TimeUnit.SECONDS.toMillis(writeTimeoutInterval));
+ }
+
+ return writeOptimisedBlobRequestOptions;
+ }
+}
diff --git a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/util/AzureRequestOptionsTest.java b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/util/AzureRequestOptionsTest.java
new file mode 100644
index 0000000000..7bbfd391a1
--- /dev/null
+++ b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/util/AzureRequestOptionsTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.oak.segment.azure.util;
+
+import com.microsoft.azure.storage.blob.BlobRequestOptions;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+public class AzureRequestOptionsTest {
+
+ private BlobRequestOptions blobRequestOptions;
+
+ @Before
+ public void setUp() {
+ blobRequestOptions = new BlobRequestOptions();
+ }
+
+ @Test
+ public void testApplyDefaultRequestOptions() {
+ AzureRequestOptions.applyDefaultRequestOptions(blobRequestOptions);
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(AzureRequestOptions.DEFAULT_TIMEOUT_EXECUTION)), Long.valueOf(blobRequestOptions.getMaximumExecutionTimeInMs()));
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(AzureRequestOptions.DEFAULT_TIMEOUT_INTERVAL)), Long.valueOf(blobRequestOptions.getTimeoutIntervalInMs()));
+ }
+
+ @Test
+ public void testApplyDefaultRequestOptionsWithCustomTimeouts() {
+ System.setProperty(AzureRequestOptions.TIMEOUT_EXECUTION_PROP, "10");
+ System.setProperty(AzureRequestOptions.TIMEOUT_INTERVAL_PROP, "5");
+
+ AzureRequestOptions.applyDefaultRequestOptions(blobRequestOptions);
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(10)), Long.valueOf(blobRequestOptions.getMaximumExecutionTimeInMs()));
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(5)), Long.valueOf(blobRequestOptions.getTimeoutIntervalInMs()));
+
+ System.clearProperty(AzureRequestOptions.TIMEOUT_EXECUTION_PROP);
+ System.clearProperty(AzureRequestOptions.TIMEOUT_INTERVAL_PROP);
+ }
+
+ @Test
+ public void testOptimiseForWriteOperations() {
+ BlobRequestOptions writeBlobRequestoptions = AzureRequestOptions.optimiseForWriteOperations(blobRequestOptions);
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(AzureRequestOptions.DEFAULT_TIMEOUT_EXECUTION)), Long.valueOf(writeBlobRequestoptions.getMaximumExecutionTimeInMs()));
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(AzureRequestOptions.DEFAULT_TIMEOUT_INTERVAL)), Long.valueOf(writeBlobRequestoptions.getTimeoutIntervalInMs()));
+ }
+
+ @Test
+ public void testOptimiseForWriteOperationsWithCustomTimeouts() {
+ System.setProperty(AzureRequestOptions.WRITE_TIMEOUT_EXECUTION_PROP, "10");
+ System.setProperty(AzureRequestOptions.WRITE_TIMEOUT_INTERVAL_PROP, "5");
+
+ BlobRequestOptions writeBlobRequestoptions = AzureRequestOptions.optimiseForWriteOperations(blobRequestOptions);
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(10)), Long.valueOf(writeBlobRequestoptions.getMaximumExecutionTimeInMs()));
+ assertEquals(Long.valueOf(TimeUnit.SECONDS.toMillis(5)), Long.valueOf(writeBlobRequestoptions.getTimeoutIntervalInMs()));
+
+ System.clearProperty(AzureRequestOptions.WRITE_TIMEOUT_EXECUTION_PROP);
+ System.clearProperty(AzureRequestOptions.WRITE_TIMEOUT_INTERVAL_PROP);
+ }
+}