diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2013-04-13 22:55:38 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2013-04-13 22:55:38 +0000 |
commit | b926a082939c526d80bbab293eee1a2e2b1413a7 (patch) | |
tree | d83eddf0b9e6c21b9508f4991773deedb51ef34e | |
parent | f54bb9107d4f1a4285c67205c6973de437923be9 (diff) |
Index triggers only use "for update" mode when the strict option is supplied.
6 files changed, 94 insertions, 31 deletions
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/DerivedIndexesTrigger.java b/src/main/java/com/amazon/carbonado/repo/indexed/DerivedIndexesTrigger.java index 8f2afde..e18accf 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/DerivedIndexesTrigger.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/DerivedIndexesTrigger.java @@ -75,13 +75,7 @@ class DerivedIndexesTrigger<S extends Storable, D extends Storable> extends Trig }
@Override
- public Object beforeTryDelete(Transaction txn, S storable) throws PersistException {
- return beforeDelete(txn, storable);
- }
-
- @Override
- public Object beforeDelete(Transaction txn, S storable) throws PersistException {
- txn.setForUpdate(true);
+ public Object beforeDelete(S storable) throws PersistException {
try {
if (storable.copy().tryLoad()) {
return createDependentIndexEntries(storable);
@@ -175,4 +169,30 @@ class DerivedIndexesTrigger<S extends Storable, D extends Storable> extends Trig newIndexEntry.tryInsert();
}
}
+
+ /**
+ * Ensure old storable instance is loaded with an upgradable lock, allowing change to
+ * proceed without deadlock.
+ */
+ final static class Strict<S extends Storable, D extends Storable>
+ extends DerivedIndexesTrigger<S, D>
+ {
+ Strict(IndexedRepository repository,
+ Class<S> sType, ChainedProperty<D> derivedTo)
+ throws RepositoryException
+ {
+ super(repository, sType, derivedTo);
+ }
+
+ @Override
+ public Object beforeTryDelete(Transaction txn, S storable) throws PersistException {
+ return beforeDelete(txn, storable);
+ }
+
+ @Override
+ public Object beforeDelete(Transaction txn, S storable) throws PersistException {
+ txn.setForUpdate(true);
+ return super.beforeDelete(storable);
+ }
+ }
}
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java index e44964b..1ec12ad 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexAnalysis.java @@ -278,7 +278,11 @@ class IndexAnalysis<S extends Storable> { managedIndexes[i++] = managedIndex;
}
- indexesTrigger = new IndexesTrigger<S>(managedIndexes);
+ if (repository.isStrictTriggers()) {
+ indexesTrigger = new IndexesTrigger.Strict<S>(managedIndexes);
+ } else {
+ indexesTrigger = new IndexesTrigger<S>(managedIndexes);
+ }
}
derivedToDependencies = gatherDerivedToDependencies(info);
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepository.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepository.java index 91b6615..26b8ea8 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepository.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepository.java @@ -64,6 +64,7 @@ class IndexedRepository implements Repository, private final boolean mIndexRepairEnabled;
private final double mIndexThrottle;
private final boolean mAllClustered;
+ private final boolean mStrictTriggers;
private final StoragePool mStoragePool;
private final IndexAnalysisPool mIndexAnalysisPool;
@@ -71,7 +72,8 @@ class IndexedRepository implements Repository, Repository repository,
boolean indexRepairEnabled,
double indexThrottle,
- boolean allClustered)
+ boolean allClustered,
+ boolean strictTriggers)
{
if (repository.getCapability(IndexInfoCapability.class) == null) {
throw new UnsupportedOperationException
@@ -85,6 +87,7 @@ class IndexedRepository implements Repository, mIndexRepairEnabled = indexRepairEnabled;
mIndexThrottle = indexThrottle;
mAllClustered = allClustered;
+ mStrictTriggers = strictTriggers;
mIndexAnalysisPool = new IndexAnalysisPool(this);
mStoragePool = new StoragePool() {
@@ -264,4 +267,8 @@ class IndexedRepository implements Repository, boolean isAllClustered() {
return mAllClustered;
}
+
+ boolean isStrictTriggers() {
+ return mStrictTriggers;
+ }
}
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepositoryBuilder.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepositoryBuilder.java index fa974fd..27b8011 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepositoryBuilder.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedRepositoryBuilder.java @@ -50,6 +50,7 @@ public class IndexedRepositoryBuilder extends AbstractRepositoryBuilder { private boolean mIndexRepairEnabled = true;
private double mIndexThrottle = 1.0;
private boolean mAllClustered;
+ private boolean mStrictTriggers;
public IndexedRepositoryBuilder() {
}
@@ -77,7 +78,8 @@ public class IndexedRepositoryBuilder extends AbstractRepositoryBuilder { Repository repo = new IndexedRepository(rootRef, getName(), wrapped,
isIndexRepairEnabled(),
getIndexRepairThrottle(),
- isAllClustered());
+ isAllClustered(),
+ mStrictTriggers);
rootRef.set(repo);
return repo;
}
@@ -190,6 +192,14 @@ public class IndexedRepositoryBuilder extends AbstractRepositoryBuilder { mAllClustered = clustered;
}
+ /**
+ * Set to true to require that index maintenance triggers use a "for update" transaction,
+ * avoiding deadlocks and lock upgrade failures.
+ */
+ public void setStrictTriggers(boolean strict) {
+ mStrictTriggers = strict;
+ }
+
@Override
public void errorCheck(Collection<String> messages) throws ConfigurationException {
super.errorCheck(messages);
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java index b00b0b4..eec8522 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java @@ -112,7 +112,15 @@ class IndexedStorage<S extends Storable> implements Storage<S>, StorageAccess<S> // Install triggers to manage derived properties in external Storables.
if (analysis.derivedToDependencies != null) {
for (ChainedProperty<?> derivedTo : analysis.derivedToDependencies) {
- addTrigger(new DerivedIndexesTrigger(mRepository, getStorableType(), derivedTo));
+ Trigger<? super S> trigger;
+ if (mRepository.isStrictTriggers()) {
+ trigger = new DerivedIndexesTrigger.Strict
+ (mRepository, getStorableType(), derivedTo);
+ } else {
+ trigger = new DerivedIndexesTrigger
+ (mRepository, getStorableType(), derivedTo);
+ }
+ addTrigger(trigger);
}
}
}
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexesTrigger.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexesTrigger.java index 4c5840a..4b8a380 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexesTrigger.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexesTrigger.java @@ -64,16 +64,7 @@ class IndexesTrigger<S extends Storable> extends Trigger<S> { }
@Override
- public Object beforeTryUpdate(Transaction txn, S storable) throws PersistException {
- return beforeUpdate(txn, storable);
- }
-
- @Override
- public Object beforeUpdate(Transaction txn, S storable) throws PersistException {
- // Ensure old storable is loaded with an upgradable lock, allowing
- // update to proceed without deadlock.
- txn.setForUpdate(true);
-
+ public Object beforeUpdate(S storable) throws PersistException {
// Return old storable for afterUpdate.
S copy = (S) storable.copy();
try {
@@ -98,16 +89,7 @@ class IndexesTrigger<S extends Storable> extends Trigger<S> { }
@Override
- public Object beforeTryDelete(Transaction txn, S storable) throws PersistException {
- return beforeDelete(txn, storable);
- }
-
- @Override
- public Object beforeDelete(Transaction txn, S storable) throws PersistException {
- // Ensure old storable is loaded with an upgradable lock, allowing
- // delete to proceed without deadlock.
- txn.setForUpdate(true);
-
+ public Object beforeDelete(S storable) throws PersistException {
// Delete index entries referenced by existing storable.
S copy = (S) storable.copy();
try {
@@ -130,4 +112,36 @@ class IndexesTrigger<S extends Storable> extends Trigger<S> { }
return null;
}
+
+ /**
+ * Ensure old storable instance is loaded with an upgradable lock, allowing change to
+ * proceed without deadlock.
+ */
+ final static class Strict<S extends Storable> extends IndexesTrigger<S> {
+ Strict(ManagedIndex<S>[] managedIndexes) {
+ super(managedIndexes);
+ }
+
+ @Override
+ public Object beforeTryUpdate(Transaction txn, S storable) throws PersistException {
+ return beforeUpdate(txn, storable);
+ }
+
+ @Override
+ public Object beforeUpdate(Transaction txn, S storable) throws PersistException {
+ txn.setForUpdate(true);
+ return super.beforeUpdate(storable);
+ }
+
+ @Override
+ public Object beforeTryDelete(Transaction txn, S storable) throws PersistException {
+ return beforeDelete(txn, storable);
+ }
+
+ @Override
+ public Object beforeDelete(Transaction txn, S storable) throws PersistException {
+ txn.setForUpdate(true);
+ return super.beforeDelete(storable);
+ }
+ }
}
|