Merge pull request #993 from andrewgaul/honor-request-timeout-1.5.x

Honor PROPERTY_REQUEST_TIMEOUT in clearContainer
This commit is contained in:
Adrian Cole 2012-11-13 18:54:42 -08:00
commit 15deefa6f3
3 changed files with 47 additions and 6 deletions

View File

@ -27,6 +27,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
@ -63,12 +64,10 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
private final ExecutorService userExecutor; private final ExecutorService userExecutor;
protected final AsyncBlobStore connection; protected final AsyncBlobStore connection;
/** /** Maximum duration in milliseconds of a request. */
* maximum duration of an blob Request
*/
@Inject(optional = true) @Inject(optional = true)
@Named(Constants.PROPERTY_REQUEST_TIMEOUT) @Named(Constants.PROPERTY_REQUEST_TIMEOUT)
protected Long maxTime; protected Long maxTime = Long.MAX_VALUE;
@Inject @Inject
DeleteAllKeysInList(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, DeleteAllKeysInList(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
@ -99,7 +98,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
Future<PageSet<? extends StorageMetadata>> listFuture = Future<PageSet<? extends StorageMetadata>> listFuture =
connection.list(containerName, options); connection.list(containerName, options);
try { try {
listing = listFuture.get(); listing = listFuture.get(maxTime, TimeUnit.MILLISECONDS);
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
break; break;
@ -110,6 +109,13 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
} }
retryHandler.imposeBackoffExponentialDelay(numErrors, message); retryHandler.imposeBackoffExponentialDelay(numErrors, message);
continue; continue;
} catch (TimeoutException te) {
++numErrors;
if (numErrors == maxErrors) {
throw propagate(te);
}
retryHandler.imposeBackoffExponentialDelay(numErrors, message);
continue;
} finally { } finally {
listFuture.cancel(true); listFuture.cancel(true);
} }

View File

@ -18,16 +18,30 @@
*/ */
package org.jclouds.blobstore.strategy.internal; package org.jclouds.blobstore.strategy.internal;
import static org.easymock.EasyMock.anyLong;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import org.jclouds.ContextBuilder; import org.jclouds.ContextBuilder;
import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.util.Throwables2;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.io.Closeables; import com.google.common.io.Closeables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Injector; import com.google.inject.Injector;
/** /**
@ -74,6 +88,27 @@ public class DeleteAllKeysInListTest {
assertEquals(blobstore.countBlobs(containerName), 1111); assertEquals(blobstore.countBlobs(containerName), 1111);
} }
public void testListTimeoutException() throws Exception {
ListenableFuture<PageSet<? extends StorageMetadata>> future = createMock(ListenableFuture.class);
expect(future.get(anyLong(), anyObject(TimeUnit.class))).andThrow(new RuntimeException(new TimeoutException()));
expect(future.cancel(true)).andReturn(true);
replay(future);
AsyncBlobStore asyncBlobStore = createMock(AsyncBlobStore.class);
expect(asyncBlobStore.list(anyObject(String.class), anyObject(ListContainerOptions.class))).andReturn(future);
replay(asyncBlobStore);
deleter = new DeleteAllKeysInList(null, asyncBlobStore, null);
try {
deleter.execute(containerName, ListContainerOptions.NONE);
fail();
} catch (Exception e) {
if (Throwables2.getFirstThrowableOfType(e, TimeoutException.class) == null) {
throw e;
}
}
}
/** /**
* Create a container "container" with 1111 blobs named "blob-%d". Create a * Create a container "container" with 1111 blobs named "blob-%d". Create a
* subdirectory "directory" which contains 2222 more blobs named * subdirectory "directory" which contains 2222 more blobs named

View File

@ -154,7 +154,7 @@ public interface Constants {
/** /**
* Long property. * Long property.
* <p/> * <p/>
* longest time a single request can take before throwing an exception. * Maximum duration in milliseconds a single request can take before throwing an exception.
*/ */
public static final String PROPERTY_REQUEST_TIMEOUT = "jclouds.request-timeout"; public static final String PROPERTY_REQUEST_TIMEOUT = "jclouds.request-timeout";
/** /**