Madan Jampani

Added a WallClockTimestamp and associated interface/implementation for generatin…

…g it. This will be used by the initial implementation of distributed host store
1 +package org.onlab.onos.net.host;
2 +
3 +import org.onlab.onos.store.Timestamp;
4 +import org.onlab.packet.MacAddress;
5 +
6 +/**
7 + * Interface for a logical clock service that issues per host timestamps.
8 + */
9 +public interface HostClockService {
10 +
11 + /**
12 + * Returns a new timestamp for the specified host mac address.
13 + * @param hostMac host MAC address.
14 + * @return timestamp.
15 + */
16 + public Timestamp getTimestamp(MacAddress hostMac);
17 +}
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import org.apache.felix.scr.annotations.Activate;
6 +import org.apache.felix.scr.annotations.Component;
7 +import org.apache.felix.scr.annotations.Deactivate;
8 +import org.apache.felix.scr.annotations.Service;
9 +import org.onlab.onos.net.host.HostClockService;
10 +import org.onlab.onos.store.Timestamp;
11 +import org.onlab.onos.store.impl.WallClockTimestamp;
12 +import org.onlab.packet.MacAddress;
13 +import org.slf4j.Logger;
14 +
15 +/**
16 + * HostClockService to issue Timestamps based on local wallclock time.
17 + */
18 +@Component(immediate = true)
19 +@Service
20 +public class HostClockManager implements HostClockService {
21 +
22 + private final Logger log = getLogger(getClass());
23 +
24 + @Activate
25 + public void activate() {
26 + log.info("Started");
27 + }
28 +
29 + @Deactivate
30 + public void deactivate() {
31 + log.info("Stopped");
32 + }
33 +
34 + @Override
35 + public Timestamp getTimestamp(MacAddress hostMac) {
36 + return new WallClockTimestamp();
37 + }
38 +}
...@@ -10,8 +10,12 @@ import com.google.common.base.MoreObjects; ...@@ -10,8 +10,12 @@ import com.google.common.base.MoreObjects;
10 import com.google.common.collect.ComparisonChain; 10 import com.google.common.collect.ComparisonChain;
11 11
12 /** 12 /**
13 - * Default implementation of Timestamp. 13 + * A logical timestamp that derives its value from two things:
14 - * TODO: Better documentation. 14 + * <ul>
15 + * <li> The current mastership term of the device.</li>
16 + * <li> The value of the counter used for tracking topology events observed from
17 + * the device during that current time of a device. </li>
18 + * </ul>
15 */ 19 */
16 public final class MastershipBasedTimestamp implements Timestamp { 20 public final class MastershipBasedTimestamp implements Timestamp {
17 21
......
1 +package org.onlab.onos.store.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkArgument;
4 +
5 +import java.util.Objects;
6 +
7 +import org.onlab.onos.store.Timestamp;
8 +
9 +import com.google.common.base.MoreObjects;
10 +import com.google.common.collect.ComparisonChain;
11 +
12 +/**
13 + * A Timestamp that derives its value from the prevailing
14 + * wallclock time on the controller where it is generated.
15 + */
16 +public class WallClockTimestamp implements Timestamp {
17 +
18 + private final long unixTimestamp;
19 +
20 + public WallClockTimestamp() {
21 + unixTimestamp = System.currentTimeMillis();
22 + }
23 +
24 + @Override
25 + public int compareTo(Timestamp o) {
26 + checkArgument(o instanceof WallClockTimestamp,
27 + "Must be WallClockTimestamp", o);
28 + WallClockTimestamp that = (WallClockTimestamp) o;
29 +
30 + return ComparisonChain.start()
31 + .compare(this.unixTimestamp, that.unixTimestamp)
32 + .result();
33 + }
34 + @Override
35 + public int hashCode() {
36 + return Objects.hash(unixTimestamp);
37 + }
38 +
39 + @Override
40 + public boolean equals(Object obj) {
41 + if (this == obj) {
42 + return true;
43 + }
44 + if (!(obj instanceof WallClockTimestamp)) {
45 + return false;
46 + }
47 + WallClockTimestamp that = (WallClockTimestamp) obj;
48 + return Objects.equals(this.unixTimestamp, that.unixTimestamp);
49 + }
50 +
51 + @Override
52 + public String toString() {
53 + return MoreObjects.toStringHelper(getClass())
54 + .add("unixTimestamp", unixTimestamp)
55 + .toString();
56 + }
57 +
58 + /**
59 + * Returns the unixTimestamp.
60 + *
61 + * @return unix timestamp
62 + */
63 + public long unixTimestamp() {
64 + return unixTimestamp;
65 + }
66 +}
1 +package org.onlab.onos.store.impl;
2 +
3 +import static org.junit.Assert.assertTrue;
4 +
5 +import java.nio.ByteBuffer;
6 +
7 +import org.junit.Test;
8 +import org.onlab.onos.store.Timestamp;
9 +import org.onlab.util.KryoPool;
10 +
11 +import com.google.common.testing.EqualsTester;
12 +
13 +/**
14 + * Tests for {@link WallClockTimestamp}.
15 + */
16 +public class WallClockTimestampTest {
17 +
18 + @Test
19 + public final void testBasic() throws InterruptedException {
20 + WallClockTimestamp ts1 = new WallClockTimestamp();
21 + Thread.sleep(50);
22 + WallClockTimestamp ts2 = new WallClockTimestamp();
23 +
24 + assertTrue(ts1.compareTo(ts1) == 0);
25 + assertTrue(ts2.compareTo(ts1) > 0);
26 + assertTrue(ts1.compareTo(ts2) < 0);
27 + }
28 +
29 + @Test
30 + public final void testKryoSerializable() {
31 + WallClockTimestamp ts1 = new WallClockTimestamp();
32 + final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
33 + final KryoPool kryos = KryoPool.newBuilder()
34 + .register(WallClockTimestamp.class)
35 + .build();
36 +
37 + kryos.serialize(ts1, buffer);
38 + buffer.flip();
39 + Timestamp copy = kryos.deserialize(buffer);
40 +
41 + new EqualsTester()
42 + .addEqualityGroup(ts1, copy)
43 + .testEquals();
44 + }
45 +}