summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE-NOTES.txt1
-rw-r--r--src/main/java/com/amazon/carbonado/spi/StorageCollection.java57
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;