blob: cef53a55a344055934f78a58f43068b123706ab4 [file] [log] [blame]
Madan Jampani12390c12014-11-12 00:35:56 -08001package org.onlab.onos.store.service.impl;
2
3import java.util.UUID;
4import java.util.concurrent.CompletableFuture;
5import java.util.concurrent.ExecutionException;
6import java.util.concurrent.TimeUnit;
7import java.util.concurrent.TimeoutException;
8import java.util.concurrent.atomic.AtomicBoolean;
9
10import org.joda.time.DateTime;
11import org.onlab.onos.cluster.ClusterService;
12import org.onlab.onos.store.service.DatabaseService;
13import org.onlab.onos.store.service.Lock;
Madan Jampani12390c12014-11-12 00:35:56 -080014
15/**
16 * A distributed lock implementation.
17 */
18public class DistributedLock implements Lock {
19
20 private final DistributedLockManager lockManager;
21 private final DatabaseService databaseService;
22 private final String path;
23 private DateTime lockExpirationTime;
24 private AtomicBoolean isLocked = new AtomicBoolean(false);
25 private byte[] lockId;
26
27 public DistributedLock(
28 String path,
29 DatabaseService databaseService,
30 ClusterService clusterService,
31 DistributedLockManager lockManager) {
32
33 this.path = path;
34 this.databaseService = databaseService;
35 this.lockManager = lockManager;
36 this.lockId =
37 (UUID.randomUUID().toString() + "::" + clusterService.getLocalNode().id().toString()).getBytes();
38 }
39
40 @Override
41 public String path() {
42 return path;
43 }
44
45 @Override
46 public void lock(int leaseDurationMillis) {
47
48 if (isLocked() && lockExpirationTime.isAfter(DateTime.now().plusMillis(leaseDurationMillis))) {
49 // Nothing to do.
50 // Current expiration time is beyond what is requested.
51 return;
52 } else {
53 tryLock(Long.MAX_VALUE, leaseDurationMillis);
54 }
55 }
56
57 @Override
58 public boolean tryLock(int leaseDurationMillis) {
Madan Jampanic22123d2014-11-12 02:12:19 -080059 return databaseService.putIfAbsent(
60 DistributedLockManager.ONOS_LOCK_TABLE_NAME,
61 path,
62 lockId);
Madan Jampani12390c12014-11-12 00:35:56 -080063 }
64
65 @Override
66 public boolean tryLock(
67 long waitTimeMillis,
68 int leaseDurationMillis) {
Madan Jampani44e6a542014-11-12 01:06:51 -080069 if (!tryLock(leaseDurationMillis)) {
Madan Jampani12390c12014-11-12 00:35:56 -080070 CompletableFuture<Void> future =
71 lockManager.lockIfAvailable(this, waitTimeMillis, leaseDurationMillis);
72 try {
73 future.get(waitTimeMillis, TimeUnit.MILLISECONDS);
74 } catch (ExecutionException | InterruptedException e) {
75 // TODO: ExecutionException could indicate something
76 // wrong with the backing database.
77 // Throw an exception?
78 return false;
79 } catch (TimeoutException e) {
80 return false;
81 }
82 }
Madan Jampanif5d263b2014-11-13 10:04:40 -080083 isLocked.set(true);
Madan Jampani12390c12014-11-12 00:35:56 -080084 lockExpirationTime = DateTime.now().plusMillis(leaseDurationMillis);
85 return true;
86 }
87
88 @Override
89 public boolean isLocked() {
90 if (isLocked.get()) {
91 // We rely on local information to check
92 // if the expired.
93 // This should should make this call
94 // light weight, which still retaining the same
95 // safety guarantees.
96 if (DateTime.now().isAfter(lockExpirationTime)) {
97 isLocked.set(false);
98 return false;
Madan Jampanif5d263b2014-11-13 10:04:40 -080099 } else {
100 return true;
Madan Jampani12390c12014-11-12 00:35:56 -0800101 }
102 }
Madan Jampanif5d263b2014-11-13 10:04:40 -0800103 return false;
Madan Jampani12390c12014-11-12 00:35:56 -0800104 }
105
106 @Override
107 public void unlock() {
108 if (!isLocked()) {
109 return;
110 } else {
Madan Jampanif5d263b2014-11-13 10:04:40 -0800111 isLocked.set(false);
Madan Jampani12390c12014-11-12 00:35:56 -0800112 databaseService.removeIfValueMatches(DistributedLockManager.ONOS_LOCK_TABLE_NAME, path, lockId);
113 }
114 }
115
116 @Override
117 public boolean extendExpiration(int leaseDurationMillis) {
118 if (isLocked() && lockExpirationTime.isAfter(DateTime.now().plusMillis(leaseDurationMillis))) {
119 return true;
120 } else {
121 return tryLock(leaseDurationMillis);
122 }
123 }
124}