Permalink
Browse files

Merge pull request #27 from jcookems/pullFromPublic

Pull from public
  • Loading branch information...
2 parents 410e861 + a7df73a commit 08504f7f230dae3d07fbc14fa19c66948ae00bea @jcookems jcookems committed Jan 11, 2013
@@ -327,7 +327,7 @@
/**
* Specifies the value to use for UserAgent header.
*/
- public static final String USER_AGENT_VERSION = "Client v0.1.3";
+ public static final String USER_AGENT_VERSION = "Client v0.1.3.1";
}
/**
@@ -54,6 +54,15 @@
private ArrayList<RequestResult> requestResults;
/**
+ * Represents an event that is triggered before sending a request.
+ *
+ * @see StorageEvent
+ * @see StorageEventMultiCaster
+ * @see SendingRequestEvent
+ */
+ private StorageEventMultiCaster<SendingRequestEvent, StorageEvent<SendingRequestEvent>> sendingRequestEventHandler = new StorageEventMultiCaster<SendingRequestEvent, StorageEvent<SendingRequestEvent>>();
+
+ /**
* Represents an event that is triggered when a response is received from the storage service while processing a
* request.
*
@@ -83,7 +92,7 @@
* Reserved for internal use.
*/
// Used internally for download resume.
- private volatile int currentOperationByteCount;
+ private volatile long currentOperationByteCount;
/**
* Creates an instance of the <code>OperationContext</code> class.
@@ -103,7 +112,7 @@ public long getClientTimeInMs() {
/**
* @return the currentOperationByteCount
*/
- public int getCurrentOperationByteCount() {
+ public long getCurrentOperationByteCount() {
return this.currentOperationByteCount;
}
@@ -157,6 +166,13 @@ private Logger getLogger() {
}
/**
+ * @return the SendingRequestEvent
+ */
+ public StorageEventMultiCaster<SendingRequestEvent, StorageEvent<SendingRequestEvent>> getSendingRequestEventHandler() {
+ return this.sendingRequestEventHandler;
+ }
+
+ /**
* @return the responseReceivedEventHandler
*/
public StorageEventMultiCaster<ResponseReceivedEvent, StorageEvent<ResponseReceivedEvent>> getResponseReceivedEventHandler() {
@@ -187,7 +203,7 @@ public void setClientTimeInMs(final long clientTimeInMs) {
* @param currentOperationByteCount
* the currentOperationByteCount to set
*/
- public void setCurrentOperationByteCount(final int currentOperationByteCount) {
+ public void setCurrentOperationByteCount(final long currentOperationByteCount) {
this.currentOperationByteCount = currentOperationByteCount;
}
@@ -219,6 +235,15 @@ private void setLogger(final Logger logger) {
}
/**
+ * @param sendingRequestEventHandler
+ * the sendingRequestEventHandler to set
+ */
+ public void setSendingRequestEventHandler(
+ final StorageEventMultiCaster<SendingRequestEvent, StorageEvent<SendingRequestEvent>> sendingRequestEventHandler) {
+ this.sendingRequestEventHandler = sendingRequestEventHandler;
+ }
+
+ /**
* @param responseReceivedEventHandler
* the responseReceivedEventHandler to set
*/
@@ -0,0 +1,63 @@
+/**
+ * Copyright Microsoft Corporation
+ *
+ * Licensed 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 com.microsoft.windowsazure.services.core.storage;
+
+/**
+ * Represents an event that is fired when before sending a request.
+ */
+public final class SendingRequestEvent {
+
+ /**
+ * Represents a connection object. Currently only <code>java.net.HttpURLConnection</code> is supported as a
+ * connection object.
+ */
+ private final Object connectionObject;
+
+ /**
+ * Represents a context for the current operation. This object is used to track requests to the storage service, and
+ * to provide additional runtime information about the operation.
+ */
+ private final OperationContext opContext;
+
+ /**
+ * Creates an instance of the <code>SendingRequestEvent</code> class.
+ *
+ * @param opContext
+ * An {@link OperationContext} object that represents the context for the current operation. This object
+ * is used to track requests to the storage service, and to provide additional runtime information about
+ * the operation.
+ * @param connectionObject
+ * Represents a connection object. Currently only <code>java.net.HttpURLConnection</code> is supported as
+ * a connection object.
+ */
+ public SendingRequestEvent(final OperationContext opContext, final Object connectionObject) {
+ this.opContext = opContext;
+ this.connectionObject = connectionObject;
+ }
+
+ /**
+ * @return the connectionObject
+ */
+ public Object getConnectionObject() {
+ return this.connectionObject;
+ }
+
+ /**
+ * @return the opContext
+ */
+ public OperationContext getOpContext() {
+ return this.opContext;
+ }
+}
@@ -33,6 +33,7 @@
import com.microsoft.windowsazure.services.core.storage.RetryPolicy;
import com.microsoft.windowsazure.services.core.storage.RetryPolicyFactory;
import com.microsoft.windowsazure.services.core.storage.RetryResult;
+import com.microsoft.windowsazure.services.core.storage.SendingRequestEvent;
import com.microsoft.windowsazure.services.core.storage.StorageErrorCodeStrings;
import com.microsoft.windowsazure.services.core.storage.StorageException;
import com.microsoft.windowsazure.services.table.client.TableServiceException;
@@ -223,6 +224,11 @@ public static InputStream getInputStream(final HttpURLConnection request, final
opContext.setCurrentRequestObject(request);
currResult.setStartDate(new Date());
opContext.getRequestResults().add(currResult);
+
+ if (opContext.getSendingRequestEventHandler().hasListeners()) {
+ opContext.getSendingRequestEventHandler().fireEvent(new SendingRequestEvent(opContext, request));
+ }
+
try {
return request.getInputStream();
}
@@ -295,6 +301,10 @@ public static RequestResult processRequest(final HttpURLConnection request, fina
opContext.getRequestResults().add(currResult);
opContext.setCurrentRequestObject(request);
+ if (opContext.getSendingRequestEventHandler().hasListeners()) {
+ opContext.getSendingRequestEventHandler().fireEvent(new SendingRequestEvent(opContext, request));
+ }
+
// Send the request
currResult.setStatusCode(request.getResponseCode());
currResult.setStatusMessage(request.getResponseMessage());
@@ -38,8 +38,11 @@
import com.microsoft.windowsazure.services.core.storage.AccessCondition;
import com.microsoft.windowsazure.services.core.storage.OperationContext;
import com.microsoft.windowsazure.services.core.storage.ResultSegment;
+import com.microsoft.windowsazure.services.core.storage.RetryNoRetry;
+import com.microsoft.windowsazure.services.core.storage.SendingRequestEvent;
import com.microsoft.windowsazure.services.core.storage.StorageCredentialsSharedAccessSignature;
import com.microsoft.windowsazure.services.core.storage.StorageErrorCodeStrings;
+import com.microsoft.windowsazure.services.core.storage.StorageEvent;
import com.microsoft.windowsazure.services.core.storage.StorageException;
/**
@@ -671,4 +674,100 @@ public void testListContainersTest() throws StorageException, URISyntaxException
null);
}
}
+
+ @Test
+ public void testSendingRequestEventBlob() throws StorageException, URISyntaxException, IOException,
+ InterruptedException {
+ String name = generateRandomContainerName();
+ CloudBlobContainer newContainer = bClient.getContainerReference(name);
+ newContainer.create();
+
+ final ArrayList<Boolean> callList = new ArrayList<Boolean>();
+ OperationContext sendingRequestEventContext = new OperationContext();
+ sendingRequestEventContext.getSendingRequestEventHandler().addListener(new StorageEvent<SendingRequestEvent>() {
+
+ @Override
+ public void eventOccurred(SendingRequestEvent eventArg) {
+ callList.add(true);
+ }
+ });
+
+ try {
+ Assert.assertEquals(0, callList.size());
+
+ //Put blob
+ CloudBlob blob = newContainer.getBlockBlobReference("newblob");
+ blob.upload(new ByteArrayInputStream(testData), testData.length, null, null, sendingRequestEventContext);
+ Assert.assertEquals(1, callList.size());
+
+ //Get blob
+ blob.download(new ByteArrayOutputStream(), null, null, sendingRequestEventContext);
+ Assert.assertEquals(2, callList.size());
+
+ //uploadMetadata
+ blob.uploadMetadata(null, null, sendingRequestEventContext);
+ Assert.assertEquals(3, callList.size());
+
+ //uploadMetadata
+ blob.downloadAttributes(null, null, sendingRequestEventContext);
+ Assert.assertEquals(4, callList.size());
+
+ }
+ finally {
+ // cleanup
+ newContainer.deleteIfExists();
+ }
+ }
+
+ @Test
+ public void testCurrentOperationByteCount() throws URISyntaxException, StorageException, IOException {
+ final int blockLength = 4 * 1024 * 1024;
+ final Random randGenerator = new Random();
+ String blobName = "testblob" + Integer.toString(randGenerator.nextInt(50000));
+ blobName = blobName.replace('-', '_');
+
+ final CloudBlobContainer containerRef = bClient.getContainerReference(BlobTestBase.testSuiteContainerName);
+
+ final CloudBlockBlob blobRef = containerRef.getBlockBlobReference(blobName);
+
+ final ArrayList<byte[]> byteList = new ArrayList<byte[]>();
+ final ArrayList<BlockEntry> blockList = new ArrayList<BlockEntry>();
+
+ int numberOfBlocks = 4;
+
+ for (int m = 0; m < numberOfBlocks; m++) {
+ final byte[] buff = new byte[blockLength];
+ randGenerator.nextBytes(buff);
+ byteList.add(buff);
+ blobRef.uploadBlock("ABC" + m, new ByteArrayInputStream(buff), blockLength);
+
+ blockList.add(new BlockEntry("ABC" + m, BlockSearchMode.LATEST));
+ }
+
+ blobRef.commitBlockList(blockList);
+
+ OperationContext operationContext = new OperationContext();
+ BlobRequestOptions options = new BlobRequestOptions();
+ options.setTimeoutIntervalInMs(1000);
+ options.setRetryPolicyFactory(new RetryNoRetry());
+ try {
+ final ByteArrayOutputStream downloadedDataStream = new ByteArrayOutputStream();
+ blobRef.download(downloadedDataStream, null, options, operationContext);
+ }
+ catch (Exception e) {
+ Assert.assertEquals(0, operationContext.getCurrentOperationByteCount());
+ }
+
+ operationContext = new OperationContext();
+ options = new BlobRequestOptions();
+ options.setTimeoutIntervalInMs(90000);
+
+ final ByteArrayOutputStream downloadedDataStream = new ByteArrayOutputStream();
+ blobRef.download(downloadedDataStream, null, options, operationContext);
+
+ Assert.assertEquals(blockLength * numberOfBlocks, operationContext.getCurrentOperationByteCount());
+
+ blobRef.delete();
+ }
+
}

0 comments on commit 08504f7

Please sign in to comment.