removed redundant retrying assertion code

This commit is contained in:
Adrian Cole 2013-01-12 14:04:47 -08:00
parent cca73d8a69
commit 015fbf22a2
6 changed files with 70 additions and 132 deletions

View File

@ -17,6 +17,7 @@
* under the License. * under the License.
*/ */
package org.jclouds.atmos.util; package org.jclouds.atmos.util;
import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
@ -31,6 +32,7 @@ import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.filters.SignRequest; import org.jclouds.atmos.filters.SignRequest;
import org.jclouds.atmos.options.PutOptions; import org.jclouds.atmos.options.PutOptions;
import org.jclouds.atmos.xml.ErrorHandler; import org.jclouds.atmos.xml.ErrorHandler;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Crypto;
@ -38,9 +40,9 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax; 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 * 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); sync.createFile(container, object, options);
} catch(KeyAlreadyExistsException e) { } catch(KeyAlreadyExistsException e) {
deleteAndEnsureGone(sync, path); deletePathAndEnsureGone(sync, path);
sync.createFile(container, object, options); sync.createFile(container, object, options);
} }
return path; return path;
} }
public static void deleteAndEnsureGone(final AtmosClient sync, final String path) { public static void deletePathAndEnsureGone(final AtmosClient sync, String path) {
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try { try {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() { sync.deletePath(in);
public Boolean get() { return !sync.pathExists(in);
sync.deletePath(path); } catch (ContainerNotFoundException e) {
return !sync.pathExists(path); 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) public AtmosError parseAtmosErrorFromContent(HttpCommand command, HttpResponse response, String content)

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.atmos; package org.jclouds.atmos;
import static com.google.common.base.Preconditions.checkState;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail; 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.FileType;
import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.atmos.domain.SystemMetadata;
import org.jclouds.atmos.options.ListOptions; import org.jclouds.atmos.options.ListOptions;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.InputStreamPayload; import org.jclouds.io.payloads.InputStreamPayload;
import org.jclouds.util.Assertions; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import org.testng.annotations.Test; 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.base.Throwables;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; 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 { TimeoutException {
try { try {
getApi().deletePath(path); getApi().deletePath(path);
} catch (KeyNotFoundException ex) { } catch (KeyNotFoundException ex) {
} }
assert Assertions.eventuallyTrue(new Supplier<Boolean>() { checkState(new RetryablePredicate<String>(new Predicate<String>() {
public Boolean get() { public boolean apply(String in) {
return !getApi().pathExists(path); 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 { protected void retryAndCheckSystemMetadataAndPutIfPresentReplaceStrategy(AtmosObject object) throws Exception {

View File

@ -19,6 +19,7 @@
package org.jclouds.s3.blobstore; package org.jclouds.s3.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Set; import java.util.Set;
@ -42,6 +43,7 @@ import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.s3.S3Client; import org.jclouds.s3.S3Client;
import org.jclouds.s3.blobstore.functions.BlobToObject; import org.jclouds.s3.blobstore.functions.BlobToObject;
import org.jclouds.s3.blobstore.functions.BucketToResourceList; 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.PutBucketOptions;
import org.jclouds.s3.options.PutObjectOptions; import org.jclouds.s3.options.PutObjectOptions;
import org.jclouds.s3.util.S3Utils; import org.jclouds.s3.util.S3Utils;
import org.jclouds.util.Assertions;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
@ -148,38 +150,20 @@ public class S3BlobStore extends BaseBlobStore {
} }
/** /**
* This implementation invokes {@link #deleteAndEnsurePathGone} * This implementation invokes {@link #clearContainer} then {@link S3Client#deleteBucketIfEmpty} until it is true.
*
* @param container
* bucket name
*/ */
@Override @Override
public void deleteContainer(String container) { protected void deletePathAndEnsureGone(String path) {
clearAndDeleteContainer(container); checkState(new RetryablePredicate<String>(new Predicate<String>() {
} public boolean apply(String in) {
/**
* This implementation invokes {@link #clearContainer} then {@link S3Client#deleteBucketIfEmpty}
* until it is true.
*/
public void clearAndDeleteContainer(final String container) {
try { try {
//TODO: probably it is better to use a retryable predicate clearContainer(in);
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() { return sync.deleteBucketIfEmpty(in);
public Boolean get() {
try {
clearContainer(container);
return sync.deleteBucketIfEmpty(container);
} catch (ContainerNotFoundException e) { } catch (ContainerNotFoundException e) {
return true; return true;
} }
} }
}, 30000)) { }, 30000).apply(path), "%s still exists after deleting!", path);
throw new IllegalStateException(container + " still exists after deleting!");
}
} catch (InterruptedException e) {
throw new IllegalStateException(container + " interrupted during deletion!", e);
}
} }
/** /**

View File

@ -19,6 +19,7 @@
package org.jclouds.blobstore.internal; package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull; 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 static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import java.util.Set; import java.util.Set;
@ -38,10 +39,12 @@ import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; 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.base.Supplier;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; 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<Void>() { return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception { public Void call() throws Exception {
deleteAndEnsurePathGone(container); deletePathAndEnsureGone(container);
return null; return null;
} }
@ -265,24 +268,17 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
}), service); }), service);
} }
protected void deleteAndEnsurePathGone(final String container) { protected void deletePathAndEnsureGone(String path) {
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try { try {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() { clearContainer(in, recursive());
public Boolean get() { return deleteAndVerifyContainerGone(in);
try {
clearContainer(container, recursive());
return deleteAndVerifyContainerGone(container);
} catch (ContainerNotFoundException e) { } catch (ContainerNotFoundException e) {
return true; return true;
} }
} }
}, 30000).apply(path), "%s still exists after deleting!", path);
}, 30000)) {
throw new IllegalStateException(container + " still exists after deleting!");
}
} catch (InterruptedException e) {
throw new IllegalStateException(container + " interrupted during deletion!", e);
}
} }
@Override @Override

View File

@ -19,6 +19,7 @@
package org.jclouds.blobstore.internal; package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull; 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 static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import java.util.Set; import java.util.Set;
@ -34,10 +35,12 @@ import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location; 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.base.Supplier;
/** /**
@ -189,28 +192,21 @@ public abstract class BaseBlobStore implements BlobStore {
* bucket name * bucket name
*/ */
@Override @Override
public void deleteContainer(final String container) { public void deleteContainer(String container) {
clearAndDeleteContainer(container); deletePathAndEnsureGone(container);
} }
protected void clearAndDeleteContainer(final String container) { protected void deletePathAndEnsureGone(String path) {
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try { try {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() { clearContainer(in, recursive());
public Boolean get() { return deleteAndVerifyContainerGone(in);
try {
clearContainer(container, recursive());
return deleteAndVerifyContainerGone(container);
} catch (ContainerNotFoundException e) { } catch (ContainerNotFoundException e) {
return true; return true;
} }
} }
}, 30000).apply(path), "%s still exists after deleting!", path);
}, 30000)) {
throw new IllegalStateException(container + " still exists after deleting!");
}
} catch (InterruptedException e) {
throw new IllegalStateException(container + " interrupted during deletion!", e);
}
} }
@Override @Override

View File

@ -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<Boolean> assertion, long inconsistencyMillis)
throws InterruptedException {
for (int i = 0; i < 30; i++) {
if (!assertion.get()) {
Thread.sleep(inconsistencyMillis / 30);
continue;
}
return true;
}
return false;
}
}