summaryrefslogtreecommitdiff
path: root/src/main/java/com/amazon/carbonado/repo
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/amazon/carbonado/repo')
-rw-r--r--src/main/java/com/amazon/carbonado/repo/indexed/DerivedIndexesTrigger.java3
-rw-r--r--src/main/java/com/amazon/carbonado/repo/indexed/IndexesTrigger.java13
-rw-r--r--src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java4
-rw-r--r--src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java19
4 files changed, 28 insertions, 11 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 7a1073d..bcb866b 100644
--- a/src/main/java/com/amazon/carbonado/repo/indexed/DerivedIndexesTrigger.java
+++ b/src/main/java/com/amazon/carbonado/repo/indexed/DerivedIndexesTrigger.java
@@ -75,7 +75,8 @@ class DerivedIndexesTrigger<S extends Storable, D extends Storable> extends Trig
}
@Override
- public Object beforeDelete(S storable) throws PersistException {
+ public Object beforeDelete(Transaction txn, S storable) throws PersistException {
+ txn.setForUpdate(true);
try {
if (storable.copy().tryLoad()) {
return createDependentIndexEntries(storable);
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 fc8a18a..67f29e8 100644
--- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexesTrigger.java
+++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexesTrigger.java
@@ -24,6 +24,7 @@ import com.amazon.carbonado.CorruptEncodingException;
import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.PersistException;
import com.amazon.carbonado.Storable;
+import com.amazon.carbonado.Transaction;
import com.amazon.carbonado.Trigger;
import com.amazon.carbonado.UniqueConstraintException;
@@ -63,7 +64,11 @@ class IndexesTrigger<S extends Storable> extends Trigger<S> {
}
@Override
- public Object beforeUpdate(S storable) throws PersistException {
+ 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);
+
// Return old storable for afterUpdate.
S copy = (S) storable.copy();
try {
@@ -88,7 +93,11 @@ class IndexesTrigger<S extends Storable> extends Trigger<S> {
}
@Override
- public Object beforeDelete(S storable) throws PersistException {
+ 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);
+
// Delete index entries referenced by existing storable.
S copy = (S) storable.copy();
try {
diff --git a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java
index cd65f46..f99276d 100644
--- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java
+++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java
@@ -74,9 +74,9 @@ class ReplicatedStorage<S extends Storable> implements Storage<S> {
}
/**
- * For testing only.
+ * Exposed for testing only.
*/
- ReplicatedStorage(Repository aRepository,
+ ReplicatedStorage(ReplicatedRepository aRepository,
Storage<S> replicaStorage,
Storage<S> masterStorage)
{
diff --git a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java
index c646f8c..ce0ce53 100644
--- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java
+++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java
@@ -49,13 +49,13 @@ import com.amazon.carbonado.spi.TriggerManager;
* @author Brian S O'Neill
*/
class ReplicationTrigger<S extends Storable> extends Trigger<S> {
- private final Repository mRepository;
+ private final ReplicatedRepository mRepository;
private final Storage<S> mReplicaStorage;
private final Storage<S> mMasterStorage;
private final TriggerManager<S> mTriggerManager;
- ReplicationTrigger(Repository repository,
+ ReplicationTrigger(ReplicatedRepository repository,
Storage<S> replicaStorage,
Storage<S> masterStorage)
{
@@ -231,9 +231,11 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
setReplicationDisabled();
try {
- Transaction txn = mRepository.enterTransaction();
+ Transaction masterTxn = mRepository.getMasterRepository().enterTransaction();
+ Transaction replicaTxn = mRepository.getReplicaRepository().enterTransaction();
+
try {
- txn.setForUpdate(true);
+ replicaTxn.setForUpdate(true);
if (reload) {
if (masterEntry == null) {
@@ -320,13 +322,18 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
}
}
- txn.commit();
+ replicaTxn.commit();
} catch (Throwable e) {
resyncFailed(listener, replicaEntry, masterEntry, newReplicaEntry, state);
ThrowUnchecked.fire(e);
}
} finally {
- txn.exit();
+ try {
+ masterTxn.exit();
+ } finally {
+ // Do second, favoring any exception thrown from it.
+ replicaTxn.exit();
+ }
}
} finally {
setReplicationEnabled();