diff --git a/apis/atmos/src/main/java/org/jclouds/atmos/util/AtmosUtils.java b/apis/atmos/src/main/java/org/jclouds/atmos/util/AtmosUtils.java index 91efe6bf44..a86c6625ba 100644 --- a/apis/atmos/src/main/java/org/jclouds/atmos/util/AtmosUtils.java +++ b/apis/atmos/src/main/java/org/jclouds/atmos/util/AtmosUtils.java @@ -17,6 +17,7 @@ * under the License. */ package org.jclouds.atmos.util; +import static com.google.common.base.Preconditions.checkState; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -31,6 +32,7 @@ import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.filters.SignRequest; import org.jclouds.atmos.options.PutOptions; import org.jclouds.atmos.xml.ErrorHandler; +import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.domain.Blob; import org.jclouds.crypto.Crypto; @@ -38,9 +40,9 @@ import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpException; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseSax; -import org.jclouds.util.Assertions; +import org.jclouds.predicates.RetryablePredicate; -import com.google.common.base.Supplier; +import com.google.common.base.Predicate; /** * Encryption, Hashing, and IO Utilities needed to sign and verify Atmos Storage requests and @@ -78,25 +80,23 @@ public class AtmosUtils { sync.createFile(container, object, options); } catch(KeyAlreadyExistsException e) { - deleteAndEnsureGone(sync, path); + deletePathAndEnsureGone(sync, path); sync.createFile(container, object, options); } return path; } - - public static void deleteAndEnsureGone(final AtmosClient sync, final String path) { - try { - if (!Assertions.eventuallyTrue(new Supplier() { - public Boolean get() { - sync.deletePath(path); - return !sync.pathExists(path); + + public static void deletePathAndEnsureGone(final AtmosClient sync, String path) { + checkState(new RetryablePredicate(new Predicate() { + public boolean apply(String in) { + try { + sync.deletePath(in); + return !sync.pathExists(in); + } catch (ContainerNotFoundException e) { + return true; } - }, 3000)) { - throw new IllegalStateException(path + " still exists after deleting!"); } - } catch (InterruptedException e) { - throw new IllegalStateException(path + " interrupted during deletion!", e); - } + }, 3000).apply(path), "%s still exists after deleting!", path); } public AtmosError parseAtmosErrorFromContent(HttpCommand command, HttpResponse response, String content) diff --git a/apis/atmos/src/test/java/org/jclouds/atmos/AtmosClientLiveTest.java b/apis/atmos/src/test/java/org/jclouds/atmos/AtmosClientLiveTest.java index 33c558ea59..7581d5e46a 100644 --- a/apis/atmos/src/test/java/org/jclouds/atmos/AtmosClientLiveTest.java +++ b/apis/atmos/src/test/java/org/jclouds/atmos/AtmosClientLiveTest.java @@ -18,6 +18,7 @@ */ package org.jclouds.atmos; +import static com.google.common.base.Preconditions.checkState; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; @@ -34,17 +35,18 @@ import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.atmos.options.ListOptions; +import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest; import org.jclouds.http.HttpResponseException; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.InputStreamPayload; -import org.jclouds.util.Assertions; +import org.jclouds.predicates.RetryablePredicate; import org.jclouds.util.Strings2; import org.testng.annotations.Test; -import com.google.common.base.Supplier; +import com.google.common.base.Predicate; import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; @@ -320,17 +322,21 @@ public class AtmosClientLiveTest extends BaseBlobStoreIntegrationTest { } - protected void deleteConsistencyAware(final String path) throws InterruptedException, ExecutionException, + protected void deleteConsistencyAware(String path) throws InterruptedException, ExecutionException, TimeoutException { try { getApi().deletePath(path); } catch (KeyNotFoundException ex) { } - assert Assertions.eventuallyTrue(new Supplier() { - public Boolean get() { - return !getApi().pathExists(path); + checkState(new RetryablePredicate(new Predicate() { + public boolean apply(String in) { + try { + return !getApi().pathExists(in); + } catch (ContainerNotFoundException e) { + return true; + } } - }, INCONSISTENCY_WINDOW); + }, INCONSISTENCY_WINDOW).apply(path), "%s still exists after deleting!", path); } protected void retryAndCheckSystemMetadataAndPutIfPresentReplaceStrategy(AtmosObject object) throws Exception { diff --git a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java index 4d6b295efa..71227952f3 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java +++ b/apis/s3/src/main/java/org/jclouds/s3/blobstore/S3BlobStore.java @@ -19,6 +19,7 @@ package org.jclouds.s3.blobstore; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import java.util.Set; @@ -42,6 +43,7 @@ import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.collect.Memoized; import org.jclouds.domain.Location; import org.jclouds.http.options.GetOptions; +import org.jclouds.predicates.RetryablePredicate; import org.jclouds.s3.S3Client; import org.jclouds.s3.blobstore.functions.BlobToObject; import org.jclouds.s3.blobstore.functions.BucketToResourceList; @@ -57,9 +59,9 @@ import org.jclouds.s3.options.ListBucketOptions; import org.jclouds.s3.options.PutBucketOptions; import org.jclouds.s3.options.PutObjectOptions; import org.jclouds.s3.util.S3Utils; -import org.jclouds.util.Assertions; import com.google.common.base.Function; +import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -148,38 +150,20 @@ public class S3BlobStore extends BaseBlobStore { } /** - * This implementation invokes {@link #deleteAndEnsurePathGone} - * - * @param container - * bucket name + * This implementation invokes {@link #clearContainer} then {@link S3Client#deleteBucketIfEmpty} until it is true. */ @Override - public void deleteContainer(String container) { - clearAndDeleteContainer(container); - } - - /** - * This implementation invokes {@link #clearContainer} then {@link S3Client#deleteBucketIfEmpty} - * until it is true. - */ - public void clearAndDeleteContainer(final String container) { - try { - //TODO: probably it is better to use a retryable predicate - if (!Assertions.eventuallyTrue(new Supplier() { - public Boolean get() { - try { - clearContainer(container); - return sync.deleteBucketIfEmpty(container); - } catch (ContainerNotFoundException e) { - return true; - } + protected void deletePathAndEnsureGone(String path) { + checkState(new RetryablePredicate(new Predicate() { + public boolean apply(String in) { + try { + clearContainer(in); + return sync.deleteBucketIfEmpty(in); + } catch (ContainerNotFoundException e) { + return true; } - }, 30000)) { - throw new IllegalStateException(container + " still exists after deleting!"); } - } catch (InterruptedException e) { - throw new IllegalStateException(container + " interrupted during deletion!", e); - } + }, 30000).apply(path), "%s still exists after deleting!", path); } /** diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java index c00e067bbe..a6bf83c17d 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseAsyncBlobStore.java @@ -19,6 +19,7 @@ package org.jclouds.blobstore.internal; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; import java.util.Set; @@ -38,10 +39,12 @@ import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.util.BlobUtils; +import org.jclouds.blobstore.util.internal.BlobUtilsImpl; import org.jclouds.collect.Memoized; import org.jclouds.domain.Location; -import org.jclouds.util.Assertions; +import org.jclouds.predicates.RetryablePredicate; +import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -254,7 +257,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore { return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable() { public Void call() throws Exception { - deleteAndEnsurePathGone(container); + deletePathAndEnsureGone(container); return null; } @@ -265,24 +268,17 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore { }), service); } - protected void deleteAndEnsurePathGone(final String container) { - try { - if (!Assertions.eventuallyTrue(new Supplier() { - public Boolean get() { - try { - clearContainer(container, recursive()); - return deleteAndVerifyContainerGone(container); - } catch (ContainerNotFoundException e) { - return true; - } + protected void deletePathAndEnsureGone(String path) { + checkState(new RetryablePredicate(new Predicate() { + public boolean apply(String in) { + try { + clearContainer(in, recursive()); + return deleteAndVerifyContainerGone(in); + } catch (ContainerNotFoundException e) { + return true; } - - }, 30000)) { - throw new IllegalStateException(container + " still exists after deleting!"); } - } catch (InterruptedException e) { - throw new IllegalStateException(container + " interrupted during deletion!", e); - } + }, 30000).apply(path), "%s still exists after deleting!", path); } @Override diff --git a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java index a28afdb164..b91f8816e8 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/internal/BaseBlobStore.java @@ -19,6 +19,7 @@ package org.jclouds.blobstore.internal; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; import java.util.Set; @@ -34,10 +35,12 @@ import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.util.BlobUtils; +import org.jclouds.blobstore.util.internal.BlobUtilsImpl; import org.jclouds.collect.Memoized; import org.jclouds.domain.Location; -import org.jclouds.util.Assertions; +import org.jclouds.predicates.RetryablePredicate; +import com.google.common.base.Predicate; import com.google.common.base.Supplier; /** @@ -189,28 +192,21 @@ public abstract class BaseBlobStore implements BlobStore { * bucket name */ @Override - public void deleteContainer(final String container) { - clearAndDeleteContainer(container); + public void deleteContainer(String container) { + deletePathAndEnsureGone(container); } - protected void clearAndDeleteContainer(final String container) { - try { - if (!Assertions.eventuallyTrue(new Supplier() { - public Boolean get() { - try { - clearContainer(container, recursive()); - return deleteAndVerifyContainerGone(container); - } catch (ContainerNotFoundException e) { - return true; - } + protected void deletePathAndEnsureGone(String path) { + checkState(new RetryablePredicate(new Predicate() { + public boolean apply(String in) { + try { + clearContainer(in, recursive()); + return deleteAndVerifyContainerGone(in); + } catch (ContainerNotFoundException e) { + return true; } - - }, 30000)) { - throw new IllegalStateException(container + " still exists after deleting!"); } - } catch (InterruptedException e) { - throw new IllegalStateException(container + " interrupted during deletion!", e); - } + }, 30000).apply(path), "%s still exists after deleting!", path); } @Override diff --git a/core/src/main/java/org/jclouds/util/Assertions.java b/core/src/main/java/org/jclouds/util/Assertions.java deleted file mode 100644 index c81ad0d1db..0000000000 --- a/core/src/main/java/org/jclouds/util/Assertions.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds 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.jclouds.util; - -import com.google.common.base.Supplier; - -/** - * - * @author Adrian Cole - */ -public class Assertions { - - public static boolean eventuallyTrue(Supplier assertion, long inconsistencyMillis) - throws InterruptedException { - - for (int i = 0; i < 30; i++) { - if (!assertion.get()) { - Thread.sleep(inconsistencyMillis / 30); - continue; - } - return true; - } - return false; - } - - - -}