Changing Intent Ids to use explicit id assignment
Change-Id: I5a4bff87842c37a869e7691b353529eaefc929db
diff --git a/core/api/src/main/java/org/onlab/onos/core/CoreService.java b/core/api/src/main/java/org/onlab/onos/core/CoreService.java
index 28145eb..c1499f7b 100644
--- a/core/api/src/main/java/org/onlab/onos/core/CoreService.java
+++ b/core/api/src/main/java/org/onlab/onos/core/CoreService.java
@@ -58,4 +58,12 @@
*/
ApplicationId registerApplication(String identifier);
+ /**
+ * Returns an id generator for a given topic.
+ *
+ * @param topic topic identified
+ * @return the id generator
+ */
+ IdGenerator getIdGenerator(String topic);
+
}
diff --git a/core/api/src/main/java/org/onlab/onos/core/IdBlock.java b/core/api/src/main/java/org/onlab/onos/core/IdBlock.java
new file mode 100644
index 0000000..c811e88
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/core/IdBlock.java
@@ -0,0 +1,87 @@
+package org.onlab.onos.core;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * A class representing an ID space.
+ */
+public final class IdBlock {
+ private final long start;
+ private final long size;
+
+ private final AtomicLong currentId;
+
+ /**
+ * Constructs a new ID block with the specified size and initial value.
+ *
+ * @param start initial value of the block
+ * @param size size of the block
+ * @throws IllegalArgumentException if the size is less than or equal to 0
+ */
+ public IdBlock(long start, long size) {
+ checkArgument(size > 0, "size should be more than 0, but %s", size);
+
+ this.start = start;
+ this.size = size;
+
+ this.currentId = new AtomicLong(start);
+ }
+
+ /**
+ * Returns the initial value.
+ *
+ * @return initial value
+ */
+ private long getStart() {
+ return start;
+ }
+
+ /**
+ * Returns the last value.
+ *
+ * @return last value
+ */
+ private long getEnd() {
+ return start + size - 1;
+ }
+
+ /**
+ * Returns the block size.
+ *
+ * @return block size
+ */
+ public long getSize() {
+ return size;
+ }
+
+ /**
+ * Returns the next ID in the block.
+ *
+ * @return next ID
+ * @throws UnavailableIdException if there is no available ID in the block.
+ */
+ public long getNextId() {
+ final long id = currentId.getAndIncrement();
+ if (id > getEnd()) {
+ throw new UnavailableIdException(String.format(
+ "used all IDs in allocated space (size: %d, end: %d, current: %d)",
+ size, getEnd(), id
+ ));
+ }
+
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("start", start)
+ .add("size", size)
+ .add("currentId", currentId)
+ .toString();
+ }
+}
diff --git a/core/api/src/main/java/org/onlab/onos/core/IdBlockStore.java b/core/api/src/main/java/org/onlab/onos/core/IdBlockStore.java
new file mode 100644
index 0000000..e67a2fe
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/core/IdBlockStore.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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 org.onlab.onos.core;
+
+/**
+ * Manages id blocks.
+ */
+public interface IdBlockStore {
+
+ /**
+ * Returns a topic-unique block of ids.
+ *
+ * @param topic topic name
+ * @return id block
+ */
+ IdBlock getIdBlock(String topic);
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/core/IdGenerator.java b/core/api/src/main/java/org/onlab/onos/core/IdGenerator.java
new file mode 100644
index 0000000..fb8953b
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/core/IdGenerator.java
@@ -0,0 +1,16 @@
+package org.onlab.onos.core;
+
+/**
+ * A generalized interface for ID generation
+ *
+ * {@link #getNewId()} generates a globally unique ID instance on
+ * each invocation.
+ */
+public interface IdGenerator {
+ /**
+ * Returns a globally unique ID instance.
+ *
+ * @return globally unique ID instance
+ */
+ long getNewId();
+}
diff --git a/core/api/src/main/java/org/onlab/onos/core/UnavailableIdException.java b/core/api/src/main/java/org/onlab/onos/core/UnavailableIdException.java
new file mode 100644
index 0000000..14c8496
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/core/UnavailableIdException.java
@@ -0,0 +1,34 @@
+package org.onlab.onos.core;
+
+/**
+ * Represents that there is no available IDs.
+ */
+public class UnavailableIdException extends RuntimeException {
+
+ private static final long serialVersionUID = -2287403908433720122L;
+
+ /**
+ * Constructs an exception with no message and no underlying cause.
+ */
+ public UnavailableIdException() {
+ }
+
+ /**
+ * Constructs an exception with the specified message.
+ *
+ * @param message the message describing the specific nature of the error
+ */
+ public UnavailableIdException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with the specified message and the underlying cause.
+ *
+ * @param message the message describing the specific nature of the error
+ * @param cause the underlying cause of this error
+ */
+ public UnavailableIdException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java
index 2a4aaeb..9059522 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java
@@ -51,18 +51,17 @@
* Path will be chosen without any constraints.
* </p>
*
- * @param id intent identifier
* @param appId application identifier
* @param resources required network resources (optional)
* @param selector traffic selector
* @param treatment treatment
* @throws NullPointerException if the selector or treatement is null
*/
- protected ConnectivityIntent(IntentId id, ApplicationId appId,
+ protected ConnectivityIntent(ApplicationId appId,
Collection<NetworkResource> resources,
TrafficSelector selector,
TrafficTreatment treatment) {
- this(id, appId, resources, selector, treatment, Collections.emptyList());
+ this(appId, resources, selector, treatment, Collections.emptyList());
}
/**
@@ -72,7 +71,6 @@
* Path will be optimized based on the first constraint if one is given.
* </p>
*
- * @param id intent identifier
* @param appId application identifier
* @param resources required network resources (optional)
* @param selector traffic selector
@@ -80,12 +78,12 @@
* @param constraints optional prioritized list of constraints
* @throws NullPointerException if the selector or treatement is null
*/
- protected ConnectivityIntent(IntentId id, ApplicationId appId,
+ protected ConnectivityIntent(ApplicationId appId,
Collection<NetworkResource> resources,
TrafficSelector selector,
TrafficTreatment treatment,
List<Constraint> constraints) {
- super(id, appId, resources);
+ super(appId, resources);
this.selector = checkNotNull(selector);
this.treatment = checkNotNull(treatment);
this.constraints = checkNotNull(constraints);
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
index b9baf10..c65d19c 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
@@ -68,9 +68,7 @@
TrafficSelector selector,
TrafficTreatment treatment,
List<Constraint> constraints) {
- super(id(HostToHostIntent.class, min(one, two), max(one, two),
- selector, treatment, constraints),
- appId, null, selector, treatment, constraints);
+ super(appId, null, selector, treatment, constraints);
// TODO: consider whether the case one and two are same is allowed
this.one = checkNotNull(one);
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java b/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java
index 657a3e4..b57e375 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java
@@ -16,14 +16,15 @@
package org.onlab.onos.net.intent;
import org.onlab.onos.core.ApplicationId;
+import org.onlab.onos.core.IdGenerator;
import org.onlab.onos.net.NetworkResource;
import org.onlab.onos.net.flow.BatchOperationTarget;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
/**
* Abstraction of an application level intent.
@@ -37,6 +38,8 @@
private final ApplicationId appId;
private final Collection<NetworkResource> resources;
+ private static IdGenerator idGenerator;
+
/**
* Constructor for serializer.
*/
@@ -49,13 +52,13 @@
/**
* Creates a new intent.
*
- * @param id intent identifier
- * @param appId application identifier
- * @param resources required network resources (optional)
+ * @param appId application identifier
+ * @param resources required network resources (optional)
*/
- protected Intent(IntentId id, ApplicationId appId,
+ protected Intent(ApplicationId appId,
Collection<NetworkResource> resources) {
- this.id = checkNotNull(id, "Intent ID cannot be null");
+ checkState(idGenerator != null, "Id generator is not bound.");
+ this.id = IntentId.valueOf(idGenerator.getNewId());
this.appId = checkNotNull(appId, "Application ID cannot be null");
this.resources = resources;
}
@@ -88,20 +91,6 @@
}
/**
- * Produces an intent identifier backed by hash-like fingerprint for the
- * specified class of intent and its constituent fields.
- *
- * @param intentClass Class of the intent
- * @param fields intent fields
- * @return intent identifier
- */
- protected static IntentId id(Class<?> intentClass, Object... fields) {
- // FIXME: spread the bits across the full long spectrum
- return IntentId.valueOf(Objects.hash(intentClass.getName(),
- Arrays.hashCode(fields)));
- }
-
- /**
* Indicates whether or not the intent is installable.
*
* @return true if installable
@@ -112,7 +101,7 @@
@Override
public final int hashCode() {
- return Objects.hash(id);
+ return id.hashCode();
}
@Override
@@ -124,7 +113,29 @@
return false;
}
final Intent other = (Intent) obj;
- return Objects.equals(this.id, other.id);
+ return this.id().equals(((Intent) obj).id());
}
+ /**
+ * Binds an id generator for unique intent id generation.
+ *
+ * Note: A generator cannot be bound if there is already a generator bound.
+ * @param newIdGenerator id generator
+ */
+ public static final void bindIdGenerator(IdGenerator newIdGenerator) {
+ checkState(idGenerator == null, "Id generator is already bound.");
+ idGenerator = checkNotNull(newIdGenerator);
+ }
+
+ /**
+ * Unbinds an id generator.
+ *
+ * Note: The caller must provide the old id generator to succeed.
+ * @param oldIdGenerator the current id generator
+ */
+ public static final void unbindIdGenerator(IdGenerator oldIdGenerator) {
+ if (Objects.equals(idGenerator, oldIdGenerator)) {
+ idGenerator = null;
+ }
+ }
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java b/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java
index c4c2752..2718e6e 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java
@@ -23,46 +23,46 @@
*/
public final class IntentId implements BatchOperationTarget {
- private final long fingerprint;
+ private final long value;
/**
* Creates an intent identifier from the specified string representation.
*
- * @param fingerprint long value
+ * @param value long value
* @return intent identifier
*/
- public static IntentId valueOf(long fingerprint) {
- return new IntentId(fingerprint);
+ public static IntentId valueOf(long value) {
+ return new IntentId(value);
}
/**
* Constructor for serializer.
*/
IntentId() {
- this.fingerprint = 0;
+ this.value = 0;
}
/**
* Constructs the ID corresponding to a given long value.
*
- * @param fingerprint the underlying value of this ID
+ * @param value the underlying value of this ID
*/
- IntentId(long fingerprint) {
- this.fingerprint = fingerprint;
+ IntentId(long value) {
+ this.value = value;
}
/**
- * Returns the backing fingerprint.
+ * Returns the backing value.
*
- * @return the fingerprint
+ * @return the value
*/
public long fingerprint() {
- return fingerprint;
+ return value;
}
@Override
public int hashCode() {
- return (int) (fingerprint ^ (fingerprint >>> 32));
+ return (int) (value ^ (value >>> 32));
}
@Override
@@ -74,12 +74,12 @@
return false;
}
IntentId that = (IntentId) obj;
- return this.fingerprint == that.fingerprint;
+ return this.value == that.value;
}
@Override
public String toString() {
- return "0x" + Long.toHexString(fingerprint);
+ return "0x" + Long.toHexString(value);
}
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
index 3844611..f34b65d 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
@@ -76,8 +76,7 @@
Set<Link> links,
ConnectPoint egressPoint,
List<Constraint> constraints) {
- super(id(LinkCollectionIntent.class, selector, treatment, links, egressPoint, constraints),
- appId, resources(links), selector, treatment, constraints);
+ super(appId, resources(links), selector, treatment, constraints);
this.links = links;
this.egressPoints = ImmutableSet.of(egressPoint);
}
@@ -99,8 +98,7 @@
Set<Link> links,
Set<ConnectPoint> egressPoints,
List<Constraint> constraints) {
- super(id(LinkCollectionIntent.class, selector, treatment, links,
- egressPoints), appId, resources(links), selector, treatment);
+ super(appId, resources(links), selector, treatment);
this.links = links;
this.egressPoints = ImmutableSet.copyOf(egressPoints);
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
index 15afedd..416768b 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
@@ -80,9 +80,7 @@
Set<ConnectPoint> ingressPoints,
ConnectPoint egressPoint,
List<Constraint> constraints) {
- super(id(MultiPointToSinglePointIntent.class, selector, treatment,
- ingressPoints, egressPoint), appId, null, selector, treatment,
- constraints);
+ super(appId, null, selector, treatment, constraints);
checkNotNull(ingressPoints);
checkArgument(!ingressPoints.isEmpty(), "Ingress point set cannot be empty");
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java
index 361f5dd..205fde6 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java
@@ -36,8 +36,7 @@
*/
public OpticalConnectivityIntent(ApplicationId appId,
ConnectPoint src, ConnectPoint dst) {
- super(id(OpticalConnectivityIntent.class, src, dst),
- appId, null);
+ super(appId, null);
this.src = src;
this.dst = dst;
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalPathIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalPathIntent.java
index 71a9187..e12e339 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalPathIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalPathIntent.java
@@ -37,9 +37,7 @@
ConnectPoint src,
ConnectPoint dst,
Path path) {
- super(id(OpticalPathIntent.class, src, dst, path),
- appId,
- ImmutableSet.<NetworkResource>copyOf(path.links()));
+ super(appId, ImmutableSet.<NetworkResource>copyOf(path.links()));
this.src = src;
this.dst = dst;
this.path = path;
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
index 5c13701..a21509d 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
@@ -64,8 +64,7 @@
*/
public PathIntent(ApplicationId appId, TrafficSelector selector,
TrafficTreatment treatment, Path path, List<Constraint> constraints) {
- super(id(PathIntent.class, selector, treatment, path, constraints), appId,
- resources(path.links()), selector, treatment, constraints);
+ super(appId, resources(path.links()), selector, treatment, constraints);
PathIntent.validate(path.links());
this.path = path;
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java
index b07a3a6..28af4c7 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java
@@ -73,9 +73,7 @@
ConnectPoint ingressPoint,
ConnectPoint egressPoint,
List<Constraint> constraints) {
- super(id(PointToPointIntent.class, selector, treatment,
- ingressPoint, egressPoint, constraints),
- appId, null, selector, treatment, constraints);
+ super(appId, null, selector, treatment, constraints);
checkNotNull(ingressPoint);
checkNotNull(egressPoint);
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java
index 7851e53..8c806bd 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java
@@ -75,9 +75,7 @@
TrafficSelector selector, TrafficTreatment treatment,
ConnectPoint ingressPoint, Set<ConnectPoint> egressPoints,
List<Constraint> constraints) {
- super(id(SinglePointToMultiPointIntent.class, selector, treatment,
- ingressPoint, egressPoints), appId, null, selector, treatment,
- constraints);
+ super(appId, null, selector, treatment, constraints);
checkNotNull(egressPoints);
checkNotNull(ingressPoint);
checkArgument(!egressPoints.isEmpty(), "Egress point set cannot be empty");