Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
16 changed files
with
177 additions
and
118 deletions
... | @@ -157,7 +157,9 @@ public class FooComponent { | ... | @@ -157,7 +157,9 @@ public class FooComponent { |
157 | final String someTable = "admin"; | 157 | final String someTable = "admin"; |
158 | final String someKey = "long"; | 158 | final String someKey = "long"; |
159 | 159 | ||
160 | - dbAdminService.createTable(someTable); | 160 | + if (!dbAdminService.listTables().contains(someTable)) { |
161 | + dbAdminService.createTable(someTable); | ||
162 | + } | ||
161 | 163 | ||
162 | VersionedValue vv = dbService.get(someTable, someKey); | 164 | VersionedValue vv = dbService.get(someTable, someKey); |
163 | if (vv == null) { | 165 | if (vv == null) { | ... | ... |
... | @@ -223,11 +223,6 @@ public class BgpSessionManager { | ... | @@ -223,11 +223,6 @@ public class BgpSessionManager { |
223 | synchronized void routeUpdates(BgpSession bgpSession, | 223 | synchronized void routeUpdates(BgpSession bgpSession, |
224 | Collection<BgpRouteEntry> addedBgpRouteEntries, | 224 | Collection<BgpRouteEntry> addedBgpRouteEntries, |
225 | Collection<BgpRouteEntry> deletedBgpRouteEntries) { | 225 | Collection<BgpRouteEntry> deletedBgpRouteEntries) { |
226 | - // | ||
227 | - // TODO: Merge the updates from different BGP Peers, | ||
228 | - // by choosing the best route. | ||
229 | - // | ||
230 | - | ||
231 | // Process the deleted route entries | 226 | // Process the deleted route entries |
232 | for (BgpRouteEntry bgpRouteEntry : deletedBgpRouteEntries) { | 227 | for (BgpRouteEntry bgpRouteEntry : deletedBgpRouteEntries) { |
233 | processDeletedRoute(bgpSession, bgpRouteEntry); | 228 | processDeletedRoute(bgpSession, bgpRouteEntry); | ... | ... |
... | @@ -22,6 +22,7 @@ public class ReadResult { | ... | @@ -22,6 +22,7 @@ public class ReadResult { |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * Returns the status of the read operation. | 24 | * Returns the status of the read operation. |
25 | + * @return read operation status | ||
25 | */ | 26 | */ |
26 | public ReadStatus status() { | 27 | public ReadStatus status() { |
27 | return status; | 28 | return status; | ... | ... |
... | @@ -269,7 +269,7 @@ implements MastershipService, MastershipAdminService { | ... | @@ -269,7 +269,7 @@ implements MastershipService, MastershipAdminService { |
269 | 269 | ||
270 | @Override | 270 | @Override |
271 | public void notify(MastershipEvent event) { | 271 | public void notify(MastershipEvent event) { |
272 | - log.info("dispatching mastership event {}", event); | 272 | + log.trace("dispatching mastership event {}", event); |
273 | eventDispatcher.post(event); | 273 | eventDispatcher.post(event); |
274 | } | 274 | } |
275 | 275 | ... | ... |
... | @@ -174,7 +174,7 @@ public class ClusterMessagingProtocol | ... | @@ -174,7 +174,7 @@ public class ClusterMessagingProtocol |
174 | public ProtocolClient createClient(TcpMember member) { | 174 | public ProtocolClient createClient(TcpMember member) { |
175 | ControllerNode remoteNode = getControllerNode(member.host(), member.port()); | 175 | ControllerNode remoteNode = getControllerNode(member.host(), member.port()); |
176 | checkNotNull(remoteNode, | 176 | checkNotNull(remoteNode, |
177 | - "A valid controller node is expected for %s:%s", | 177 | + "No matching ONOS Node for %s:%s", |
178 | member.host(), member.port()); | 178 | member.host(), member.port()); |
179 | return new ClusterMessagingProtocolClient( | 179 | return new ClusterMessagingProtocolClient( |
180 | clusterCommunicator, clusterService.getLocalNode(), remoteNode); | 180 | clusterCommunicator, clusterService.getLocalNode(), remoteNode); | ... | ... |
... | @@ -20,11 +20,12 @@ import java.io.IOException; | ... | @@ -20,11 +20,12 @@ import java.io.IOException; |
20 | import java.util.HashMap; | 20 | import java.util.HashMap; |
21 | import java.util.Map; | 21 | import java.util.Map; |
22 | import java.util.Objects; | 22 | import java.util.Objects; |
23 | +import java.util.concurrent.TimeUnit; | ||
23 | import java.util.concurrent.atomic.AtomicBoolean; | 24 | import java.util.concurrent.atomic.AtomicBoolean; |
24 | 25 | ||
25 | -//import net.jodah.expiringmap.ExpiringMap; | 26 | +import net.jodah.expiringmap.ExpiringMap; |
26 | -//import net.jodah.expiringmap.ExpiringMap.ExpirationListener; | 27 | +import net.jodah.expiringmap.ExpiringMap.ExpirationListener; |
27 | -//import net.jodah.expiringmap.ExpiringMap.ExpirationPolicy; | 28 | +import net.jodah.expiringmap.ExpiringMap.ExpirationPolicy; |
28 | import net.kuujo.copycat.cluster.Member; | 29 | import net.kuujo.copycat.cluster.Member; |
29 | import net.kuujo.copycat.event.EventHandler; | 30 | import net.kuujo.copycat.event.EventHandler; |
30 | import net.kuujo.copycat.event.LeaderElectEvent; | 31 | import net.kuujo.copycat.event.LeaderElectEvent; |
... | @@ -34,19 +35,22 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | ... | @@ -34,19 +35,22 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; |
34 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 35 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
35 | import org.onlab.onos.store.cluster.messaging.MessageSubject; | 36 | import org.onlab.onos.store.cluster.messaging.MessageSubject; |
36 | import org.onlab.onos.store.service.DatabaseService; | 37 | import org.onlab.onos.store.service.DatabaseService; |
38 | +import org.onlab.onos.store.service.VersionedValue; | ||
37 | import org.slf4j.Logger; | 39 | import org.slf4j.Logger; |
38 | import org.slf4j.LoggerFactory; | 40 | import org.slf4j.LoggerFactory; |
39 | 41 | ||
40 | /** | 42 | /** |
41 | - * Database update event handler. | 43 | + * Plugs into the database update stream and track the TTL of entries added to |
44 | + * the database. For tables with pre-configured finite TTL, this class has | ||
45 | + * mechanisms for expiring (deleting) old, expired entries from the database. | ||
42 | */ | 46 | */ |
43 | -public class DatabaseUpdateEventHandler implements | 47 | +public class DatabaseEntryExpirationTracker implements |
44 | - DatabaseUpdateEventListener, EventHandler<LeaderElectEvent> { | 48 | + DatabaseUpdateEventListener, EventHandler<LeaderElectEvent> { |
45 | 49 | ||
46 | private final Logger log = LoggerFactory.getLogger(getClass()); | 50 | private final Logger log = LoggerFactory.getLogger(getClass()); |
47 | 51 | ||
48 | - public static final MessageSubject DATABASE_UPDATES = | 52 | + public static final MessageSubject DATABASE_UPDATES = new MessageSubject( |
49 | - new MessageSubject("database-update-event"); | 53 | + "database-update-event"); |
50 | 54 | ||
51 | private DatabaseService databaseService; | 55 | private DatabaseService databaseService; |
52 | private ClusterService cluster; | 56 | private ClusterService cluster; |
... | @@ -54,29 +58,32 @@ public class DatabaseUpdateEventHandler implements | ... | @@ -54,29 +58,32 @@ public class DatabaseUpdateEventHandler implements |
54 | 58 | ||
55 | private final Member localMember; | 59 | private final Member localMember; |
56 | private final AtomicBoolean isLocalMemberLeader = new AtomicBoolean(false); | 60 | private final AtomicBoolean isLocalMemberLeader = new AtomicBoolean(false); |
57 | - private final Map<String, Map<DatabaseRow, Void>> tableEntryExpirationMap = new HashMap<>(); | ||
58 | - //private final ExpirationListener<DatabaseRow, Void> expirationObserver = new ExpirationObserver(); | ||
59 | 61 | ||
60 | - DatabaseUpdateEventHandler(Member localMember) { | 62 | + private final Map<String, Map<DatabaseRow, VersionedValue>> tableEntryExpirationMap = new HashMap<>(); |
63 | + | ||
64 | + private final ExpirationListener<DatabaseRow, VersionedValue> expirationObserver = new ExpirationObserver(); | ||
65 | + | ||
66 | + DatabaseEntryExpirationTracker(Member localMember) { | ||
61 | this.localMember = localMember; | 67 | this.localMember = localMember; |
62 | } | 68 | } |
63 | 69 | ||
64 | @Override | 70 | @Override |
65 | public void tableModified(TableModificationEvent event) { | 71 | public void tableModified(TableModificationEvent event) { |
66 | DatabaseRow row = new DatabaseRow(event.tableName(), event.key()); | 72 | DatabaseRow row = new DatabaseRow(event.tableName(), event.key()); |
67 | - Map<DatabaseRow, Void> map = tableEntryExpirationMap.get(event.tableName()); | 73 | + Map<DatabaseRow, VersionedValue> map = tableEntryExpirationMap |
74 | + .get(event.tableName()); | ||
68 | 75 | ||
69 | switch (event.type()) { | 76 | switch (event.type()) { |
70 | case ROW_DELETED: | 77 | case ROW_DELETED: |
71 | if (isLocalMemberLeader.get()) { | 78 | if (isLocalMemberLeader.get()) { |
72 | try { | 79 | try { |
73 | - clusterCommunicator.broadcast( | 80 | + clusterCommunicator.broadcast(new ClusterMessage(cluster |
74 | - new ClusterMessage( | 81 | + .getLocalNode().id(), DATABASE_UPDATES, |
75 | - cluster.getLocalNode().id(), | 82 | + DatabaseStateMachine.SERIALIZER.encode(event))); |
76 | - DATABASE_UPDATES, | ||
77 | - DatabaseStateMachine.SERIALIZER.encode(event))); | ||
78 | } catch (IOException e) { | 83 | } catch (IOException e) { |
79 | - log.error("Failed to broadcast a database table modification event.", e); | 84 | + log.error( |
85 | + "Failed to broadcast a database table modification event.", | ||
86 | + e); | ||
80 | } | 87 | } |
81 | } | 88 | } |
82 | break; | 89 | break; |
... | @@ -94,15 +101,11 @@ public class DatabaseUpdateEventHandler implements | ... | @@ -94,15 +101,11 @@ public class DatabaseUpdateEventHandler implements |
94 | // make this explicit instead of relying on a negative value | 101 | // make this explicit instead of relying on a negative value |
95 | // to indicate no expiration. | 102 | // to indicate no expiration. |
96 | if (expirationTimeMillis > 0) { | 103 | if (expirationTimeMillis > 0) { |
97 | - tableEntryExpirationMap.put(tableName, null); | 104 | + tableEntryExpirationMap.put(tableName, ExpiringMap.builder() |
98 | - /* | ||
99 | - ExpiringMap.builder() | ||
100 | .expiration(expirationTimeMillis, TimeUnit.SECONDS) | 105 | .expiration(expirationTimeMillis, TimeUnit.SECONDS) |
101 | .expirationListener(expirationObserver) | 106 | .expirationListener(expirationObserver) |
102 | // FIXME: make the expiration policy configurable. | 107 | // FIXME: make the expiration policy configurable. |
103 | - .expirationPolicy(ExpirationPolicy.CREATED) | 108 | + .expirationPolicy(ExpirationPolicy.CREATED).build()); |
104 | - .build()); | ||
105 | - */ | ||
106 | } | 109 | } |
107 | } | 110 | } |
108 | 111 | ||
... | @@ -111,27 +114,40 @@ public class DatabaseUpdateEventHandler implements | ... | @@ -111,27 +114,40 @@ public class DatabaseUpdateEventHandler implements |
111 | tableEntryExpirationMap.remove(tableName); | 114 | tableEntryExpirationMap.remove(tableName); |
112 | } | 115 | } |
113 | 116 | ||
114 | - /* | 117 | + private class ExpirationObserver implements |
115 | - private class ExpirationObserver implements ExpirationListener<DatabaseRow, Void> { | 118 | + ExpirationListener<DatabaseRow, VersionedValue> { |
116 | @Override | 119 | @Override |
117 | - public void expired(DatabaseRow key, Void value) { | 120 | + public void expired(DatabaseRow key, VersionedValue value) { |
118 | try { | 121 | try { |
119 | - // TODO: The safety of this check needs to be verified. | ||
120 | - // Couple of issues: | ||
121 | - // 1. It is very likely that only one member should attempt deletion of the entry from database. | ||
122 | - // 2. A potential race condition exists where the entry expires, but before its can be deleted | ||
123 | - // from the database, a new entry is added or existing entry is updated. | ||
124 | - // That means ttl and expiration should be for a given version. | ||
125 | if (isLocalMemberLeader.get()) { | 122 | if (isLocalMemberLeader.get()) { |
126 | - databaseService.remove(key.tableName, key.key); | 123 | + if (!databaseService.removeIfVersionMatches(key.tableName, |
124 | + key.key, value.version())) { | ||
125 | + log.info("Entry in the database changed before right its TTL expiration."); | ||
126 | + } | ||
127 | + } else { | ||
128 | + // If this node is not the current leader, we should never | ||
129 | + // let the expiring entries drop off | ||
130 | + // Under stable conditions (i.e no leadership switch) the | ||
131 | + // current leader will initiate | ||
132 | + // a database remove and this instance will get notified | ||
133 | + // of a tableModification event causing it to remove from | ||
134 | + // the map. | ||
135 | + Map<DatabaseRow, VersionedValue> map = tableEntryExpirationMap | ||
136 | + .get(key.tableName); | ||
137 | + if (map != null) { | ||
138 | + map.put(key, value); | ||
139 | + } | ||
127 | } | 140 | } |
141 | + | ||
128 | } catch (Exception e) { | 142 | } catch (Exception e) { |
129 | - log.warn("Failed to delete entry from the database after ttl expiration. Will retry eviction", e); | 143 | + log.warn( |
130 | - tableEntryExpirationMap.get(key.tableName).put(new DatabaseRow(key.tableName, key.key), null); | 144 | + "Failed to delete entry from the database after ttl expiration. Will retry eviction", |
145 | + e); | ||
146 | + tableEntryExpirationMap.get(key.tableName).put( | ||
147 | + new DatabaseRow(key.tableName, key.key), value); | ||
131 | } | 148 | } |
132 | } | 149 | } |
133 | } | 150 | } |
134 | - */ | ||
135 | 151 | ||
136 | @Override | 152 | @Override |
137 | public void handle(LeaderElectEvent event) { | 153 | public void handle(LeaderElectEvent event) { |
... | @@ -140,6 +156,9 @@ public class DatabaseUpdateEventHandler implements | ... | @@ -140,6 +156,9 @@ public class DatabaseUpdateEventHandler implements |
140 | } | 156 | } |
141 | } | 157 | } |
142 | 158 | ||
159 | + /** | ||
160 | + * Wrapper class for a database row identifier. | ||
161 | + */ | ||
143 | private class DatabaseRow { | 162 | private class DatabaseRow { |
144 | 163 | ||
145 | String tableName; | 164 | String tableName; |
... | @@ -160,8 +179,8 @@ public class DatabaseUpdateEventHandler implements | ... | @@ -160,8 +179,8 @@ public class DatabaseUpdateEventHandler implements |
160 | } | 179 | } |
161 | DatabaseRow that = (DatabaseRow) obj; | 180 | DatabaseRow that = (DatabaseRow) obj; |
162 | 181 | ||
163 | - return Objects.equals(this.tableName, that.tableName) && | 182 | + return Objects.equals(this.tableName, that.tableName) |
164 | - Objects.equals(this.key, that.key); | 183 | + && Objects.equals(this.key, that.key); |
165 | } | 184 | } |
166 | 185 | ||
167 | @Override | 186 | @Override |
... | @@ -169,4 +188,4 @@ public class DatabaseUpdateEventHandler implements | ... | @@ -169,4 +188,4 @@ public class DatabaseUpdateEventHandler implements |
169 | return Objects.hash(tableName, key); | 188 | return Objects.hash(tableName, key); |
170 | } | 189 | } |
171 | } | 190 | } |
172 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
191 | +} | ... | ... |
... | @@ -67,6 +67,7 @@ public class DatabaseManager implements DatabaseService, DatabaseAdminService { | ... | @@ -67,6 +67,7 @@ public class DatabaseManager implements DatabaseService, DatabaseAdminService { |
67 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 67 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
68 | protected DatabaseProtocolService copycatMessagingProtocol; | 68 | protected DatabaseProtocolService copycatMessagingProtocol; |
69 | 69 | ||
70 | + // FIXME: point to appropriate path | ||
70 | public static final String LOG_FILE_PREFIX = "/tmp/onos-copy-cat-log_"; | 71 | public static final String LOG_FILE_PREFIX = "/tmp/onos-copy-cat-log_"; |
71 | 72 | ||
72 | // Current working dir seems to be /opt/onos/apache-karaf-3.0.2 | 73 | // Current working dir seems to be /opt/onos/apache-karaf-3.0.2 | ... | ... |
... | @@ -237,8 +237,8 @@ public class DatabaseStateMachine implements StateMachine { | ... | @@ -237,8 +237,8 @@ public class DatabaseStateMachine implements StateMachine { |
237 | WriteResult putResult = new WriteResult(WriteStatus.OK, previousValue); | 237 | WriteResult putResult = new WriteResult(WriteStatus.OK, previousValue); |
238 | results.add(putResult); | 238 | results.add(putResult); |
239 | tableModificationEvent = (previousValue == null) ? | 239 | tableModificationEvent = (previousValue == null) ? |
240 | - TableModificationEvent.rowAdded(request.tableName(), request.key()) : | 240 | + TableModificationEvent.rowAdded(request.tableName(), request.key(), newValue) : |
241 | - TableModificationEvent.rowUpdated(request.tableName(), request.key()); | 241 | + TableModificationEvent.rowUpdated(request.tableName(), request.key(), newValue); |
242 | break; | 242 | break; |
243 | 243 | ||
244 | case REMOVE: | 244 | case REMOVE: |
... | @@ -249,7 +249,7 @@ public class DatabaseStateMachine implements StateMachine { | ... | @@ -249,7 +249,7 @@ public class DatabaseStateMachine implements StateMachine { |
249 | results.add(removeResult); | 249 | results.add(removeResult); |
250 | if (removedValue != null) { | 250 | if (removedValue != null) { |
251 | tableModificationEvent = | 251 | tableModificationEvent = |
252 | - TableModificationEvent.rowDeleted(request.tableName(), request.key()); | 252 | + TableModificationEvent.rowDeleted(request.tableName(), request.key(), removedValue); |
253 | } | 253 | } |
254 | break; | 254 | break; |
255 | 255 | ... | ... |
... | @@ -29,15 +29,14 @@ public interface DatabaseUpdateEventListener { | ... | @@ -29,15 +29,14 @@ public interface DatabaseUpdateEventListener { |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * Notifies listeners of a table created event. | 31 | * Notifies listeners of a table created event. |
32 | - * @param tableName | 32 | + * @param tableName name of the table created |
33 | - * @param expirationTimeMillis | 33 | + * @param expirationTimeMillis TTL for entries added to the table (measured since last update time) |
34 | */ | 34 | */ |
35 | public void tableCreated(String tableName, int expirationTimeMillis); | 35 | public void tableCreated(String tableName, int expirationTimeMillis); |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * Notifies listeners of a table deleted event. | 38 | * Notifies listeners of a table deleted event. |
39 | - * @param tableName | 39 | + * @param tableName name of the table deleted |
40 | */ | 40 | */ |
41 | public void tableDeleted(String tableName); | 41 | public void tableDeleted(String tableName); |
42 | - | ||
43 | } | 42 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -33,7 +33,8 @@ public class DistributedLockManager implements LockService { | ... | @@ -33,7 +33,8 @@ public class DistributedLockManager implements LockService { |
33 | 33 | ||
34 | public static final String ONOS_LOCK_TABLE_NAME = "onos-locks"; | 34 | public static final String ONOS_LOCK_TABLE_NAME = "onos-locks"; |
35 | 35 | ||
36 | - private final ArrayListMultimap<String, LockRequest> locksToAcquire = ArrayListMultimap.create(); | 36 | + private final ArrayListMultimap<String, LockRequest> locksToAcquire = ArrayListMultimap |
37 | + .create(); | ||
37 | 38 | ||
38 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 39 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
39 | private ClusterCommunicationService clusterCommunicator; | 40 | private ClusterCommunicationService clusterCommunicator; |
... | @@ -61,11 +62,7 @@ public class DistributedLockManager implements LockService { | ... | @@ -61,11 +62,7 @@ public class DistributedLockManager implements LockService { |
61 | 62 | ||
62 | @Override | 63 | @Override |
63 | public Lock create(String path) { | 64 | public Lock create(String path) { |
64 | - return new DistributedLock( | 65 | + return new DistributedLock(path, databaseService, clusterService, this); |
65 | - path, | ||
66 | - databaseService, | ||
67 | - clusterService, | ||
68 | - this); | ||
69 | } | 66 | } |
70 | 67 | ||
71 | @Override | 68 | @Override |
... | @@ -80,21 +77,19 @@ public class DistributedLockManager implements LockService { | ... | @@ -80,21 +77,19 @@ public class DistributedLockManager implements LockService { |
80 | throw new UnsupportedOperationException(); | 77 | throw new UnsupportedOperationException(); |
81 | } | 78 | } |
82 | 79 | ||
83 | - protected CompletableFuture<Void> lockIfAvailable( | 80 | + protected CompletableFuture<Void> lockIfAvailable(Lock lock, |
84 | - Lock lock, | 81 | + long waitTimeMillis, int leaseDurationMillis) { |
85 | - long waitTimeMillis, | ||
86 | - int leaseDurationMillis) { | ||
87 | CompletableFuture<Void> future = new CompletableFuture<>(); | 82 | CompletableFuture<Void> future = new CompletableFuture<>(); |
88 | - locksToAcquire.put( | 83 | + locksToAcquire.put(lock.path(), new LockRequest(lock, waitTimeMillis, |
89 | - lock.path(), | 84 | + leaseDurationMillis, future)); |
90 | - new LockRequest(lock, waitTimeMillis, leaseDurationMillis, future)); | ||
91 | return future; | 85 | return future; |
92 | } | 86 | } |
93 | 87 | ||
94 | private class LockEventMessageListener implements ClusterMessageHandler { | 88 | private class LockEventMessageListener implements ClusterMessageHandler { |
95 | @Override | 89 | @Override |
96 | public void handle(ClusterMessage message) { | 90 | public void handle(ClusterMessage message) { |
97 | - TableModificationEvent event = DatabaseStateMachine.SERIALIZER.decode(message.payload()); | 91 | + TableModificationEvent event = DatabaseStateMachine.SERIALIZER |
92 | + .decode(message.payload()); | ||
98 | if (!event.tableName().equals(ONOS_LOCK_TABLE_NAME)) { | 93 | if (!event.tableName().equals(ONOS_LOCK_TABLE_NAME)) { |
99 | return; | 94 | return; |
100 | } | 95 | } |
... | @@ -110,15 +105,20 @@ public class DistributedLockManager implements LockService { | ... | @@ -110,15 +105,20 @@ public class DistributedLockManager implements LockService { |
110 | return; | 105 | return; |
111 | } | 106 | } |
112 | 107 | ||
113 | - Iterator<LockRequest> existingRequestIterator = existingRequests.iterator(); | 108 | + synchronized (existingRequests) { |
114 | - while (existingRequestIterator.hasNext()) { | 109 | + |
115 | - LockRequest request = existingRequestIterator.next(); | 110 | + Iterator<LockRequest> existingRequestIterator = existingRequests |
116 | - if (request.expirationTime().isAfter(DateTime.now())) { | 111 | + .iterator(); |
117 | - existingRequestIterator.remove(); | 112 | + while (existingRequestIterator.hasNext()) { |
118 | - } else { | 113 | + LockRequest request = existingRequestIterator.next(); |
119 | - if (request.lock().tryLock(request.leaseDurationMillis())) { | 114 | + if (request.expirationTime().isAfter(DateTime.now())) { |
120 | - request.future().complete(null); | 115 | + existingRequestIterator.remove(); |
121 | - existingRequests.remove(0); | 116 | + } else { |
117 | + if (request.lock().tryLock( | ||
118 | + request.leaseDurationMillis())) { | ||
119 | + request.future().complete(null); | ||
120 | + existingRequestIterator.remove(); | ||
121 | + } | ||
122 | } | 122 | } |
123 | } | 123 | } |
124 | } | 124 | } |
... | @@ -133,14 +133,12 @@ public class DistributedLockManager implements LockService { | ... | @@ -133,14 +133,12 @@ public class DistributedLockManager implements LockService { |
133 | private final int leaseDurationMillis; | 133 | private final int leaseDurationMillis; |
134 | private final CompletableFuture<Void> future; | 134 | private final CompletableFuture<Void> future; |
135 | 135 | ||
136 | - public LockRequest( | 136 | + public LockRequest(Lock lock, long waitTimeMillis, |
137 | - Lock lock, | 137 | + int leaseDurationMillis, CompletableFuture<Void> future) { |
138 | - long waitTimeMillis, | ||
139 | - int leaseDurationMillis, | ||
140 | - CompletableFuture<Void> future) { | ||
141 | 138 | ||
142 | this.lock = lock; | 139 | this.lock = lock; |
143 | - this.expirationTime = DateTime.now().plusMillis((int) waitTimeMillis); | 140 | + this.expirationTime = DateTime.now().plusMillis( |
141 | + (int) waitTimeMillis); | ||
144 | this.leaseDurationMillis = leaseDurationMillis; | 142 | this.leaseDurationMillis = leaseDurationMillis; |
145 | this.future = future; | 143 | this.future = future; |
146 | } | 144 | } | ... | ... |
1 | package org.onlab.onos.store.service.impl; | 1 | package org.onlab.onos.store.service.impl; |
2 | 2 | ||
3 | +import org.onlab.onos.store.service.VersionedValue; | ||
4 | + | ||
3 | /** | 5 | /** |
4 | * A table modification event. | 6 | * A table modification event. |
5 | */ | 7 | */ |
... | @@ -17,41 +19,46 @@ public final class TableModificationEvent { | ... | @@ -17,41 +19,46 @@ public final class TableModificationEvent { |
17 | 19 | ||
18 | private final String tableName; | 20 | private final String tableName; |
19 | private final String key; | 21 | private final String key; |
22 | + private final VersionedValue value; | ||
20 | private final Type type; | 23 | private final Type type; |
21 | 24 | ||
22 | /** | 25 | /** |
23 | * Creates a new row deleted table modification event. | 26 | * Creates a new row deleted table modification event. |
24 | * @param tableName table name. | 27 | * @param tableName table name. |
25 | * @param key row key | 28 | * @param key row key |
29 | + * @param value value associated with the key when it was deleted. | ||
26 | * @return table modification event. | 30 | * @return table modification event. |
27 | */ | 31 | */ |
28 | - public static TableModificationEvent rowDeleted(String tableName, String key) { | 32 | + public static TableModificationEvent rowDeleted(String tableName, String key, VersionedValue value) { |
29 | - return new TableModificationEvent(tableName, key, Type.ROW_DELETED); | 33 | + return new TableModificationEvent(tableName, key, value, Type.ROW_DELETED); |
30 | } | 34 | } |
31 | 35 | ||
32 | /** | 36 | /** |
33 | * Creates a new row added table modification event. | 37 | * Creates a new row added table modification event. |
34 | * @param tableName table name. | 38 | * @param tableName table name. |
35 | * @param key row key | 39 | * @param key row key |
40 | + * @param value value associated with the key | ||
36 | * @return table modification event. | 41 | * @return table modification event. |
37 | */ | 42 | */ |
38 | - public static TableModificationEvent rowAdded(String tableName, String key) { | 43 | + public static TableModificationEvent rowAdded(String tableName, String key, VersionedValue value) { |
39 | - return new TableModificationEvent(tableName, key, Type.ROW_ADDED); | 44 | + return new TableModificationEvent(tableName, key, value, Type.ROW_ADDED); |
40 | } | 45 | } |
41 | 46 | ||
42 | /** | 47 | /** |
43 | * Creates a new row updated table modification event. | 48 | * Creates a new row updated table modification event. |
44 | * @param tableName table name. | 49 | * @param tableName table name. |
45 | * @param key row key | 50 | * @param key row key |
51 | + * @param newValue value | ||
46 | * @return table modification event. | 52 | * @return table modification event. |
47 | */ | 53 | */ |
48 | - public static TableModificationEvent rowUpdated(String tableName, String key) { | 54 | + public static TableModificationEvent rowUpdated(String tableName, String key, VersionedValue newValue) { |
49 | - return new TableModificationEvent(tableName, key, Type.ROW_UPDATED); | 55 | + return new TableModificationEvent(tableName, key, newValue, Type.ROW_UPDATED); |
50 | } | 56 | } |
51 | 57 | ||
52 | - private TableModificationEvent(String tableName, String key, Type type) { | 58 | + private TableModificationEvent(String tableName, String key, VersionedValue value, Type type) { |
53 | this.tableName = tableName; | 59 | this.tableName = tableName; |
54 | this.key = key; | 60 | this.key = key; |
61 | + this.value = value; | ||
55 | this.type = type; | 62 | this.type = type; |
56 | } | 63 | } |
57 | 64 | ||
... | @@ -72,6 +79,15 @@ public final class TableModificationEvent { | ... | @@ -72,6 +79,15 @@ public final class TableModificationEvent { |
72 | } | 79 | } |
73 | 80 | ||
74 | /** | 81 | /** |
82 | + * Returns the value associated with the key. If the event for a deletion, this | ||
83 | + * method returns value that was deleted. | ||
84 | + * @return row value | ||
85 | + */ | ||
86 | + public VersionedValue value() { | ||
87 | + return value; | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
75 | * Returns the type of table modification event. | 91 | * Returns the type of table modification event. |
76 | * @return event type. | 92 | * @return event type. |
77 | */ | 93 | */ | ... | ... |
... | @@ -176,7 +176,7 @@ | ... | @@ -176,7 +176,7 @@ |
176 | com.hazelcast.map.merge.HigherHitsMapMergePolicy ; entry with the higher hits wins. | 176 | com.hazelcast.map.merge.HigherHitsMapMergePolicy ; entry with the higher hits wins. |
177 | com.hazelcast.map.merge.LatestUpdateMapMergePolicy ; entry with the latest update wins. | 177 | com.hazelcast.map.merge.LatestUpdateMapMergePolicy ; entry with the latest update wins. |
178 | --> | 178 | --> |
179 | - <merge-policy>com.hazelcast.map.merge.PassThroughMergePolicy</merge-policy> | 179 | + <merge-policy>com.hazelcast.map.merge.PutIfAbsentMapMergePolicy</merge-policy> |
180 | 180 | ||
181 | </map> | 181 | </map> |
182 | 182 | ... | ... |
... | @@ -13,6 +13,8 @@ jar=$(find org/onlab -type f -name '*.jar' | grep -e $1 | grep -v -e -tests | he | ... | @@ -13,6 +13,8 @@ jar=$(find org/onlab -type f -name '*.jar' | grep -e $1 | grep -v -e -tests | he |
13 | 13 | ||
14 | bundle=$(echo $(basename $jar .jar) | sed 's/-[0-9].*//g') | 14 | bundle=$(echo $(basename $jar .jar) | sed 's/-[0-9].*//g') |
15 | 15 | ||
16 | +echo "pushing bundle: $bundle" | ||
17 | + | ||
16 | nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2) | 18 | nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2) |
17 | for node in $nodes; do | 19 | for node in $nodes; do |
18 | scp -q $jar $ONOS_USER@$node:.m2/repository/$jar | 20 | scp -q $jar $ONOS_USER@$node:.m2/repository/$jar | ... | ... |
... | @@ -39,30 +39,23 @@ | ... | @@ -39,30 +39,23 @@ |
39 | </dependency> | 39 | </dependency> |
40 | 40 | ||
41 | <dependency> | 41 | <dependency> |
42 | - <groupId>net.kuujo.copycat</groupId> | 42 | + <groupId>net.jodah</groupId> |
43 | - <artifactId>copycat</artifactId> | 43 | + <artifactId>expiringmap</artifactId> |
44 | - <version>${copycat.version}</version> | 44 | + <version>0.3.1</version> |
45 | </dependency> | 45 | </dependency> |
46 | -<!-- Commented out due to Chronicle + OSGi issue | 46 | + |
47 | <dependency> | 47 | <dependency> |
48 | <groupId>net.kuujo.copycat</groupId> | 48 | <groupId>net.kuujo.copycat</groupId> |
49 | - <artifactId>copycat-chronicle</artifactId> | 49 | + <artifactId>copycat</artifactId> |
50 | <version>${copycat.version}</version> | 50 | <version>${copycat.version}</version> |
51 | </dependency> | 51 | </dependency> |
52 | ---> | 52 | + |
53 | <dependency> | 53 | <dependency> |
54 | <groupId>net.kuujo.copycat</groupId> | 54 | <groupId>net.kuujo.copycat</groupId> |
55 | <artifactId>copycat-tcp</artifactId> | 55 | <artifactId>copycat-tcp</artifactId> |
56 | <version>${copycat.version}</version> | 56 | <version>${copycat.version}</version> |
57 | </dependency> | 57 | </dependency> |
58 | 58 | ||
59 | -<!-- chronicle transitive dependency | ||
60 | - <dependency> | ||
61 | - <groupId>net.java.dev.jna</groupId> | ||
62 | - <artifactId>jna</artifactId> | ||
63 | - <version>4.1.0</version> | ||
64 | - </dependency> | ||
65 | ---> | ||
66 | </dependencies> | 59 | </dependencies> |
67 | 60 | ||
68 | <build> | 61 | <build> |
... | @@ -89,20 +82,19 @@ | ... | @@ -89,20 +82,19 @@ |
89 | </filter> | 82 | </filter> |
90 | 83 | ||
91 | <filter> | 84 | <filter> |
92 | - <artifact>net.kuujo.copycat:*</artifact> | 85 | + <artifact>net.jodah.expiringmap:*</artifact> |
93 | <includes> | 86 | <includes> |
94 | - <include>net/kuujo/copycat/**</include> | 87 | + <include>net/jodah/expiringmap/**</include> |
95 | </includes> | 88 | </includes> |
96 | </filter> | 89 | </filter> |
97 | -<!-- chronicle transitive dependency | ||
98 | 90 | ||
99 | <filter> | 91 | <filter> |
100 | - <artifact>net.java.dev.jna:*</artifact> | 92 | + <artifact>net.kuujo.copycat:*</artifact> |
101 | <includes> | 93 | <includes> |
102 | - <include>com/sun/jna/**</include> | 94 | + <include>net/kuujo/copycat/**</include> |
103 | </includes> | 95 | </includes> |
104 | </filter> | 96 | </filter> |
105 | ---> | 97 | + |
106 | </filters> | 98 | </filters> |
107 | </configuration> | 99 | </configuration> |
108 | <executions> | 100 | <executions> |
... | @@ -120,7 +112,7 @@ | ... | @@ -120,7 +112,7 @@ |
120 | <configuration> | 112 | <configuration> |
121 | <instructions> | 113 | <instructions> |
122 | <Export-Package> | 114 | <Export-Package> |
123 | - com.googlecode.concurrenttrees.*;net.kuujo.copycat.* | 115 | + com.googlecode.concurrenttrees.*;net.kuujo.copycat.*;net.jodah.expiringmap.* |
124 | </Export-Package> | 116 | </Export-Package> |
125 | </instructions> | 117 | </instructions> |
126 | </configuration> | 118 | </configuration> | ... | ... |
... | @@ -146,3 +146,24 @@ | ... | @@ -146,3 +146,24 @@ |
146 | border: 0; | 146 | border: 0; |
147 | } | 147 | } |
148 | 148 | ||
149 | +/* Web Socket Closed Mask (starts hidden) */ | ||
150 | + | ||
151 | +#topo-mask { | ||
152 | + display: none; | ||
153 | + position: absolute; | ||
154 | + top: 0; | ||
155 | + left: 0; | ||
156 | + width: 10000px; | ||
157 | + height: 8000px; | ||
158 | + z-index: 5000; | ||
159 | + background-color: rgba(0,0,0,0.75); | ||
160 | + padding: 60px; | ||
161 | +} | ||
162 | + | ||
163 | +#topo-mask p { | ||
164 | + margin: 8px 20px; | ||
165 | + color: #ddd; | ||
166 | + font-size: 14pt; | ||
167 | + font-style: italic; | ||
168 | +} | ||
169 | + | ... | ... |
... | @@ -151,6 +151,7 @@ | ... | @@ -151,6 +151,7 @@ |
151 | debug: false | 151 | debug: false |
152 | }, | 152 | }, |
153 | webSock, | 153 | webSock, |
154 | + sid = 0, | ||
154 | deviceLabelIndex = 0, | 155 | deviceLabelIndex = 0, |
155 | hostLabelIndex = 0, | 156 | hostLabelIndex = 0, |
156 | detailPane, | 157 | detailPane, |
... | @@ -169,7 +170,8 @@ | ... | @@ -169,7 +170,8 @@ |
169 | nodeG, | 170 | nodeG, |
170 | linkG, | 171 | linkG, |
171 | node, | 172 | node, |
172 | - link; | 173 | + link, |
174 | + mask; | ||
173 | 175 | ||
174 | // ============================== | 176 | // ============================== |
175 | // For Debugging / Development | 177 | // For Debugging / Development |
... | @@ -193,10 +195,6 @@ | ... | @@ -193,10 +195,6 @@ |
193 | 195 | ||
194 | function testMe(view) { | 196 | function testMe(view) { |
195 | view.alert('test'); | 197 | view.alert('test'); |
196 | - detailPane.show(); | ||
197 | - setTimeout(function () { | ||
198 | - detailPane.hide(); | ||
199 | - }, 3000); | ||
200 | } | 198 | } |
201 | 199 | ||
202 | function abortIfLive() { | 200 | function abortIfLive() { |
... | @@ -1059,6 +1057,7 @@ | ... | @@ -1059,6 +1057,7 @@ |
1059 | webSock.ws = new WebSocket(webSockUrl()); | 1057 | webSock.ws = new WebSocket(webSockUrl()); |
1060 | 1058 | ||
1061 | webSock.ws.onopen = function() { | 1059 | webSock.ws.onopen = function() { |
1060 | + noWebSock(false); | ||
1062 | }; | 1061 | }; |
1063 | 1062 | ||
1064 | webSock.ws.onmessage = function(m) { | 1063 | webSock.ws.onmessage = function(m) { |
... | @@ -1070,6 +1069,7 @@ | ... | @@ -1070,6 +1069,7 @@ |
1070 | 1069 | ||
1071 | webSock.ws.onclose = function(m) { | 1070 | webSock.ws.onclose = function(m) { |
1072 | webSock.ws = null; | 1071 | webSock.ws = null; |
1072 | + noWebSock(true); | ||
1073 | }; | 1073 | }; |
1074 | }, | 1074 | }, |
1075 | 1075 | ||
... | @@ -1089,7 +1089,9 @@ | ... | @@ -1089,7 +1089,9 @@ |
1089 | 1089 | ||
1090 | }; | 1090 | }; |
1091 | 1091 | ||
1092 | - var sid = 0; | 1092 | + function noWebSock(b) { |
1093 | + mask.style('display',b ? 'block' : 'none'); | ||
1094 | + } | ||
1093 | 1095 | ||
1094 | // TODO: use cache of pending messages (key = sid) to reconcile responses | 1096 | // TODO: use cache of pending messages (key = sid) to reconcile responses |
1095 | 1097 | ||
... | @@ -1273,6 +1275,11 @@ | ... | @@ -1273,6 +1275,11 @@ |
1273 | 1275 | ||
1274 | } | 1276 | } |
1275 | 1277 | ||
1278 | + | ||
1279 | + function para(sel, text) { | ||
1280 | + sel.append('p').text(text); | ||
1281 | + } | ||
1282 | + | ||
1276 | // ============================== | 1283 | // ============================== |
1277 | // View life-cycle callbacks | 1284 | // View life-cycle callbacks |
1278 | 1285 | ||
... | @@ -1367,6 +1374,12 @@ | ... | @@ -1367,6 +1374,12 @@ |
1367 | .on('tick', tick); | 1374 | .on('tick', tick); |
1368 | 1375 | ||
1369 | network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd); | 1376 | network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd); |
1377 | + | ||
1378 | + // create mask layer for when we lose connection to server. | ||
1379 | + mask = view.$div.append('div').attr('id','topo-mask'); | ||
1380 | + para(mask, 'Oops!'); | ||
1381 | + para(mask, 'Web-socket connection to server closed...'); | ||
1382 | + para(mask, 'Try refreshing the page.'); | ||
1370 | } | 1383 | } |
1371 | 1384 | ||
1372 | function load(view, ctx, flags) { | 1385 | function load(view, ctx, flags) { | ... | ... |
-
Please register or login to post a comment