Moving LabelResourceManager to incubator
Breaking apart resource package into {device, link, label}
Refactored cluster serializers so they are visible
Change-Id: I71051bcd5e790ae6abeb154bf58286e584c32858
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/DefaultLabelResource.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/DefaultLabelResource.java
new file mode 100644
index 0000000..8eed7c1
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/DefaultLabelResource.java
@@ -0,0 +1,81 @@
+package org.onosproject.incubator.net.resource.label;
+
+import java.util.Objects;
+
+import org.onosproject.net.Annotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderId;
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * the implementation of a label resource of a device.
+ */
+public final class DefaultLabelResource implements LabelResource {
+
+ private DeviceId deviceId;
+
+ private LabelResourceId labelResourceId;
+
+ /**
+ * Initialize a label resource object.
+ * @param deviceId device identifier
+ * @param labelResourceId label resource id
+ */
+ public DefaultLabelResource(String deviceId, long labelResourceId) {
+ this.deviceId = DeviceId.deviceId(deviceId);
+ this.labelResourceId = LabelResourceId.labelResourceId(labelResourceId);
+ }
+
+ /**
+ * Initialize a label resource object.
+ * @param deviceId device identifier
+ * @param labelResourceId label resource id
+ */
+ public DefaultLabelResource(DeviceId deviceId,
+ LabelResourceId labelResourceId) {
+ this.deviceId = deviceId;
+ this.labelResourceId = labelResourceId;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public LabelResourceId labelResourceId() {
+ return labelResourceId;
+ }
+
+ @Override
+ public Annotations annotations() {
+ return null;
+ }
+
+ @Override
+ public ProviderId providerId() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId, labelResourceId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof DefaultLabelResource) {
+ DefaultLabelResource that = (DefaultLabelResource) obj;
+ return Objects.equals(this.deviceId, that.deviceId)
+ && Objects.equals(this.labelResourceId,
+ that.labelResourceId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("deviceId", deviceId)
+ .add("labelResourceId", labelResourceId).toString();
+ }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResource.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResource.java
new file mode 100644
index 0000000..612240f
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResource.java
@@ -0,0 +1,23 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.net.Annotated;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.Provided;
+
+/**
+ * Representation of label resource.
+ */
+public interface LabelResource extends Annotated, Provided, NetworkResource {
+ /**
+ * Returns device id.
+ * @return DeviceId
+ */
+ DeviceId deviceId();
+
+ /**
+ * Returns labelResource Id.
+ * @return LabelResourceId
+ */
+ LabelResourceId labelResourceId();
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceAdminService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceAdminService.java
new file mode 100644
index 0000000..6576ebf
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceAdminService.java
@@ -0,0 +1,49 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.net.DeviceId;
+
+/**
+ * Service for managing label resource.
+ */
+public interface LabelResourceAdminService {
+ /**
+ * Creates the only label resource of some device id from begin label to end
+ * label.
+ *
+ * @param deviceId device identifier
+ * @param beginLabel represents for the first label id in the range of label
+ * pool
+ * @param endLabel represents for the last label id in the range of label
+ * pool
+ * @return success or fail
+ */
+ boolean createDevicePool(DeviceId deviceId, LabelResourceId beginLabel,
+ LabelResourceId endLabel);
+
+ /**
+ * Creates the only global label resource pool.
+ *
+ * @param beginLabel represents for the first label id in the range of label
+ * pool
+ * @param endLabel represents for the last label id in the range of label
+ * pool
+ * @return success or fail
+ */
+ boolean createGlobalPool(LabelResourceId beginLabel,
+ LabelResourceId endLabel);
+
+ /**
+ * Destroys a label resource pool of a specific device id.
+ *
+ * @param deviceId device identifier
+ * @return success or fail
+ */
+ boolean destroyDevicePool(DeviceId deviceId);
+
+ /**
+ * Destroys the global label resource pool.
+ *
+ * @return success or fail
+ */
+ boolean destroyGlobalPool();
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceDelegate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceDelegate.java
new file mode 100644
index 0000000..25287b9
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceDelegate.java
@@ -0,0 +1,9 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.store.StoreDelegate;
+/**
+ * Label resource store delegate.
+ */
+public interface LabelResourceDelegate extends StoreDelegate<LabelResourceEvent> {
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceEvent.java
new file mode 100644
index 0000000..b532378
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceEvent.java
@@ -0,0 +1,38 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes label resource event.
+ */
+public final class LabelResourceEvent
+ extends AbstractEvent<LabelResourceEvent.Type, LabelResourcePool> {
+
+ /**
+ * Type of label resource event.
+ */
+ public enum Type {
+ /**
+ * Signifies that a new pool has been administratively created.
+ */
+ POOL_CREATED,
+ /**
+ * Signifies that a new pool has been administratively destroyed.
+ */
+ POOL_DESTROYED,
+ /**
+ * Signifies that a new pool has been administratively changed.
+ */
+ POOL_CAPACITY_CHANGED
+ }
+
+ /**
+ * Creates an event of a given type and the given LabelResourcePool.
+ *
+ * @param type event type
+ * @param subject pool
+ */
+ public LabelResourceEvent(Type type, LabelResourcePool subject) {
+ super(type, subject);
+ }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceId.java
new file mode 100644
index 0000000..688dbff
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceId.java
@@ -0,0 +1,46 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.net.resource.ResourceId;
+
+import java.util.Objects;
+
+/**
+ * Representation of a label.
+ */
+public final class LabelResourceId implements ResourceId {
+
+ private long labelId;
+
+ public static LabelResourceId labelResourceId(long labelResourceId) {
+ return new LabelResourceId(labelResourceId);
+ }
+
+ // Public construction is prohibited
+ private LabelResourceId(long labelId) {
+ this.labelId = labelId;
+ }
+
+ public long labelId() {
+ return labelId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(labelId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LabelResourceId) {
+ LabelResourceId that = (LabelResourceId) obj;
+ return Objects.equals(this.labelId, that.labelId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(this.labelId);
+ }
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceListener.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceListener.java
new file mode 100644
index 0000000..599a2b4
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceListener.java
@@ -0,0 +1,9 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.event.EventListener;
+/**
+ * Entity capable of receiving label resource related events.
+ */
+public interface LabelResourceListener extends EventListener<LabelResourceEvent> {
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourcePool.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourcePool.java
new file mode 100644
index 0000000..e590dd9
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourcePool.java
@@ -0,0 +1,173 @@
+package org.onosproject.incubator.net.resource.label;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+
+import org.onosproject.net.DeviceId;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Abstraction of the capacity of device label resource or global label
+ * resource. it's contiguous range of label resource.when a application apply
+ * some labels of some device,first catch from Set that store
+ * available labels,if the size of the Set less than the apply number,then get
+ * labels by calculating with three attributes, beginLabel,endLabel and
+ * currentUsedMaxLabelId
+ */
+public class LabelResourcePool {
+
+ private final DeviceId deviceId;
+ private final LabelResourceId beginLabel;
+ private final LabelResourceId endLabel;
+ private final long totalNum; // capacity of label resource pool
+ private final long usedNum; // have used label number
+ private final LabelResourceId currentUsedMaxLabelId; // the maximal label
+ // number id
+ private ImmutableSet<LabelResource> releaseLabelId; // Set of released label
+
+ /**
+ * Creates a pool by device id,begin label id,end label id.
+ *
+ * @param deviceId device identifier
+ * @param beginLabel represents for the first label id in the range of label
+ * resource pool
+ * @param endLabel represents for the last label id in the range of label
+ * resource pool
+ */
+ public LabelResourcePool(String deviceId, long beginLabel, long endLabel) {
+ this(deviceId, beginLabel, endLabel, endLabel - beginLabel + 1, 0L,
+ beginLabel, ImmutableSet.copyOf(Collections.emptySet()));
+ }
+
+ /**
+ * Creates a pool by device id,begin label id,end label id.
+ * used to update a pool in the store.
+ * @param deviceId device identifier
+ * @param beginLabel represents for the first label id in the range of label
+ * resource pool
+ * @param endLabel represents for the last label id in the range of label
+ * resource pool
+ * @param totalNum capacity of label resource pool
+ * @param usedNum have used label number
+ * @param currentUsedMaxLabelId the maximal label number id
+ * @param releaseLabelId Set of released label
+ */
+ public LabelResourcePool(String deviceId, long beginLabel, long endLabel,
+ long totalNum, long usedNum,
+ long currentUsedMaxLabelId,
+ ImmutableSet<LabelResource> releaseLabelId) {
+ checkArgument(endLabel >= beginLabel,
+ "endLabel %s must be greater than or equal to beginLabel %s",
+ endLabel, beginLabel);
+ this.deviceId = DeviceId.deviceId(deviceId);
+ this.beginLabel = LabelResourceId.labelResourceId(beginLabel);
+ this.endLabel = LabelResourceId.labelResourceId(endLabel);
+ this.totalNum = totalNum;
+ this.usedNum = usedNum;
+ this.currentUsedMaxLabelId = LabelResourceId
+ .labelResourceId(currentUsedMaxLabelId);
+ this.releaseLabelId = releaseLabelId;
+ }
+
+ /**
+ * Returns a device id.
+ *
+ * @return DeviceId
+ */
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ /**
+ * Returns a begin Label id.
+ *
+ * @return begin Label id
+ */
+ public LabelResourceId beginLabel() {
+ return beginLabel;
+ }
+
+ /**
+ * Returns a end Label id.
+ *
+ * @return end Label id
+ */
+ public LabelResourceId endLabel() {
+ return endLabel;
+ }
+
+ /**
+ * Returns a begin Label id.
+ *
+ * @return current Used Maximal Label Id
+ */
+ public LabelResourceId currentUsedMaxLabelId() {
+ return currentUsedMaxLabelId;
+ }
+
+ /**
+ * Returns total number.
+ *
+ * @return the total label number
+ */
+ public long totalNum() {
+ return totalNum;
+ }
+
+ /**
+ * Returns used number.
+ *
+ * @return the used label number
+ */
+ public long usedNum() {
+ return usedNum;
+ }
+
+ /**
+ * Returns the Set of released label before.
+ *
+ * @return the Set of LabelResource
+ */
+ public Set<LabelResource> releaseLabelId() {
+ return releaseLabelId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.deviceId, this.beginLabel, this.endLabel,
+ this.totalNum, this.usedNum,
+ this.currentUsedMaxLabelId, this.releaseLabelId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LabelResourcePool) {
+ LabelResourcePool that = (LabelResourcePool) obj;
+ return Objects.equals(this.deviceId, that.deviceId)
+ && Objects.equals(this.beginLabel, that.beginLabel)
+ && Objects.equals(this.endLabel, that.endLabel)
+ && Objects.equals(this.totalNum, that.totalNum)
+ && Objects.equals(this.usedNum, that.usedNum)
+ && Objects.equals(this.currentUsedMaxLabelId,
+ that.currentUsedMaxLabelId)
+ && Objects.equals(this.releaseLabelId, that.releaseLabelId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ // TODO Auto-generated method stub
+ return MoreObjects.toStringHelper(this).add("deviceId", this.deviceId)
+ .add("beginLabel", this.beginLabel)
+ .add("endLabel", this.endLabel).add("totalNum", this.totalNum)
+ .add("usedNum", this.usedNum)
+ .add("currentUsedMaxLabelId", this.currentUsedMaxLabelId)
+ .add("releaseLabelId", this.releaseLabelId).toString();
+ }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProvider.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProvider.java
new file mode 100644
index 0000000..d0b46d0
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProvider.java
@@ -0,0 +1,10 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.net.provider.Provider;
+/**
+ * Abstraction of an entity providing information about label resource
+ * to the core.
+ */
+public interface LabelResourceProvider extends Provider {
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProviderRegistry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProviderRegistry.java
new file mode 100644
index 0000000..4d50297
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProviderRegistry.java
@@ -0,0 +1,10 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.net.provider.ProviderRegistry;
+/**
+ * Abstraction of an label resource provider registry.
+ */
+public interface LabelResourceProviderRegistry
+ extends ProviderRegistry<LabelResourceProvider, LabelResourceProviderService> {
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProviderService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProviderService.java
new file mode 100644
index 0000000..e804cc9
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceProviderService.java
@@ -0,0 +1,26 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.provider.ProviderService;
+
+/**
+ * Means for injecting label information into the core.
+ */
+public interface LabelResourceProviderService extends ProviderService<LabelResourceProvider> {
+
+ /**
+ * Signals that a device label resource pool has been detected.
+ * @param deviceId device identifier
+ * @param beginLabel the begin label number of resource
+ * @param endLabel the end label number of resource
+ */
+ void deviceLabelResourcePoolDetected(DeviceId deviceId,
+ LabelResourceId beginLabel,
+ LabelResourceId endLabel);
+
+ /**
+ * Signals that an label resource pool has been destroyed.
+ * @param deviceId device identifier
+ */
+ void deviceLabelResourcePoolDestroyed(DeviceId deviceId);
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceRequest.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceRequest.java
new file mode 100644
index 0000000..7e429e2
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceRequest.java
@@ -0,0 +1,101 @@
+package org.onosproject.incubator.net.resource.label;
+
+import java.util.Collection;
+import java.util.Objects;
+
+import org.onosproject.net.DeviceId;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+/**
+ * Represents for a label request.
+ */
+public class LabelResourceRequest {
+
+ private final DeviceId deviceId;
+ private final Type type;
+ private final long applyNum;
+ private ImmutableSet<LabelResource> releaseCollection;
+
+ /**
+ * Creates LabelResourceRequest object.
+ * @param deviceId device identifier
+ * @param type request type
+ * @param applyNum apply the number of labels
+ * @param releaseCollection Set of released label
+ */
+ public LabelResourceRequest(DeviceId deviceId,
+ Type type,
+ long applyNum,
+ ImmutableSet<LabelResource> releaseCollection) {
+ this.deviceId = deviceId;
+ this.type = type;
+ this.applyNum = applyNum;
+ this.releaseCollection = releaseCollection;
+ }
+ /**
+ * Returns a device id.
+ * @return DeviceId
+ */
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ /**
+ * Returns request type.
+ * @return Type
+ */
+ public Type type() {
+ return type;
+ }
+
+ /**
+ * Returns apply label number.
+ * @return label number
+ */
+ public long applyNum() {
+ return applyNum;
+ }
+
+ /**
+ * Returns the collection of release labels.
+ * @return Collection of DefaultLabelResource
+ */
+ public Collection<LabelResource> releaseCollection() {
+ return releaseCollection;
+ }
+
+ /**
+ * Request type.
+ */
+ public enum Type {
+ APPLY, //apple label request
+ RELEASE //release label request
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.deviceId, this.applyNum, this.type,
+ this.releaseCollection);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof LabelResourceRequest) {
+ LabelResourceRequest that = (LabelResourceRequest) obj;
+ return Objects.equals(this.deviceId, that.deviceId)
+ && Objects.equals(this.applyNum, that.applyNum)
+ && Objects.equals(this.type, that.type)
+ && Objects.equals(this.releaseCollection,
+ that.releaseCollection);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("deviceId", this.deviceId)
+ .add("applyNum", this.applyNum).add("type", this.type)
+ .add("releaseCollection", this.releaseCollection).toString();
+ }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceService.java
new file mode 100644
index 0000000..9b35de1
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceService.java
@@ -0,0 +1,109 @@
+package org.onosproject.incubator.net.resource.label;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.onosproject.net.DeviceId;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * Service for providing label resource allocation.
+ */
+public interface LabelResourceService {
+
+ /**
+ * Returns labels from resource pool by a specific device id.
+ *
+ * @param deviceId device identifier
+ * @param applyNum the applying number
+ * @return collection of applying labels
+ */
+ Collection<LabelResource> applyFromDevicePool(DeviceId deviceId,
+ long applyNum);
+
+ /**
+ * Returns labels from the global label resource pool.
+ *
+ * @param applyNum the applying number
+ * @return collection of applying labels
+ */
+ Collection<LabelResource> applyFromGlobalPool(long applyNum);
+
+ /**
+ * Releases unused labels to device pools .
+ *
+ * @param release the collection of releasing labels
+ * @return success or fail
+ */
+ boolean releaseToDevicePool(Multimap<DeviceId, LabelResource> release);
+
+ /**
+ * Releases unused labels to the global resource pool.
+ *
+ * @param release release the collection of releasing labels
+ * @return success or fail
+ */
+ boolean releaseToGlobalPool(Set<LabelResourceId> release);
+
+ /**
+ * Judges if the pool of a specific device id is full.
+ *
+ * @param deviceId device identifier
+ * @return yes or no
+ */
+ boolean isDevicePoolFull(DeviceId deviceId);
+
+ /**
+ * Judges if the global resource pool is full.
+ *
+ * @return yes or no
+ */
+ boolean isGlobalPoolFull();
+
+ /**
+ * Returns the unused label number of a label resource pool by a specific device
+ * id.
+ *
+ * @param deviceId device identifier
+ * @return number of unused labels
+ */
+ long getFreeNumOfDevicePool(DeviceId deviceId);
+
+ /**
+ * Returns the unused label number of a global label resource pool.
+ *
+ * @return number of unused labels
+ */
+ long getFreeNumOfGlobalPool();
+
+ /**
+ * Returns the label resource pool of a label resource by a specific device
+ * id.
+ *
+ * @param deviceId device identifier
+ * @return the device label resource pool
+ */
+ LabelResourcePool getDeviceLabelResourcePool(DeviceId deviceId);
+
+ /**
+ * Returns the global label resource pool.
+ *
+ * @return the global label resource pool
+ */
+ LabelResourcePool getGlobalLabelResourcePool();
+
+ /**
+ * Adds the specified label resource listener.
+ *
+ * @param listener label resource listener
+ */
+ void addListener(LabelResourceListener listener);
+
+ /**
+ * Removes the specified label resource listener.
+ *
+ * @param listener label resource listener
+ */
+ void removeListener(LabelResourceListener listener);
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceStore.java
new file mode 100644
index 0000000..8fdc77d
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/resource/label/LabelResourceStore.java
@@ -0,0 +1,137 @@
+package org.onosproject.incubator.net.resource.label;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.Store;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * Manages inventory of label; not intended for direct use.
+ *
+ */
+public interface LabelResourceStore
+ extends Store<LabelResourceEvent, LabelResourceDelegate> {
+
+ /**
+ * Creates a label resource of some device id from begin label to end label.
+ *
+ * @param deviceId device identifier
+ * @param beginLabel represents for the first label id in the range of label
+ * pool
+ * @param endLabel represents for the last label id in the range of label
+ * pool
+ * @return success or fail
+ */
+ boolean createDevicePool(DeviceId deviceId, LabelResourceId beginLabel,
+ LabelResourceId endLabel);
+
+ /**
+ * Creates the global label resource pool.
+ *
+ * @param beginLabel represents for the first label id in the range of label
+ * pool
+ * @param endLabel represents for the last label id in the range of label
+ * pool
+ * @return success or fail
+ */
+ boolean createGlobalPool(LabelResourceId beginLabel,
+ LabelResourceId endLabel);
+
+ /**
+ * Destroys a label resource pool of a specific device id.
+ *
+ * @param deviceId device identifier
+ * @return success or fail
+ */
+ boolean destroyDevicePool(DeviceId deviceId);
+
+ /**
+ * Destroys a the global label resource pool.
+ *
+ * @return success or fail
+ */
+ boolean destroyGlobalPool();
+
+ /**
+ * Returns labels from resource pool by a specific device id.
+ *
+ * @param deviceId device identifier
+ * @param applyNum the applying number
+ * @return collection of applying labels
+ */
+ Collection<LabelResource> applyFromDevicePool(DeviceId deviceId,
+ long applyNum);
+
+ /**
+ * Returns labels from the global label resource pool.
+ *
+ * @param applyNum apply the number of labels
+ * @return collection of labels
+ */
+ Collection<LabelResource> applyFromGlobalPool(long applyNum);
+
+ /**
+ * Releases unused labels to device pools .
+ *
+ * @param release the collection of releasing labels
+ * @return success or fail
+ */
+ boolean releaseToDevicePool(Multimap<DeviceId, LabelResource> release);
+
+ /**
+ * Releases unused labels to the global resource pool.
+ *
+ * @param release release the collection of releasing labels
+ * @return success or fail
+ */
+ boolean releaseToGlobalPool(Set<LabelResourceId> release);
+
+ /**
+ * Judges if the pool of a specific device id is full.
+ *
+ * @param deviceId device identifier
+ * @return yes or no
+ */
+ boolean isDevicePoolFull(DeviceId deviceId);
+
+ /**
+ * Judges if the global resource pool is full.
+ *
+ * @return yes or no
+ */
+ boolean isGlobalPoolFull();
+
+ /**
+ * Returns the unused label number of a label resource pool by a specific device
+ * id.
+ *
+ * @param deviceId device identifier
+ * @return number of unused labels
+ */
+ long getFreeNumOfDevicePool(DeviceId deviceId);
+
+ /**
+ * Returns the unused number of a global label resource pool.
+ *
+ * @return number of unused labels
+ */
+ long getFreeNumOfGlobalPool();
+
+ /**
+ * Returns the label resource pool by a specific device id.
+ *
+ * @param deviceId device identifier
+ * @return the device label resource pool
+ */
+ LabelResourcePool getDeviceLabelResourcePool(DeviceId deviceId);
+
+ /**
+ * Returns the global label resource pool.
+ *
+ * @return the global label resource pool
+ */
+ LabelResourcePool getGlobalLabelResourcePool();
+}
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/DefaultLabelResourceTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/DefaultLabelResourceTest.java
new file mode 100644
index 0000000..5d7c02f
--- /dev/null
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/DefaultLabelResourceTest.java
@@ -0,0 +1,31 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.junit.Test;
+import org.onosproject.event.AbstractEventTest;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Tests of default label resource.
+ */
+public class DefaultLabelResourceTest extends AbstractEventTest {
+
+ @Test
+ public void testEquality() {
+ String deviceId1 = "of:001";
+ String deviceId2 = "of:002";
+ long labelResourceId1 = 100;
+ long labelResourceId2 = 200;
+ DefaultLabelResource h1 = new DefaultLabelResource(deviceId1,
+ labelResourceId1);
+ DefaultLabelResource h2 = new DefaultLabelResource(deviceId1,
+ labelResourceId1);
+ DefaultLabelResource h3 = new DefaultLabelResource(deviceId2,
+ labelResourceId2);
+ DefaultLabelResource h4 = new DefaultLabelResource(deviceId2,
+ labelResourceId2);
+
+ new EqualsTester().addEqualityGroup(h1, h2).addEqualityGroup(h3, h4)
+ .testEquals();
+ }
+}
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/LabelResourcePoolTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/LabelResourcePoolTest.java
new file mode 100644
index 0000000..8783508
--- /dev/null
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/LabelResourcePoolTest.java
@@ -0,0 +1,23 @@
+package org.onosproject.incubator.net.resource.label;
+
+import org.junit.Test;
+import org.onosproject.event.AbstractEventTest;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Tests of the label resource pool.
+ */
+public class LabelResourcePoolTest extends AbstractEventTest {
+
+ @Test
+ public void testEquality() {
+ LabelResourcePool h1 = new LabelResourcePool("of:001", 0, 100);
+ LabelResourcePool h2 = new LabelResourcePool("of:001", 0, 100);
+ LabelResourcePool h3 = new LabelResourcePool("of:002", 0, 100);
+ LabelResourcePool h4 = new LabelResourcePool("of:002", 0, 100);
+ new EqualsTester().addEqualityGroup(h1, h2).addEqualityGroup(h3, h4)
+ .testEquals();
+ }
+
+}
diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/LabelResourceRequestTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/LabelResourceRequestTest.java
new file mode 100644
index 0000000..1b08f7c
--- /dev/null
+++ b/incubator/api/src/test/java/org/onosproject/incubator/net/resource/label/LabelResourceRequestTest.java
@@ -0,0 +1,44 @@
+package org.onosproject.incubator.net.resource.label;
+
+import java.util.Collections;
+
+import org.junit.Test;
+import org.onosproject.event.AbstractEventTest;
+import org.onosproject.net.DeviceId;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Tests of the label resource request.
+ */
+public class LabelResourceRequestTest extends AbstractEventTest {
+
+ @Test
+ public void testEquality() {
+ DeviceId deviceId1 = DeviceId.deviceId("of:0001");
+ DeviceId deviceId2 = DeviceId.deviceId("of:0002");
+ long apply = 2;
+ ImmutableSet<LabelResource> releaseCollection = ImmutableSet
+ .copyOf(Collections.emptySet());
+ LabelResourceRequest h1 = new LabelResourceRequest(
+ deviceId1,
+ LabelResourceRequest.Type.APPLY,
+ apply, null);
+ LabelResourceRequest h2 = new LabelResourceRequest(
+ deviceId1,
+ LabelResourceRequest.Type.APPLY,
+ apply, null);
+ LabelResourceRequest h3 = new LabelResourceRequest(
+ deviceId2,
+ LabelResourceRequest.Type.RELEASE,
+ 0, releaseCollection);
+ LabelResourceRequest h4 = new LabelResourceRequest(
+ deviceId2,
+ LabelResourceRequest.Type.RELEASE,
+ 0, releaseCollection);
+
+ new EqualsTester().addEqualityGroup(h1, h2).addEqualityGroup(h3, h4)
+ .testEquals();
+ }
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java
new file mode 100644
index 0000000..94daed0
--- /dev/null
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java
@@ -0,0 +1,251 @@
+package org.onosproject.incubator.net.resource.label.impl;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.event.EventDeliveryService;
+import org.onosproject.event.ListenerRegistry;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceEvent.Type;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.provider.AbstractProviderRegistry;
+import org.onosproject.net.provider.AbstractProviderService;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceDelegate;
+import org.onosproject.incubator.net.resource.label.LabelResourceEvent;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceListener;
+import org.onosproject.incubator.net.resource.label.LabelResourcePool;
+import org.onosproject.incubator.net.resource.label.LabelResourceProvider;
+import org.onosproject.incubator.net.resource.label.LabelResourceProviderRegistry;
+import org.onosproject.incubator.net.resource.label.LabelResourceProviderService;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+import org.onosproject.incubator.net.resource.label.LabelResourceStore;
+import org.slf4j.Logger;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.collect.Multimap;
+
+/**
+ * provides implementation of the label resource NB & SB APIs.
+ *
+ */
+@Component(immediate = true)
+@Service
+public class LabelResourceManager
+ extends
+ AbstractProviderRegistry<LabelResourceProvider, LabelResourceProviderService>
+ implements LabelResourceService, LabelResourceAdminService,
+ LabelResourceProviderRegistry {
+ private final Logger log = getLogger(getClass());
+ private final LabelResourceDelegate delegate = new InternalLabelResourceDelegate();
+
+ private final ListenerRegistry<LabelResourceEvent, LabelResourceListener> listenerRegistry
+ = new ListenerRegistry<>();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LabelResourceStore store;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected EventDeliveryService eventDispatcher;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ private DeviceListener deviceListener = new InternalDeviceListener();
+
+ @Activate
+ public void activate() {
+ store.setDelegate(delegate);
+ eventDispatcher.addSink(LabelResourceEvent.class, listenerRegistry);
+ deviceService.addListener(deviceListener);
+ log.info("Started");
+
+ }
+
+ @Deactivate
+ public void deactivate() {
+ deviceService.removeListener(deviceListener);
+ store.unsetDelegate(delegate);
+ eventDispatcher.removeSink(LabelResourceEvent.class);
+ log.info("Stopped");
+ }
+
+ @Override
+ public boolean createDevicePool(DeviceId deviceId,
+ LabelResourceId beginLabel,
+ LabelResourceId endLabel) {
+ checkNotNull(deviceId, "deviceId is not null");
+ checkNotNull(beginLabel, "beginLabel is not null");
+ checkNotNull(endLabel, "beginLabel is not null");
+ checkArgument(beginLabel.labelId() < 0 || endLabel.labelId() < 0,
+ "The value of beginLabel and the value of endLabel must be both positive number.");
+ checkArgument(beginLabel.labelId() > endLabel.labelId(),
+ "The value of endLabel must be greater than the value of endLabel.");
+ return store.createDevicePool(deviceId, beginLabel, endLabel);
+ }
+
+ @Override
+ public boolean createGlobalPool(LabelResourceId beginLabel,
+ LabelResourceId endLabel) {
+ checkNotNull(beginLabel, "beginLabel is not null");
+ checkNotNull(endLabel, "beginLabel is not null");
+ checkArgument(beginLabel.labelId() < 0 || endLabel.labelId() < 0,
+ "The value of beginLabel and the value of endLabel must be both positive number.");
+ checkArgument(beginLabel.labelId() > endLabel.labelId(),
+ "The value of endLabel must be greater than the value of endLabel.");
+ return store.createGlobalPool(beginLabel, endLabel);
+ }
+
+ @Override
+ public boolean destroyDevicePool(DeviceId deviceId) {
+ checkNotNull(deviceId, "deviceId is not null");
+ return store.destroyDevicePool(deviceId);
+ }
+
+ @Override
+ public boolean destroyGlobalPool() {
+ return store.destroyGlobalPool();
+ }
+
+ @Override
+ public Collection<LabelResource> applyFromDevicePool(DeviceId deviceId,
+ long applyNum) {
+ checkNotNull(deviceId, "deviceId is not null");
+ checkNotNull(applyNum, "applyNum is not null");
+ return store.applyFromDevicePool(deviceId, applyNum);
+ }
+
+ @Override
+ public Collection<LabelResource> applyFromGlobalPool(long applyNum) {
+ checkNotNull(applyNum, "applyNum is not null");
+ return store.applyFromGlobalPool(applyNum);
+ }
+
+ @Override
+ public boolean releaseToDevicePool(Multimap<DeviceId, LabelResource> release) {
+ checkNotNull(release, "release is not null");
+ return store.releaseToDevicePool(release);
+ }
+
+ @Override
+ public boolean releaseToGlobalPool(Set<LabelResourceId> release) {
+ checkNotNull(release, "release is not null");
+ return store.releaseToGlobalPool(release);
+ }
+
+ @Override
+ public boolean isDevicePoolFull(DeviceId deviceId) {
+ checkNotNull(deviceId, "deviceId is not null");
+ return store.isDevicePoolFull(deviceId);
+ }
+
+ @Override
+ public boolean isGlobalPoolFull() {
+ return store.isGlobalPoolFull();
+ }
+
+ @Override
+ public long getFreeNumOfDevicePool(DeviceId deviceId) {
+ checkNotNull(deviceId, "deviceId is not null");
+ return store.getFreeNumOfDevicePool(deviceId);
+ }
+
+ @Override
+ public long getFreeNumOfGlobalPool() {
+ return store.getFreeNumOfGlobalPool();
+ }
+
+ @Override
+ public LabelResourcePool getDeviceLabelResourcePool(DeviceId deviceId) {
+ checkNotNull(deviceId, "deviceId is not null");
+ return store.getDeviceLabelResourcePool(deviceId);
+ }
+
+ @Override
+ public LabelResourcePool getGlobalLabelResourcePool() {
+ return store.getGlobalLabelResourcePool();
+ }
+
+ @Override
+ public void addListener(LabelResourceListener listener) {
+ listenerRegistry.addListener(listener);
+ }
+
+ @Override
+ public void removeListener(LabelResourceListener listener) {
+ listenerRegistry.removeListener(listener);
+
+ }
+
+ private void post(LabelResourceEvent event) {
+ if (event != null) {
+ eventDispatcher.post(event);
+ }
+ }
+
+ private class InternalLabelResourceDelegate
+ implements LabelResourceDelegate {
+
+ @Override
+ public void notify(LabelResourceEvent event) {
+ post(event);
+ }
+
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ if (Type.DEVICE_REMOVED.equals(event.type())) {
+ destroyDevicePool(device.id());
+ }
+ }
+ }
+
+ private class InternalLabelResourceProviderService
+ extends AbstractProviderService<LabelResourceProvider>
+ implements LabelResourceProviderService {
+
+ protected InternalLabelResourceProviderService(LabelResourceProvider provider) {
+ super(provider);
+ }
+
+ @Override
+ public void deviceLabelResourcePoolDetected(DeviceId deviceId,
+ LabelResourceId beginLabel,
+ LabelResourceId endLabel) {
+ checkNotNull(deviceId, "deviceId is not null");
+ checkNotNull(beginLabel, "beginLabel is not null");
+ checkNotNull(endLabel, "endLabel is not null");
+ createDevicePool(deviceId, beginLabel, endLabel);
+ }
+
+ @Override
+ public void deviceLabelResourcePoolDestroyed(DeviceId deviceId) {
+ checkNotNull(deviceId, "deviceId is not null");
+ destroyDevicePool(deviceId);
+ }
+
+ }
+
+ @Override
+ protected LabelResourceProviderService createProviderService(LabelResourceProvider provider) {
+ return new InternalLabelResourceProviderService(provider);
+ }
+}
diff --git a/incubator/pom.xml b/incubator/pom.xml
index 0eb6e89..ca8cd7e 100644
--- a/incubator/pom.xml
+++ b/incubator/pom.xml
@@ -42,6 +42,13 @@
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/resource/impl/DistributedLabelResourceStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/resource/impl/DistributedLabelResourceStore.java
new file mode 100644
index 0000000..09a558d
--- /dev/null
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/resource/impl/DistributedLabelResourceStore.java
@@ -0,0 +1,578 @@
+package org.onosproject.incubator.store.resource.impl;
+
+import static org.onlab.util.Tools.groupedThreads;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceDelegate;
+import org.onosproject.incubator.net.resource.label.LabelResourceEvent;
+import org.onosproject.incubator.net.resource.label.LabelResourceEvent.Type;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourcePool;
+import org.onosproject.incubator.net.resource.label.LabelResourceRequest;
+import org.onosproject.incubator.net.resource.label.LabelResourceStore;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
+import org.onosproject.store.cluster.messaging.ClusterMessage;
+import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
+import org.onosproject.store.flow.ReplicaInfo;
+import org.onosproject.store.flow.ReplicaInfoService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.serializers.KryoSerializer;
+import org.onosproject.store.serializers.custom.DistributedStoreSerializers;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+
+/**
+ * Manages label resources using copycat.
+ */
+@Component(immediate = true, enabled = true)
+@Service
+public class DistributedLabelResourceStore
+ extends AbstractStore<LabelResourceEvent, LabelResourceDelegate>
+ implements LabelResourceStore {
+ private final Logger log = getLogger(getClass());
+
+ private static final String POOL_MAP_NAME = "labelresourcepool";
+
+ private static final String GLOBAL_RESOURCE_POOL_DEVICE_ID = "global_resource_pool_device_id";
+ // primary data:
+ // read/write needs to be locked
+ private final ReentrantReadWriteLock resourcePoolLock = new ReentrantReadWriteLock();
+
+ private ConsistentMap<DeviceId, LabelResourcePool> resourcePool = null;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ReplicaInfoService replicaInfoManager;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterCommunicationService clusterCommunicator;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterService clusterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ private ExecutorService messageHandlingExecutor;
+ private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 8;
+ private static final long PEER_REQUEST_TIMEOUT_MS = 5000;
+
+ protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
+ @Override
+ protected void setupKryoPool() {
+ serializerPool = KryoNamespace.newBuilder()
+ .register(DistributedStoreSerializers.STORE_COMMON)
+ .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
+ .register(LabelResourceEvent.class)
+ .register(LabelResourcePool.class).register(DeviceId.class)
+ .register(LabelResourceRequest.class)
+ .register(LabelResourceRequest.Type.class)
+ .register(LabelResourceEvent.Type.class)
+ .register(DefaultLabelResource.class)
+ .register(LabelResourceId.class).build();
+ }
+ };
+
+ @Activate
+ public void activate() {
+
+ resourcePool = storageService
+ .<DeviceId, LabelResourcePool>consistentMapBuilder()
+ .withName(POOL_MAP_NAME).withSerializer(new Serializer() {
+ KryoNamespace kryo = new KryoNamespace.Builder()
+ .register(KryoNamespaces.API).build();
+
+ @Override
+ public <T> byte[] encode(T object) {
+ return kryo.serialize(object);
+ }
+
+ @Override
+ public <T> T decode(byte[] bytes) {
+ return kryo.deserialize(bytes);
+ }
+ }).withPartitionsDisabled().build();
+ messageHandlingExecutor = Executors
+ .newFixedThreadPool(MESSAGE_HANDLER_THREAD_POOL_SIZE,
+ groupedThreads("onos/store/flow",
+ "message-handlers"));
+ clusterCommunicator
+ .addSubscriber(LabelResourceMessageSubjects.LABEL_POOL_CREATED,
+ new ClusterMessageHandler() {
+
+ @Override
+ public void handle(ClusterMessage message) {
+ LabelResourcePool operation = SERIALIZER
+ .decode(message.payload());
+ log.trace("received get flow entry request for {}",
+ operation);
+ boolean b = internalCreate(operation);
+ message.respond(SERIALIZER.encode(b));
+ }
+ }, messageHandlingExecutor);
+ clusterCommunicator
+ .addSubscriber(LabelResourceMessageSubjects.LABEL_POOL_DESTROYED,
+ new ClusterMessageHandler() {
+
+ @Override
+ public void handle(ClusterMessage message) {
+ DeviceId deviceId = SERIALIZER
+ .decode(message.payload());
+ log.trace("received get flow entry request for {}",
+ deviceId);
+ boolean b = internalDestroy(deviceId);
+ message.respond(SERIALIZER.encode(b));
+ }
+ }, messageHandlingExecutor);
+ clusterCommunicator
+ .addSubscriber(LabelResourceMessageSubjects.LABEL_POOL_APPLY,
+ new ClusterMessageHandler() {
+
+ @Override
+ public void handle(ClusterMessage message) {
+ LabelResourceRequest request = SERIALIZER
+ .decode(message.payload());
+ log.trace("received get flow entry request for {}",
+ request);
+ final Collection<LabelResource> resource = internalApply(request);
+ message.respond(SERIALIZER
+ .encode(resource));
+ }
+ }, messageHandlingExecutor);
+ clusterCommunicator
+ .addSubscriber(LabelResourceMessageSubjects.LABEL_POOL_RELEASE,
+ new ClusterMessageHandler() {
+
+ @Override
+ public void handle(ClusterMessage message) {
+ LabelResourceRequest request = SERIALIZER
+ .decode(message.payload());
+ log.trace("received get flow entry request for {}",
+ request);
+ final boolean isSuccess = internalRelease(request);
+ message.respond(SERIALIZER
+ .encode(isSuccess));
+ }
+ }, messageHandlingExecutor);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ clusterCommunicator
+ .removeSubscriber(LabelResourceMessageSubjects.LABEL_POOL_CREATED);
+ clusterCommunicator
+ .removeSubscriber(LabelResourceMessageSubjects.LABEL_POOL_APPLY);
+ clusterCommunicator
+ .removeSubscriber(LabelResourceMessageSubjects.LABEL_POOL_DESTROYED);
+ clusterCommunicator
+ .removeSubscriber(LabelResourceMessageSubjects.LABEL_POOL_RELEASE);
+ messageHandlingExecutor.shutdown();
+ log.info("Stopped");
+ }
+
+ @Override
+ public boolean createDevicePool(DeviceId deviceId,
+ LabelResourceId beginLabel,
+ LabelResourceId endLabel) {
+ LabelResourcePool pool = new LabelResourcePool(deviceId.toString(),
+ beginLabel.labelId(),
+ endLabel.labelId());
+ return this.create(pool);
+ }
+
+ @Override
+ public boolean createGlobalPool(LabelResourceId beginLabel,
+ LabelResourceId endLabel) {
+ LabelResourcePool pool = new LabelResourcePool(
+ GLOBAL_RESOURCE_POOL_DEVICE_ID,
+ beginLabel.labelId(),
+ endLabel.labelId());
+ return this.internalCreate(pool);
+ }
+
+ private boolean create(LabelResourcePool pool) {
+ Device device = (Device) deviceService.getDevice(pool.deviceId());
+ if (device == null) {
+ return false;
+ }
+
+ ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(pool
+ .deviceId());
+
+ if (!replicaInfo.master().isPresent()) {
+ log.warn("Failed to getFlowEntries: No master for {}", pool);
+ return false;
+ }
+
+ if (replicaInfo.master().get()
+ .equals(clusterService.getLocalNode().id())) {
+ return internalCreate(pool);
+ }
+
+ log.trace("Forwarding getFlowEntries to {}, which is the primary (master) for device {}",
+ replicaInfo.master().orNull(), pool.deviceId());
+
+ return complete(clusterCommunicator
+ .sendAndReceive(pool,
+ LabelResourceMessageSubjects.LABEL_POOL_CREATED,
+ SERIALIZER::encode, SERIALIZER::decode,
+ replicaInfo.master().get()));
+ }
+
+ private boolean internalCreate(LabelResourcePool pool) {
+ resourcePoolLock.writeLock().lock();
+ LabelResourcePool poolOld = resourcePool.get(pool.deviceId()).value();
+ if (poolOld == null) {
+ resourcePool.put(pool.deviceId(), pool);
+ resourcePoolLock.writeLock().unlock();
+ LabelResourceEvent event = new LabelResourceEvent(
+ Type.POOL_CREATED,
+ pool);
+ notifyDelegate(event);
+ return true;
+ }
+ resourcePoolLock.writeLock().unlock();
+ return false;
+ }
+
+ @Override
+ public boolean destroyDevicePool(DeviceId deviceId) {
+ Device device = (Device) deviceService.getDevice(deviceId);
+ if (device == null) {
+ return false;
+ }
+ ReplicaInfo replicaInfo = replicaInfoManager
+ .getReplicaInfoFor(deviceId);
+
+ if (!replicaInfo.master().isPresent()) {
+ log.warn("Failed to getFlowEntries: No master for {}", deviceId);
+ return false;
+ }
+
+ if (replicaInfo.master().get()
+ .equals(clusterService.getLocalNode().id())) {
+ return internalDestroy(deviceId);
+ }
+
+ log.trace("Forwarding getFlowEntries to {}, which is the primary (master) for device {}",
+ replicaInfo.master().orNull(), deviceId);
+
+ return complete(clusterCommunicator
+ .sendAndReceive(deviceId,
+ LabelResourceMessageSubjects.LABEL_POOL_DESTROYED,
+ SERIALIZER::encode, SERIALIZER::decode,
+ replicaInfo.master().get()));
+ }
+
+ private boolean internalDestroy(DeviceId deviceId) {
+ LabelResourcePool poolOld = resourcePool.get(deviceId).value();
+ if (poolOld != null) {
+ resourcePool.remove(deviceId);
+ LabelResourceEvent event = new LabelResourceEvent(
+ Type.POOL_CREATED,
+ poolOld);
+ notifyDelegate(event);
+ }
+ log.info("success to destroy the label resource pool of device id {}",
+ deviceId);
+ return true;
+ }
+
+ @Override
+ public Collection<LabelResource> applyFromDevicePool(DeviceId deviceId,
+ long applyNum) {
+ Device device = (Device) deviceService.getDevice(deviceId);
+ if (device == null) {
+ return Collections.emptyList();
+ }
+ LabelResourceRequest request = new LabelResourceRequest(
+ deviceId,
+ LabelResourceRequest.Type.APPLY,
+ applyNum, null);
+ ReplicaInfo replicaInfo = replicaInfoManager
+ .getReplicaInfoFor(deviceId);
+
+ if (!replicaInfo.master().isPresent()) {
+ log.warn("Failed to getFlowEntries: No master for {}", deviceId);
+ return Collections.emptyList();
+ }
+
+ if (replicaInfo.master().get()
+ .equals(clusterService.getLocalNode().id())) {
+ return internalApply(request);
+ }
+
+ log.trace("Forwarding getFlowEntries to {}, which is the primary (master) for device {}",
+ replicaInfo.master().orNull(), deviceId);
+
+ return complete(clusterCommunicator
+ .sendAndReceive(request,
+ LabelResourceMessageSubjects.LABEL_POOL_APPLY,
+ SERIALIZER::encode, SERIALIZER::decode,
+ replicaInfo.master().get()));
+ }
+
+ private Collection<LabelResource> internalApply(LabelResourceRequest request) {
+ resourcePoolLock.writeLock().lock();
+ DeviceId deviceId = request.deviceId();
+ long applyNum = request.applyNum();
+ LabelResourcePool pool = resourcePool.get(deviceId).value();
+ Collection<LabelResource> result = new HashSet<LabelResource>();
+ long freeNum = this.getFreeNumOfDevicePool(deviceId);
+ if (applyNum > freeNum) {
+ log.info("the free number of the label resource pool of deviceId {} is not enough.");
+ resourcePoolLock.writeLock().unlock();
+ return Collections.emptyList();
+ }
+ Set<LabelResource> releaseLabels = new HashSet<LabelResource>(
+ pool.releaseLabelId());
+ long tmp = releaseLabels.size() > applyNum ? applyNum : releaseLabels
+ .size();
+ LabelResource resource = null;
+ for (int i = 0; i < tmp; i++) {
+ Iterator<LabelResource> it = releaseLabels.iterator();
+ if (it.hasNext()) {
+ resource = it.next();
+ releaseLabels.remove(resource);
+ }
+ result.add(resource);
+ }
+ for (long j = pool.currentUsedMaxLabelId().labelId(); j < pool
+ .currentUsedMaxLabelId().labelId() + applyNum - tmp; j++) {
+ resource = new DefaultLabelResource(deviceId,
+ LabelResourceId
+ .labelResourceId(j));
+ result.add(resource);
+ }
+ long beginLabel = pool.beginLabel().labelId();
+ long endLabel = pool.endLabel().labelId();
+ long totalNum = pool.totalNum();
+ long current = pool.currentUsedMaxLabelId().labelId() + applyNum - tmp;
+ long usedNum = pool.usedNum() + applyNum;
+ ImmutableSet<LabelResource> freeLabel = ImmutableSet
+ .copyOf(releaseLabels);
+ LabelResourcePool newPool = new LabelResourcePool(deviceId.toString(),
+ beginLabel, endLabel,
+ totalNum, usedNum,
+ current, freeLabel);
+ resourcePool.put(deviceId, newPool);
+ log.info("success to apply label resource");
+ resourcePoolLock.writeLock().unlock();
+ return result;
+ }
+
+ @Override
+ public boolean releaseToDevicePool(Multimap<DeviceId, LabelResource> release) {
+ Map<DeviceId, Collection<LabelResource>> maps = release.asMap();
+ Set<DeviceId> deviceIdSet = maps.keySet();
+ LabelResourceRequest request = null;
+ for (Iterator<DeviceId> it = deviceIdSet.iterator(); it.hasNext();) {
+ DeviceId deviceId = (DeviceId) it.next();
+ Device device = (Device) deviceService.getDevice(deviceId);
+ if (device == null) {
+ continue;
+ }
+ ImmutableSet<LabelResource> collection = ImmutableSet.copyOf(maps
+ .get(deviceId));
+ request = new LabelResourceRequest(
+ deviceId,
+ LabelResourceRequest.Type.RELEASE,
+ 0, collection);
+ ReplicaInfo replicaInfo = replicaInfoManager
+ .getReplicaInfoFor(deviceId);
+
+ if (!replicaInfo.master().isPresent()) {
+ log.warn("Failed to getFlowEntries: No master for {}", deviceId);
+ return false;
+ }
+
+ if (replicaInfo.master().get()
+ .equals(clusterService.getLocalNode().id())) {
+ return internalRelease(request);
+ }
+
+ log.trace("Forwarding getFlowEntries to {}, which is the primary (master) for device {}",
+ replicaInfo.master().orNull(), deviceId);
+
+ return complete(clusterCommunicator
+ .sendAndReceive(request,
+ LabelResourceMessageSubjects.LABEL_POOL_RELEASE,
+ SERIALIZER::encode, SERIALIZER::decode,
+ replicaInfo.master().get()));
+ }
+ return false;
+ }
+
+ private boolean internalRelease(LabelResourceRequest request) {
+ resourcePoolLock.writeLock().lock();
+ DeviceId deviceId = request.deviceId();
+ Collection<LabelResource> release = request.releaseCollection();
+ LabelResourcePool pool = resourcePool.get(deviceId).value();
+ if (pool == null) {
+ resourcePoolLock.writeLock().unlock();
+ log.info("the label resource pool of device id {} does not exist");
+ return false;
+ }
+ Set<LabelResource> storeSet = new HashSet<LabelResource>(
+ pool.releaseLabelId());
+ LabelResource labelResource = null;
+ long realReleasedNum = 0;
+ for (Iterator<LabelResource> it = release.iterator(); it.hasNext();) {
+ labelResource = it.next();
+ if (labelResource.labelResourceId().labelId() < pool.beginLabel()
+ .labelId()
+ || labelResource.labelResourceId().labelId() > pool
+ .endLabel().labelId()) {
+ continue;
+ }
+ if (pool.currentUsedMaxLabelId().labelId() > labelResource
+ .labelResourceId().labelId()
+ || !storeSet.contains(labelResource)) {
+ storeSet.add(labelResource);
+ realReleasedNum++;
+ }
+ }
+ long beginNum = pool.beginLabel().labelId();
+ long endNum = pool.endLabel().labelId();
+ long totalNum = pool.totalNum();
+ long usedNum = pool.usedNum() - realReleasedNum;
+ long current = pool.currentUsedMaxLabelId().labelId();
+ ImmutableSet<LabelResource> s = ImmutableSet.copyOf(storeSet);
+ LabelResourcePool newPool = new LabelResourcePool(deviceId.toString(),
+ beginNum, endNum,
+ totalNum, usedNum,
+ current, s);
+ resourcePool.put(deviceId, newPool);
+ log.info("success to release label resource");
+ resourcePoolLock.writeLock().unlock();
+ return true;
+ }
+
+ @Override
+ public boolean isDevicePoolFull(DeviceId deviceId) {
+ LabelResourcePool pool = resourcePool.get(deviceId).value();
+ if (pool == null) {
+ return true;
+ }
+ return pool.currentUsedMaxLabelId() == pool.endLabel()
+ && pool.releaseLabelId().size() == 0 ? true : false;
+ }
+
+ @Override
+ public long getFreeNumOfDevicePool(DeviceId deviceId) {
+ LabelResourcePool pool = resourcePool.get(deviceId).value();
+ if (pool == null) {
+ return 0;
+ }
+ return pool.endLabel().labelId()
+ - pool.currentUsedMaxLabelId().labelId()
+ + pool.releaseLabelId().size();
+ }
+
+ @Override
+ public LabelResourcePool getDeviceLabelResourcePool(DeviceId deviceId) {
+ return resourcePool.get(deviceId).value();
+ }
+
+ @Override
+ public boolean destroyGlobalPool() {
+ return this.internalDestroy(DeviceId
+ .deviceId(GLOBAL_RESOURCE_POOL_DEVICE_ID));
+ }
+
+ @Override
+ public Collection<LabelResource> applyFromGlobalPool(long applyNum) {
+ LabelResourceRequest request = new LabelResourceRequest(
+ DeviceId.deviceId(GLOBAL_RESOURCE_POOL_DEVICE_ID),
+ LabelResourceRequest.Type.APPLY,
+ applyNum, null);
+ return this.internalApply(request);
+ }
+
+ @Override
+ public boolean releaseToGlobalPool(Set<LabelResourceId> release) {
+ Set<LabelResource> set = new HashSet<LabelResource>();
+ DefaultLabelResource resource = null;
+ for (LabelResourceId labelResource : release) {
+ resource = new DefaultLabelResource(
+ DeviceId.deviceId(GLOBAL_RESOURCE_POOL_DEVICE_ID),
+ labelResource);
+ set.add(resource);
+ }
+ LabelResourceRequest request = new LabelResourceRequest(
+ DeviceId.deviceId(GLOBAL_RESOURCE_POOL_DEVICE_ID),
+ LabelResourceRequest.Type.APPLY,
+ 0,
+ ImmutableSet
+ .copyOf(set));
+ return this.internalRelease(request);
+ }
+
+ @Override
+ public boolean isGlobalPoolFull() {
+ return this.isDevicePoolFull(DeviceId
+ .deviceId(GLOBAL_RESOURCE_POOL_DEVICE_ID));
+ }
+
+ @Override
+ public long getFreeNumOfGlobalPool() {
+ return this.getFreeNumOfDevicePool(DeviceId
+ .deviceId(GLOBAL_RESOURCE_POOL_DEVICE_ID));
+ }
+
+ @Override
+ public LabelResourcePool getGlobalLabelResourcePool() {
+ return this.getDeviceLabelResourcePool(DeviceId
+ .deviceId(GLOBAL_RESOURCE_POOL_DEVICE_ID));
+ }
+
+ private <T> T complete(Future<T> future) {
+ try {
+ return future.get(PEER_REQUEST_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ log.error("Interrupted while waiting for operation to complete.", e);
+ return null;
+ } catch (TimeoutException | ExecutionException e) {
+ log.error("Failed remote operation", e);
+ return null;
+ }
+ }
+}
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/resource/impl/LabelResourceMessageSubjects.java b/incubator/store/src/main/java/org/onosproject/incubator/store/resource/impl/LabelResourceMessageSubjects.java
new file mode 100644
index 0000000..0a6f164
--- /dev/null
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/resource/impl/LabelResourceMessageSubjects.java
@@ -0,0 +1,17 @@
+package org.onosproject.incubator.store.resource.impl;
+
+import org.onosproject.store.cluster.messaging.MessageSubject;
+
+public final class LabelResourceMessageSubjects {
+
+ private LabelResourceMessageSubjects() {
+ }
+ public static final MessageSubject LABEL_POOL_CREATED
+ = new MessageSubject("label-resource-pool-created");
+ public static final MessageSubject LABEL_POOL_DESTROYED
+ = new MessageSubject("label-resource-pool-destroyed");
+ public static final MessageSubject LABEL_POOL_APPLY
+ = new MessageSubject("label-resource-pool-apply");
+ public static final MessageSubject LABEL_POOL_RELEASE
+ = new MessageSubject("label-resource-pool-release");
+}