Browse files

Factor out multi-lock behavior into its own class MultiLock.

  • Loading branch information...
1 parent 2f2dc91 commit e421e2ba3fbb62dffbf3ea0a5cee0a66e07e302b @thomas-kielbus thomas-kielbus committed Jun 11, 2014
View
81 megadesk-core/src/main/java/com/liveramp/megadesk/base/state/MultiLock.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2014 LiveRamp
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.liveramp.megadesk.base.state;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+
+import com.liveramp.megadesk.core.state.Lock;
+
+public class MultiLock implements Lock {
+
+ private final Collection<Lock> locks;
+ private final Set<Lock> acquiredLocks;
+
+ public MultiLock(Collection<Lock> locks) {
+ this.locks = ImmutableList.copyOf(locks);
+ this.acquiredLocks = Sets.newHashSet();
+ }
+
+ @Override
+ public void lock() {
+ for (Lock lock : locks) {
+ lockAndRemember(lock, acquiredLocks);
+ }
+ }
+
+ @Override
+ public boolean tryLock() {
+ for (Lock lock : locks) {
+ if (!tryLockAndRemember(lock, acquiredLocks)) {
+ unlockAndRemember(acquiredLocks);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void unlock() {
+ unlockAndRemember(acquiredLocks);
+ }
+
+ private static boolean tryLockAndRemember(Lock lock, Set<Lock> acquiredLocks) {
+ boolean result = lock.tryLock();
+ if (result) {
+ acquiredLocks.add(lock);
+ }
+ return result;
+ }
+
+ private static void lockAndRemember(Lock lock, Set<Lock> acquiredLocks) {
+ lock.lock();
+ acquiredLocks.add(lock);
+ }
+
+ private static void unlockAndRemember(Set<Lock> acquiredLocks) {
+ Iterator<Lock> lockIterator = acquiredLocks.iterator();
+ while (lockIterator.hasNext()) {
+ lockIterator.next().unlock();
+ lockIterator.remove();
+ }
+ }
+}
View
68 ...k-core/src/main/java/com/liveramp/megadesk/base/transaction/BaseTransactionExecution.java
@@ -16,20 +16,16 @@
package com.liveramp.megadesk.base.transaction;
-import java.util.Collection;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import com.liveramp.megadesk.base.state.MultiLock;
import com.liveramp.megadesk.core.state.Lock;
import com.liveramp.megadesk.core.state.Variable;
import com.liveramp.megadesk.core.transaction.Context;
import com.liveramp.megadesk.core.transaction.Dependency;
-import com.liveramp.megadesk.core.transaction.DependencyType;
import com.liveramp.megadesk.core.transaction.TransactionExecution;
import com.liveramp.megadesk.core.transaction.VariableDependency;
@@ -45,26 +41,25 @@
private Dependency dependency;
private Context data;
private State state = State.STANDBY;
- private final Set<Lock> locksAcquired;
-
- public BaseTransactionExecution() {
- locksAcquired = Sets.newHashSet();
- }
+ private Lock lock;
@Override
public Context begin(Dependency dependency) {
ensureState(State.STANDBY);
- lock(dependency);
+ lock = dependencyLock(dependency);
+ lock.lock();
return prepare(dependency);
}
@Override
public Context tryBegin(Dependency dependency) {
ensureState(State.STANDBY);
- boolean result = tryLock(dependency);
+ lock = dependencyLock(dependency);
+ boolean result = lock.tryLock();
if (result) {
return prepare(dependency);
} else {
+ lock = null;
return null;
}
}
@@ -85,23 +80,19 @@ public void commit() {
variable.driver().persistence().write(value);
}
// Release execution locks
- unlock(locksAcquired);
+ lock.unlock();
state = State.COMMITTED;
}
@Override
public void abort() {
ensureState(State.RUNNING);
- unlock(locksAcquired);
+ lock.unlock();
state = State.ABORTED;
}
- private boolean tryLock(Dependency dependency) {
- return tryLockAndRemember(orderedLocks(dependency), locksAcquired);
- }
-
- private void lock(Dependency dependency) {
- lockAndRemember(orderedLocks(dependency), locksAcquired);
+ private static Lock dependencyLock(Dependency dependency) {
+ return new MultiLock(orderedLocks(dependency));
}
// Locks are globally ordered to prevent deadlocks
@@ -115,43 +106,6 @@ private void lock(Dependency dependency) {
return result;
}
- private static boolean tryLockAndRemember(Collection<Lock> locks, Set<Lock> acquiredLocks) {
- for (Lock lock : locks) {
- if (!tryLockAndRemember(lock, acquiredLocks)) {
- unlock(acquiredLocks);
- return false;
- }
- }
- return true;
- }
-
- private static void lockAndRemember(Collection<Lock> locks, Set<Lock> acquiredLocks) {
- for (Lock lock : locks) {
- lockAndRemember(lock, acquiredLocks);
- }
- }
-
- private static boolean tryLockAndRemember(Lock lock, Set<Lock> acquiredLocks) {
- boolean result = lock.tryLock();
- if (result) {
- acquiredLocks.add(lock);
- }
- return result;
- }
-
- private static void lockAndRemember(Lock lock, Set<Lock> acquiredLocks) {
- lock.lock();
- acquiredLocks.add(lock);
- }
-
- private static void unlock(Set<Lock> acquiredLocks) {
- Iterator<Lock> lockIterator = acquiredLocks.iterator();
- while (lockIterator.hasNext()) {
- lockIterator.next().unlock();
- lockIterator.remove();
- }
- }
-
private void ensureState(State state) {
if (this.state != state) {
throw new IllegalStateException("State should be " + state + " but is " + this.state);

0 comments on commit e421e2b

Please sign in to comment.