diff options
-rw-r--r-- | RELEASE-NOTES.txt | 1 | ||||
-rw-r--r-- | src/main/java/com/amazon/carbonado/spi/StorageCollection.java | 57 |
2 files changed, 33 insertions, 25 deletions
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 6373977..da82d27 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -4,6 +4,7 @@ Carbonado change history 1.1-BETA4 to 1.1-BETA5
-------------------------------
- More fixes in resync corruption repair logic.
+- Fixed deadlock when using unsupported Storage for the first time.
1.1-BETA3 to 1.1-BETA4
-------------------------------
diff --git a/src/main/java/com/amazon/carbonado/spi/StorageCollection.java b/src/main/java/com/amazon/carbonado/spi/StorageCollection.java index f0d38ad..45ab6f5 100644 --- a/src/main/java/com/amazon/carbonado/spi/StorageCollection.java +++ b/src/main/java/com/amazon/carbonado/spi/StorageCollection.java @@ -70,35 +70,42 @@ public abstract class StorageCollection { }
}
- synchronized (lock) {
- // Check storage map again before creating new storage.
- while (true) {
- storage = mStorageMap.get(type);
- if (storage != null) {
- return storage;
- }
- if (doCreate) {
- break;
- }
- try {
- lock.wait();
- } catch (InterruptedException e) {
- throw new RepositoryException("Interrupted");
- }
- }
+ if (Thread.holdsLock(lock)) {
+ throw new IllegalStateException
+ ("Recursively trying to create storage for type: " + type);
+ }
- // Examine and throw exception early if there is a problem.
- StorableIntrospector.examine(type);
+ try {
+ synchronized (lock) {
+ // Check storage map again before creating new storage.
+ while (true) {
+ storage = mStorageMap.get(type);
+ if (storage != null) {
+ return storage;
+ }
+ if (doCreate) {
+ break;
+ }
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ throw new RepositoryException("Interrupted");
+ }
+ }
- storage = createStorage(type);
+ // Examine and throw exception early if there is a problem.
+ StorableIntrospector.examine(type);
- mStorageMap.put(type, storage);
- lock.notifyAll();
- }
+ storage = createStorage(type);
- // Storable type lock no longer needed.
- synchronized (mStorableTypeLockMap) {
- mStorableTypeLockMap.remove(type);
+ mStorageMap.put(type, storage);
+ lock.notifyAll();
+ }
+ } finally {
+ // Storable type lock no longer needed.
+ synchronized (mStorableTypeLockMap) {
+ mStorableTypeLockMap.remove(type);
+ }
}
return storage;
|