summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian S. O'Neill <bronee@gmail.com>2007-02-17 01:28:20 +0000
committerBrian S. O'Neill <bronee@gmail.com>2007-02-17 01:28:20 +0000
commitc4954dc33c91c3815dda286b765e7164ec2b3eba (patch)
treed8d907beff864d371c27a652b77c07f4b91bbf6f
parent431daf9c6e6373f9c272d170b37c74c5b0c84c4f (diff)
ReplicatedRepository installs user triggers on the replica again, but it now disables all triggers during resync to prevent errors. When triggers were on master, downstream triggers would not see changes made by earlier triggers.
-rw-r--r--RELEASE-NOTES.txt3
-rw-r--r--src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java26
-rw-r--r--src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java29
-rw-r--r--src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java62
-rw-r--r--src/main/java/com/amazon/carbonado/spi/TriggerManager.java282
5 files changed, 281 insertions, 121 deletions
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index e2d3ede..ea9ff54 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -7,6 +7,9 @@ Carbonado change history
cleared. Otherwise, indexes on newly added properties might not get updated.
- Added system properties to control performance characteristics of MergeSortBuffer.
- Fixed verify error in generation of markPropertiesDirty.
+- ReplicatedRepository installs user triggers on the replica again, but it now
+ disables all triggers during resync to prevent errors. When triggers were on
+ master, downstream triggers would not see changes made by earlier triggers.
1.1-BETA9 to 1.1-BETA10
-------------------------------
diff --git a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java
index c292d9c..3b215bc 100644
--- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java
+++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedRepository.java
@@ -356,9 +356,9 @@ class ReplicatedRepository
Object... filterValues)
throws RepositoryException
{
- ReplicationTrigger<S> trigger;
+ ReplicationTrigger<S> replicationTrigger;
if (storageFor(type) instanceof ReplicatedStorage) {
- trigger = ((ReplicatedStorage) storageFor(type)).getTrigger();
+ replicationTrigger = ((ReplicatedStorage) storageFor(type)).getReplicationTrigger();
} else {
throw new UnsupportedTypeException("Storable type is not replicated", type);
}
@@ -413,7 +413,7 @@ class ReplicatedRepository
try {
replicaTxn.setForUpdate(true);
- resync(trigger,
+ resync(replicationTrigger,
replicaStorage, replicaQuery,
masterStorage, masterQuery,
throttle, desiredSpeed,
@@ -426,7 +426,7 @@ class ReplicatedRepository
}
@SuppressWarnings("unchecked")
- private <S extends Storable> void resync(ReplicationTrigger<S> trigger,
+ private <S extends Storable> void resync(ReplicationTrigger<S> replicationTrigger,
Storage<S> replicaStorage, Query<S> replicaQuery,
Storage<S> masterStorage, Query<S> masterQuery,
Throttle throttle, double desiredSpeed,
@@ -493,7 +493,7 @@ class ReplicatedRepository
if (replicaWithKeyOnly != null) {
// Delete corrupt replica entry.
try {
- trigger.deleteReplica(replicaWithKeyOnly);
+ replicationTrigger.deleteReplica(replicaWithKeyOnly);
log.info("Deleted corrupt replica entry: " +
replicaWithKeyOnly.toStringKeyOnly(), e);
skip = false;
@@ -551,7 +551,7 @@ class ReplicatedRepository
if (compare < 0) {
// Bogus record exists only in replica so delete it.
- resyncTask = prepareResyncTask(trigger, replicaEntry, null);
+ resyncTask = prepareResyncTask(replicationTrigger, replicaEntry, null);
// Allow replica to advance.
if (replicaCursor == null) {
replicaCursor = replicaQuery.fetchAfter(replicaEntry);
@@ -560,7 +560,7 @@ class ReplicatedRepository
replicaEntry = null;
} else if (compare > 0) {
// Replica cursor is missing an entry so copy it.
- resyncTask = prepareResyncTask(trigger, null, masterEntry);
+ resyncTask = prepareResyncTask(replicationTrigger, null, masterEntry);
// Allow master to advance.
lastMasterEntry = masterEntry;
masterEntry = null;
@@ -576,7 +576,8 @@ class ReplicatedRepository
// Both replicaEntry and masterEntry are non-null.
if (!replicaEntry.equalProperties(masterEntry)) {
// Replica is stale.
- resyncTask = prepareResyncTask(trigger, replicaEntry, masterEntry);
+ resyncTask = prepareResyncTask
+ (replicationTrigger, replicaEntry, masterEntry);
}
// Entries are synchronized so allow both cursors to advance.
@@ -607,9 +608,10 @@ class ReplicatedRepository
}
}
- private <S extends Storable> Runnable prepareResyncTask(final ReplicationTrigger<S> trigger,
- final S replicaEntry,
- final S masterEntry)
+ private <S extends Storable> Runnable prepareResyncTask
+ (final ReplicationTrigger<S> replicationTrigger,
+ final S replicaEntry,
+ final S masterEntry)
throws RepositoryException
{
if (replicaEntry == null && masterEntry == null) {
@@ -622,7 +624,7 @@ class ReplicatedRepository
Runnable task = new Runnable() {
public void run() {
try {
- trigger.resyncEntries(replicaEntry, masterEntry);
+ replicationTrigger.resyncEntries(replicaEntry, masterEntry);
} catch (Exception e) {
LogFactory.getLog(ReplicatedRepository.class).error(null, e);
}
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 ebb6db6..9711784 100644
--- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java
+++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicatedStorage.java
@@ -43,7 +43,7 @@ import com.amazon.carbonado.spi.BelatedStorageCreator;
class ReplicatedStorage<S extends Storable> implements Storage<S> {
final Storage<S> mReplicaStorage;
final Storage<S> mMasterStorage;
- final ReplicationTrigger<S> mTrigger;
+ final ReplicationTrigger<S> mReplicationTrigger;
/**
* @throws UnsupportedTypeException if master doesn't support Storable, but
@@ -63,8 +63,13 @@ class ReplicatedStorage<S extends Storable> implements Storage<S> {
ReplicatedRepositoryBuilder.DEFAULT_RETRY_MILLIS);
mMasterStorage = creator.get(ReplicatedRepositoryBuilder.DEFAULT_MASTER_TIMEOUT_MILLIS);
- mTrigger = new ReplicationTrigger<S>(aRepository, mReplicaStorage, mMasterStorage);
- mReplicaStorage.addTrigger(mTrigger);
+
+ // ReplicationTrigger contains internal TriggerManager, and all other
+ // triggers should register with the ReplicationTrigger. This allows
+ // all triggers to be easily disabled during resync and repairs.
+
+ mReplicationTrigger = new ReplicationTrigger<S>
+ (aRepository, mReplicaStorage, mMasterStorage);
}
/**
@@ -76,8 +81,8 @@ class ReplicatedStorage<S extends Storable> implements Storage<S> {
{
mReplicaStorage = replicaStorage;
mMasterStorage = masterStorage;
- mTrigger = new ReplicationTrigger<S>(aRepository, mReplicaStorage, masterStorage);
- mReplicaStorage.addTrigger(mTrigger);
+ mReplicationTrigger = new ReplicationTrigger<S>
+ (aRepository, mReplicaStorage, masterStorage);
}
public Class<S> getStorableType() {
@@ -100,21 +105,15 @@ class ReplicatedStorage<S extends Storable> implements Storage<S> {
return mReplicaStorage.query(filter);
}
- // Note: All user triggers must be added to the master storage. Otherwise,
- // resync operations can cause the triggers to run again, which can be
- // disastrous. If triggers ever support "after load" events, things get
- // complicated. Perhaps this use case is a good example for why supporting
- // "after load" events might be bad.
-
public boolean addTrigger(Trigger<? super S> trigger) {
- return mMasterStorage.addTrigger(trigger);
+ return mReplicationTrigger.addTrigger(trigger);
}
public boolean removeTrigger(Trigger<? super S> trigger) {
- return mMasterStorage.removeTrigger(trigger);
+ return mReplicationTrigger.removeTrigger(trigger);
}
- ReplicationTrigger<S> getTrigger() {
- return mTrigger;
+ ReplicationTrigger<S> getReplicationTrigger() {
+ return mReplicationTrigger;
}
}
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 249a779..7f743ac 100644
--- a/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java
+++ b/src/main/java/com/amazon/carbonado/repo/replicated/ReplicationTrigger.java
@@ -18,8 +18,6 @@
package com.amazon.carbonado.repo.replicated;
-import java.util.concurrent.atomic.AtomicInteger;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -36,6 +34,7 @@ import com.amazon.carbonado.Trigger;
import com.amazon.carbonado.UniqueConstraintException;
import com.amazon.carbonado.spi.RepairExecutor;
+import com.amazon.carbonado.spi.TriggerManager;
/**
* All inserts/updates/deletes are first committed to the master storage, then
@@ -49,7 +48,7 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
private final Storage<S> mReplicaStorage;
private final Storage<S> mMasterStorage;
- private final ThreadLocal<AtomicInteger> mDisabled = new ThreadLocal<AtomicInteger>();
+ private final TriggerManager<S> mTriggerManager;
ReplicationTrigger(Repository repository,
Storage<S> replicaStorage,
@@ -58,6 +57,11 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
mRepository = repository;
mReplicaStorage = replicaStorage;
mMasterStorage = masterStorage;
+ // Use TriggerManager to locally disable trigger execution during
+ // resync and repairs.
+ mTriggerManager = new TriggerManager<S>();
+ mTriggerManager.addTrigger(this);
+ replicaStorage.addTrigger(mTriggerManager);
}
@Override
@@ -71,10 +75,6 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
}
private Object beforeInsert(S replica, boolean forTry) throws PersistException {
- if (isReplicationDisabled()) {
- return null;
- }
-
final S master = mMasterStorage.prepare();
replica.copyAllProperties(master);
@@ -129,10 +129,6 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
}
private Object beforeUpdate(S replica, boolean forTry) throws PersistException {
- if (isReplicationDisabled()) {
- return null;
- }
-
final S master = mMasterStorage.prepare();
replica.copyPrimaryKeyProperties(master);
@@ -209,10 +205,6 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
@Override
public Object beforeDelete(S replica) throws PersistException {
- if (isReplicationDisabled()) {
- return null;
- }
-
S master = mMasterStorage.prepare();
replica.copyPrimaryKeyProperties(master);
@@ -373,6 +365,14 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
});
}
+ boolean addTrigger(Trigger<? super S> trigger) {
+ return mTriggerManager.addTrigger(trigger);
+ }
+
+ boolean removeTrigger(Trigger<? super S> trigger) {
+ return mTriggerManager.removeTrigger(trigger);
+ }
+
/**
* Deletes the replica entry with replication disabled.
*/
@@ -401,35 +401,13 @@ class ReplicationTrigger<S extends Storable> extends Trigger<S> {
}
}
- /**
- * Returns true if replication is disabled for the current thread.
- */
- private boolean isReplicationDisabled() {
- // Count indicates how many times disabled (nested)
- AtomicInteger i = mDisabled.get();
- return i != null && i.get() > 0;
- }
-
- /**
- * By default, replication is enabled for the current thread. Pass true to
- * disable during re-sync operations.
- */
- private void setReplicationDisabled(boolean disabled) {
- // Using a count allows this method call to be nested. Based on the
- // current implementation, it should never be nested, so this extra
- // work is just a safeguard.
- AtomicInteger i = mDisabled.get();
+ void setReplicationDisabled(boolean disabled) {
+ // This method disables not only this trigger, but all triggers added
+ // to manager.
if (disabled) {
- if (i == null) {
- i = new AtomicInteger(1);
- mDisabled.set(i);
- } else {
- i.incrementAndGet();
- }
+ mTriggerManager.localDisable();
} else {
- if (i != null) {
- i.decrementAndGet();
- }
+ mTriggerManager.localEnable();
}
}
}
diff --git a/src/main/java/com/amazon/carbonado/spi/TriggerManager.java b/src/main/java/com/amazon/carbonado/spi/TriggerManager.java
index 147d1ed..a67b134 100644
--- a/src/main/java/com/amazon/carbonado/spi/TriggerManager.java
+++ b/src/main/java/com/amazon/carbonado/spi/TriggerManager.java
@@ -23,6 +23,9 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
import com.amazon.carbonado.PersistException;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storable;
@@ -36,7 +39,7 @@ import com.amazon.carbonado.TriggerFactory;
*
* @author Brian S O'Neill
*/
-public class TriggerManager<S extends Storable> {
+public class TriggerManager<S extends Storable> extends Trigger<S> {
// Bit masks returned by selectTypes.
private static final int FOR_INSERT = 1;
private static final int FOR_UPDATE = 2;
@@ -91,9 +94,9 @@ public class TriggerManager<S extends Storable> {
}
}
- private volatile ForInsert<S> mForInsert;
- private volatile ForUpdate<S> mForUpdate;
- private volatile ForDelete<S> mForDelete;
+ private final ForInsert<S> mForInsert = new ForInsert<S>();
+ private final ForUpdate<S> mForUpdate = new ForUpdate<S>();
+ private final ForDelete<S> mForDelete = new ForDelete<S>();
public TriggerManager() {
}
@@ -111,102 +114,74 @@ public class TriggerManager<S extends Storable> {
}
/**
- * Returns consolidated trigger to call for insert operations, or null if
- * none.
+ * Returns a consolidated trigger to call for insert operations, or null if
+ * none. If not null, the consolidated trigger is not a snapshot -- it will
+ * change as the set of triggers in this manager changes.
*/
public Trigger<? super S> getInsertTrigger() {
- return mForInsert;
+ ForInsert<S> forInsert = mForInsert;
+ return forInsert.isEmpty() ? null : forInsert;
}
/**
- * Returns consolidated trigger to call for update operations, or null if
- * none.
+ * Returns a consolidated trigger to call for update operations, or null if
+ * none. If not null, the consolidated trigger is not a snapshot -- it will
+ * change as the set of triggers in this manager changes.
*/
public Trigger<? super S> getUpdateTrigger() {
- return mForUpdate;
+ ForUpdate<S> forUpdate = mForUpdate;
+ return forUpdate.isEmpty() ? null : forUpdate;
}
/**
- * Returns consolidated trigger to call for delete operations, or null if
- * none.
+ * Returns a consolidated trigger to call for delete operations, or null if
+ * none. If not null, the consolidated trigger is not a snapshot -- it will
+ * change as the set of triggers in this manager changes.
*/
public Trigger<? super S> getDeleteTrigger() {
- return mForDelete;
+ ForDelete<S> forDelete = mForDelete;
+ return forDelete.isEmpty() ? null : forDelete;
}
- public synchronized boolean addTrigger(Trigger<? super S> trigger) {
+ public boolean addTrigger(Trigger<? super S> trigger) {
if (trigger == null) {
throw new IllegalArgumentException();
}
int types = selectTypes(trigger);
- if (types == 0) {
- return false;
- }
boolean retValue = false;
if ((types & FOR_INSERT) != 0) {
- if (mForInsert == null) {
- mForInsert = new ForInsert<S>();
- }
retValue |= mForInsert.add(trigger);
}
-
if ((types & FOR_UPDATE) != 0) {
- if (mForUpdate == null) {
- mForUpdate = new ForUpdate<S>();
- }
retValue |= mForUpdate.add(trigger);
}
-
if ((types & FOR_DELETE) != 0) {
- if (mForDelete == null) {
- mForDelete = new ForDelete<S>();
- }
retValue |= mForDelete.add(trigger);
}
return retValue;
}
- public synchronized boolean removeTrigger(Trigger<? super S> trigger) {
+ public boolean removeTrigger(Trigger<? super S> trigger) {
if (trigger == null) {
throw new IllegalArgumentException();
}
int types = selectTypes(trigger);
- if (types == 0) {
- return false;
- }
boolean retValue = false;
if ((types & FOR_INSERT) != 0) {
- if (mForInsert != null && mForInsert.remove(trigger)) {
- retValue = true;
- if (mForInsert.isEmpty()) {
- mForInsert = null;
- }
- }
+ retValue |= mForInsert.remove(trigger);
}
-
if ((types & FOR_UPDATE) != 0) {
- if (mForUpdate != null && mForUpdate.remove(trigger)) {
- retValue = true;
- if (mForUpdate.isEmpty()) {
- mForUpdate = null;
- }
- }
+ retValue |= mForUpdate.remove(trigger);
}
-
if ((types & FOR_DELETE) != 0) {
- if (mForDelete != null && mForDelete.remove(trigger)) {
- retValue = true;
- if (mForDelete.isEmpty()) {
- mForDelete = null;
- }
- }
+ retValue |= mForDelete.remove(trigger);
}
return retValue;
@@ -224,6 +199,102 @@ public class TriggerManager<S extends Storable> {
}
/**
+ * Disables execution of all managed triggers for the current thread. Call
+ * localEnable to enable again. This call can be made multiple times, but
+ * be sure to call localEnable the same number of times to fully enable.
+ */
+ public void localDisable() {
+ mForInsert.localDisable();
+ mForUpdate.localDisable();
+ mForDelete.localDisable();
+ }
+
+ /**
+ * Enables execution of all managed triggers for the current thread, if
+ * they had been disabled before.
+ */
+ public void localEnable() {
+ mForInsert.localEnable();
+ mForUpdate.localEnable();
+ mForDelete.localEnable();
+ }
+
+ @Override
+ public Object beforeInsert(S storable) throws PersistException {
+ return mForInsert.beforeInsert(storable);
+ }
+
+ @Override
+ public Object beforeTryInsert(S storable) throws PersistException {
+ return mForInsert.beforeTryInsert(storable);
+ }
+
+ @Override
+ public void afterInsert(S storable, Object state) throws PersistException {
+ mForInsert.afterInsert(storable, state);
+ }
+
+ @Override
+ public void afterTryInsert(S storable, Object state) throws PersistException {
+ mForInsert.afterTryInsert(storable, state);
+ }
+
+ @Override
+ public void failedInsert(S storable, Object state) {
+ mForInsert.failedInsert(storable, state);
+ }
+
+ @Override
+ public Object beforeUpdate(S storable) throws PersistException {
+ return mForUpdate.beforeUpdate(storable);
+ }
+
+ @Override
+ public Object beforeTryUpdate(S storable) throws PersistException {
+ return mForUpdate.beforeTryUpdate(storable);
+ }
+
+ @Override
+ public void afterUpdate(S storable, Object state) throws PersistException {
+ mForUpdate.afterUpdate(storable, state);
+ }
+
+ @Override
+ public void afterTryUpdate(S storable, Object state) throws PersistException {
+ mForUpdate.afterTryUpdate(storable, state);
+ }
+
+ @Override
+ public void failedUpdate(S storable, Object state) {
+ mForUpdate.failedUpdate(storable, state);
+ }
+
+ @Override
+ public Object beforeDelete(S storable) throws PersistException {
+ return mForDelete.beforeDelete(storable);
+ }
+
+ @Override
+ public Object beforeTryDelete(S storable) throws PersistException {
+ return mForDelete.beforeTryDelete(storable);
+ }
+
+ @Override
+ public void afterDelete(S storable, Object state) throws PersistException {
+ mForDelete.afterDelete(storable, state);
+ }
+
+ @Override
+ public void afterTryDelete(S storable, Object state) throws PersistException {
+ mForDelete.afterTryDelete(storable, state);
+ }
+
+ @Override
+ public void failedDelete(S storable, Object state) {
+ mForDelete.failedDelete(storable, state);
+ }
+
+ /**
* Determines which operations the given trigger overrides.
*/
private int selectTypes(Trigger<? super S> trigger) {
@@ -281,10 +352,16 @@ public class TriggerManager<S extends Storable> {
}
private static abstract class ForSomething<S> extends Trigger<S> {
+ private static final AtomicReferenceFieldUpdater<ForSomething, ThreadLocal>
+ cDisabledFlagRef = AtomicReferenceFieldUpdater
+ .newUpdater(ForSomething.class, ThreadLocal.class, "mDisabledFlag");
+
private static Trigger[] NO_TRIGGERS = new Trigger[0];
protected volatile Trigger<? super S>[] mTriggers;
+ private volatile ThreadLocal<AtomicInteger> mDisabledFlag;
+
ForSomething() {
mTriggers = NO_TRIGGERS;
}
@@ -313,11 +390,56 @@ public class TriggerManager<S extends Storable> {
boolean isEmpty() {
return mTriggers.length == 0;
}
+
+ boolean isLocallyDisabled() {
+ ThreadLocal<AtomicInteger> disabledFlag = mDisabledFlag;
+ if (disabledFlag == null) {
+ return false;
+ }
+ // Count indicates how many times disabled (nested)
+ AtomicInteger i = disabledFlag.get();
+ return i != null && i.get() > 0;
+ }
+
+ void localDisable() {
+ // Using a count allows this method call to be nested.
+ ThreadLocal<AtomicInteger> disabledFlag = disabledFlag();
+ AtomicInteger i = disabledFlag.get();
+ if (i == null) {
+ disabledFlag.set(new AtomicInteger(1));
+ } else {
+ i.incrementAndGet();
+ }
+ }
+
+ void localEnable() {
+ // Using a count allows this method call to be nested.
+ AtomicInteger i = disabledFlag().get();
+ if (i != null) {
+ i.decrementAndGet();
+ }
+ }
+
+ private ThreadLocal<AtomicInteger> disabledFlag() {
+ ThreadLocal<AtomicInteger> disabledFlag = mDisabledFlag;
+ while (disabledFlag == null) {
+ disabledFlag = new ThreadLocal<AtomicInteger>();
+ if (cDisabledFlagRef.compareAndSet(this, null, disabledFlag)) {
+ break;
+ }
+ disabledFlag = mDisabledFlag;
+ }
+ return disabledFlag;
+ }
}
private static class ForInsert<S> extends ForSomething<S> {
@Override
public Object beforeInsert(S storable) throws PersistException {
+ if (isLocallyDisabled()) {
+ return null;
+ }
+
TriggerStates<S> triggerStates = null;
Trigger<? super S>[] triggers = mTriggers;
@@ -336,6 +458,10 @@ public class TriggerManager<S extends Storable> {
@Override
public Object beforeTryInsert(S storable) throws PersistException {
+ if (isLocallyDisabled()) {
+ return null;
+ }
+
TriggerStates<S> triggerStates = null;
Trigger<? super S>[] triggers = mTriggers;
@@ -354,6 +480,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void afterInsert(S storable, Object state) throws PersistException {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -383,6 +513,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void afterTryInsert(S storable, Object state) throws PersistException {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -412,6 +546,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void failedInsert(S storable, Object state) {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -453,6 +591,10 @@ public class TriggerManager<S extends Storable> {
private static class ForUpdate<S> extends ForSomething<S> {
@Override
public Object beforeUpdate(S storable) throws PersistException {
+ if (isLocallyDisabled()) {
+ return null;
+ }
+
TriggerStates<S> triggerStates = null;
Trigger<? super S>[] triggers = mTriggers;
@@ -471,6 +613,10 @@ public class TriggerManager<S extends Storable> {
@Override
public Object beforeTryUpdate(S storable) throws PersistException {
+ if (isLocallyDisabled()) {
+ return null;
+ }
+
TriggerStates<S> triggerStates = null;
Trigger<? super S>[] triggers = mTriggers;
@@ -489,6 +635,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void afterUpdate(S storable, Object state) throws PersistException {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -518,6 +668,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void afterTryUpdate(S storable, Object state) throws PersistException {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -547,6 +701,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void failedUpdate(S storable, Object state) {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -588,6 +746,10 @@ public class TriggerManager<S extends Storable> {
private static class ForDelete<S> extends ForSomething<S> {
@Override
public Object beforeDelete(S storable) throws PersistException {
+ if (isLocallyDisabled()) {
+ return null;
+ }
+
TriggerStates<S> triggerStates = null;
Trigger<? super S>[] triggers = mTriggers;
@@ -606,6 +768,10 @@ public class TriggerManager<S extends Storable> {
@Override
public Object beforeTryDelete(S storable) throws PersistException {
+ if (isLocallyDisabled()) {
+ return null;
+ }
+
TriggerStates<S> triggerStates = null;
Trigger<? super S>[] triggers = mTriggers;
@@ -624,6 +790,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void afterDelete(S storable, Object state) throws PersistException {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -653,6 +823,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void afterTryDelete(S storable, Object state) throws PersistException {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;
@@ -682,6 +856,10 @@ public class TriggerManager<S extends Storable> {
@Override
public void failedDelete(S storable, Object state) {
+ if (isLocallyDisabled()) {
+ return;
+ }
+
TriggerStates<S> triggerStates;
Trigger<? super S>[] triggers;