Praseed Balakrishnan

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

...@@ -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 + if (!dbAdminService.listTables().contains(someTable)) {
160 dbAdminService.createTable(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(),
76 - DATABASE_UPDATES,
77 DatabaseStateMachine.SERIALIZER.encode(event))); 82 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);
127 } 139 }
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
......
...@@ -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) {
109 +
110 + Iterator<LockRequest> existingRequestIterator = existingRequests
111 + .iterator();
114 while (existingRequestIterator.hasNext()) { 112 while (existingRequestIterator.hasNext()) {
115 LockRequest request = existingRequestIterator.next(); 113 LockRequest request = existingRequestIterator.next();
116 if (request.expirationTime().isAfter(DateTime.now())) { 114 if (request.expirationTime().isAfter(DateTime.now())) {
117 existingRequestIterator.remove(); 115 existingRequestIterator.remove();
118 } else { 116 } else {
119 - if (request.lock().tryLock(request.leaseDurationMillis())) { 117 + if (request.lock().tryLock(
118 + request.leaseDurationMillis())) {
120 request.future().complete(null); 119 request.future().complete(null);
121 - existingRequests.remove(0); 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) {
......