Use ResourceId or DiscreteResourceId when specifying a resource
Change-Id: I4e29558ec649510c8d08bb5e5f8ed10c189252e5
diff --git a/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
index b5aa160..afac1bc 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
@@ -27,7 +27,9 @@
import org.onlab.util.GuavaCollectors;
import org.onlab.util.Tools;
import org.onosproject.net.newresource.ContinuousResource;
+import org.onosproject.net.newresource.ContinuousResourceId;
import org.onosproject.net.newresource.DiscreteResource;
+import org.onosproject.net.newresource.DiscreteResourceId;
import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourceConsumer;
import org.onosproject.net.newresource.ResourceEvent;
@@ -35,6 +37,7 @@
import org.onosproject.net.newresource.Resource;
import org.onosproject.net.newresource.ResourceStore;
import org.onosproject.net.newresource.ResourceStoreDelegate;
+import org.onosproject.net.newresource.Resources;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
@@ -86,60 +89,63 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService service;
- private ConsistentMap<DiscreteResource, ResourceConsumer> discreteConsumers;
- private ConsistentMap<ResourceId, ContinuousResourceAllocation> continuousConsumers;
- private ConsistentMap<DiscreteResource, Set<Resource>> childMap;
+ private ConsistentMap<DiscreteResourceId, ResourceConsumer> discreteConsumers;
+ private ConsistentMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumers;
+ private ConsistentMap<DiscreteResourceId, Set<Resource>> childMap;
@Activate
public void activate() {
- discreteConsumers = service.<DiscreteResource, ResourceConsumer>consistentMapBuilder()
+ discreteConsumers = service.<DiscreteResourceId, ResourceConsumer>consistentMapBuilder()
.withName(DISCRETE_CONSUMER_MAP)
.withSerializer(SERIALIZER)
.build();
- continuousConsumers = service.<ResourceId, ContinuousResourceAllocation>consistentMapBuilder()
+ continuousConsumers = service.<ContinuousResourceId, ContinuousResourceAllocation>consistentMapBuilder()
.withName(CONTINUOUS_CONSUMER_MAP)
.withSerializer(SERIALIZER)
.build();
- childMap = service.<DiscreteResource, Set<Resource>>consistentMapBuilder()
+ childMap = service.<DiscreteResourceId, Set<Resource>>consistentMapBuilder()
.withName(CHILD_MAP)
.withSerializer(SERIALIZER)
.build();
- Tools.retryable(() -> childMap.put(Resource.ROOT, new LinkedHashSet<>()),
+ Tools.retryable(() -> childMap.put(Resource.ROOT.id(), new LinkedHashSet<>()),
ConsistentMapException.class, MAX_RETRIES, RETRY_DELAY);
log.info("Started");
}
+ // Computational complexity: O(1) if the resource is discrete type.
+ // O(n) if the resource is continuous type where n is the number of the existing allocations for the resource
@Override
- public List<ResourceConsumer> getConsumers(Resource resource) {
- checkNotNull(resource);
- checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
+ public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
+ checkNotNull(id);
+ checkArgument(id instanceof DiscreteResourceId || id instanceof ContinuousResourceId);
- if (resource instanceof DiscreteResource) {
- return getConsumers((DiscreteResource) resource);
+ if (id instanceof DiscreteResourceId) {
+ return getResourceAllocations((DiscreteResourceId) id);
} else {
- return getConsumers((ContinuousResource) resource);
+ return getResourceAllocations((ContinuousResourceId) id);
}
}
- private List<ResourceConsumer> getConsumers(DiscreteResource resource) {
+ // computational complexity: O(1)
+ private List<ResourceAllocation> getResourceAllocations(DiscreteResourceId resource) {
Versioned<ResourceConsumer> consumer = discreteConsumers.get(resource);
if (consumer == null) {
return ImmutableList.of();
}
- return ImmutableList.of(consumer.value());
+ return ImmutableList.of(new ResourceAllocation(Resources.discrete(resource).resource(), consumer.value()));
}
- private List<ResourceConsumer> getConsumers(ContinuousResource resource) {
- Versioned<ContinuousResourceAllocation> allocations = continuousConsumers.get(resource.id());
+ // computational complexity: O(n) where n is the number of the existing allocations for the resource
+ private List<ResourceAllocation> getResourceAllocations(ContinuousResourceId resource) {
+ Versioned<ContinuousResourceAllocation> allocations = continuousConsumers.get(resource);
if (allocations == null) {
return ImmutableList.of();
}
return allocations.value().allocations().stream()
- .filter(x -> x.resource().equals(resource))
- .map(ResourceAllocation::consumer)
+ .filter(x -> x.resource().id().equals(resource))
.collect(GuavaCollectors.toImmutableList());
}
@@ -153,7 +159,7 @@
TransactionContext tx = service.transactionContextBuilder().build();
tx.begin();
- TransactionalMap<DiscreteResource, Set<Resource>> childTxMap =
+ TransactionalMap<DiscreteResourceId, Set<Resource>> childTxMap =
tx.getTransactionalMap(CHILD_MAP, SERIALIZER);
Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
@@ -166,7 +172,7 @@
return abortTransaction(tx);
}
- if (!appendValues(childTxMap, entry.getKey(), entry.getValue())) {
+ if (!appendValues(childTxMap, entry.getKey().id(), entry.getValue())) {
return abortTransaction(tx);
}
}
@@ -189,26 +195,27 @@
TransactionContext tx = service.transactionContextBuilder().build();
tx.begin();
- TransactionalMap<DiscreteResource, Set<Resource>> childTxMap =
+ TransactionalMap<DiscreteResourceId, Set<Resource>> childTxMap =
tx.getTransactionalMap(CHILD_MAP, SERIALIZER);
- TransactionalMap<DiscreteResource, ResourceConsumer> discreteConsumerTxMap =
+ TransactionalMap<DiscreteResourceId, ResourceConsumer> discreteConsumerTxMap =
tx.getTransactionalMap(DISCRETE_CONSUMER_MAP, SERIALIZER);
- TransactionalMap<ResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
+ TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
tx.getTransactionalMap(CONTINUOUS_CONSUMER_MAP, SERIALIZER);
// Extract Discrete instances from resources
- Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
+ Map<DiscreteResourceId, List<Resource>> resourceMap = resources.stream()
.filter(x -> x.parent().isPresent())
- .collect(Collectors.groupingBy(x -> x.parent().get()));
+ .collect(Collectors.groupingBy(x -> x.parent().get().id()));
// even if one of the resources is allocated to a consumer,
// all unregistrations are regarded as failure
- for (Map.Entry<DiscreteResource, List<Resource>> entry: resourceMap.entrySet()) {
+ for (Map.Entry<DiscreteResourceId, List<Resource>> entry: resourceMap.entrySet()) {
boolean allocated = entry.getValue().stream().anyMatch(x -> {
if (x instanceof DiscreteResource) {
- return discreteConsumerTxMap.get((DiscreteResource) x) != null;
+ return discreteConsumerTxMap.get(((DiscreteResource) x).id()) != null;
} else if (x instanceof ContinuousResource) {
- ContinuousResourceAllocation allocations = continuousConsumerTxMap.get(x.id());
+ ContinuousResourceAllocation allocations =
+ continuousConsumerTxMap.get(((ContinuousResource) x).id());
return allocations != null && !allocations.allocations().isEmpty();
} else {
return false;
@@ -247,11 +254,11 @@
TransactionContext tx = service.transactionContextBuilder().build();
tx.begin();
- TransactionalMap<DiscreteResource, Set<Resource>> childTxMap =
+ TransactionalMap<DiscreteResourceId, Set<Resource>> childTxMap =
tx.getTransactionalMap(CHILD_MAP, SERIALIZER);
- TransactionalMap<DiscreteResource, ResourceConsumer> discreteConsumerTxMap =
+ TransactionalMap<DiscreteResourceId, ResourceConsumer> discreteConsumerTxMap =
tx.getTransactionalMap(DISCRETE_CONSUMER_MAP, SERIALIZER);
- TransactionalMap<ResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
+ TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
tx.getTransactionalMap(CONTINUOUS_CONSUMER_MAP, SERIALIZER);
for (Resource resource: resources) {
@@ -260,7 +267,7 @@
return abortTransaction(tx);
}
- ResourceConsumer oldValue = discreteConsumerTxMap.put((DiscreteResource) resource, consumer);
+ ResourceConsumer oldValue = discreteConsumerTxMap.put(((DiscreteResource) resource).id(), consumer);
if (oldValue != null) {
return abortTransaction(tx);
}
@@ -295,9 +302,9 @@
TransactionContext tx = service.transactionContextBuilder().build();
tx.begin();
- TransactionalMap<DiscreteResource, ResourceConsumer> discreteConsumerTxMap =
+ TransactionalMap<DiscreteResourceId, ResourceConsumer> discreteConsumerTxMap =
tx.getTransactionalMap(DISCRETE_CONSUMER_MAP, SERIALIZER);
- TransactionalMap<ResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
+ TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> continuousConsumerTxMap =
tx.getTransactionalMap(CONTINUOUS_CONSUMER_MAP, SERIALIZER);
Iterator<Resource> resourceIte = resources.iterator();
Iterator<ResourceConsumer> consumerIte = consumers.iterator();
@@ -309,7 +316,7 @@
if (resource instanceof DiscreteResource) {
// if this single release fails (because the resource is allocated to another consumer,
// the whole release fails
- if (!discreteConsumerTxMap.remove((DiscreteResource) resource, consumer)) {
+ if (!discreteConsumerTxMap.remove(((DiscreteResource) resource).id(), consumer)) {
return abortTransaction(tx);
}
} else if (resource instanceof ContinuousResource) {
@@ -330,20 +337,23 @@
return tx.commit();
}
+ // computational complexity: O(1) if the resource is discrete type.
+ // O(n) if the resource is continuous type where n is the number of the children of
+ // the specified resource's parent
@Override
public boolean isAvailable(Resource resource) {
checkNotNull(resource);
checkArgument(resource instanceof DiscreteResource || resource instanceof ContinuousResource);
// check if it's registered or not.
- Versioned<Set<Resource>> v = childMap.get(resource.parent().get());
+ Versioned<Set<Resource>> v = childMap.get(resource.parent().get().id());
if (v == null || !v.value().contains(resource)) {
return false;
}
if (resource instanceof DiscreteResource) {
// check if already consumed
- return getConsumers((DiscreteResource) resource).isEmpty();
+ return getResourceAllocations(resource.id()).isEmpty();
} else {
ContinuousResource requested = (ContinuousResource) resource;
ContinuousResource registered = v.value().stream()
@@ -360,6 +370,7 @@
}
}
+ // computational complexity: O(n) where n is the number of existing allocations for the resource
private boolean isAvailable(ContinuousResource resource) {
Versioned<ContinuousResourceAllocation> allocation = continuousConsumers.get(resource.id());
if (allocation == null) {
@@ -370,6 +381,8 @@
return hasEnoughResource(allocation.value().original(), resource, allocation.value());
}
+ // computational complexity: O(n + m) where n is the number of entries in discreteConsumers
+ // and m is the number of allocations for all continuous resources
@Override
public Collection<Resource> getResources(ResourceConsumer consumer) {
checkNotNull(consumer);
@@ -378,7 +391,8 @@
// TODO: revisit for better backend data structure
Stream<DiscreteResource> discreteStream = discreteConsumers.entrySet().stream()
.filter(x -> x.getValue().value().equals(consumer))
- .map(Map.Entry::getKey);
+ .map(Map.Entry::getKey)
+ .map(x -> Resources.discrete(x).resource());
Stream<ContinuousResource> continuousStream = continuousConsumers.values().stream()
.flatMap(x -> x.value().allocations().stream()
@@ -389,15 +403,12 @@
return Stream.concat(discreteStream, continuousStream).collect(Collectors.toList());
}
+ // computational complexity: O(n)
@Override
- public Set<Resource> getChildResources(Resource parent) {
+ public Set<Resource> getChildResources(DiscreteResourceId parent) {
checkNotNull(parent);
- if (!(parent instanceof DiscreteResource)) {
- // only Discrete resource can have child resource
- return ImmutableSet.of();
- }
- Versioned<Set<Resource>> children = childMap.get((DiscreteResource) parent);
+ Versioned<Set<Resource>> children = childMap.get(parent);
if (children == null) {
return ImmutableSet.of();
}
@@ -405,13 +416,13 @@
return children.value();
}
+ // computational complexity: O(n) where n is the number of the children of the parent
@Override
- public <T> Collection<Resource> getAllocatedResources(Resource parent, Class<T> cls) {
+ public <T> Collection<Resource> getAllocatedResources(DiscreteResourceId parent, Class<T> cls) {
checkNotNull(parent);
checkNotNull(cls);
- checkArgument(parent instanceof DiscreteResource);
- Versioned<Set<Resource>> children = childMap.get((DiscreteResource) parent);
+ Versioned<Set<Resource>> children = childMap.get(parent);
if (children == null) {
return ImmutableList.of();
}
@@ -419,11 +430,11 @@
Stream<DiscreteResource> discrete = children.value().stream()
.filter(x -> x.last().getClass().equals(cls))
.filter(x -> x instanceof DiscreteResource)
- .map(x -> (DiscreteResource) x)
- .filter(discreteConsumers::containsKey);
+ .map(x -> ((DiscreteResource) x))
+ .filter(x -> discreteConsumers.containsKey(x.id()));
Stream<ContinuousResource> continuous = children.value().stream()
- .filter(x -> x.id().equals(parent.id().child(cls)))
+ .filter(x -> x.id().equals(parent.child(cls)))
.filter(x -> x instanceof ContinuousResource)
.map(x -> (ContinuousResource) x)
.filter(x -> continuousConsumers.containsKey(x.id()))
@@ -445,7 +456,8 @@
}
// Appends the specified ResourceAllocation to the existing values stored in the map
- private boolean appendValue(TransactionalMap<ResourceId, ContinuousResourceAllocation> map,
+ // computational complexity: O(n) where n is the number of the elements in the associated allocation
+ private boolean appendValue(TransactionalMap<ContinuousResourceId, ContinuousResourceAllocation> map,
ContinuousResource original, ResourceAllocation value) {
ContinuousResourceAllocation oldValue = map.putIfAbsent(original.id(),
new ContinuousResourceAllocation(original, ImmutableList.of(value)));
@@ -474,8 +486,9 @@
* @param values values to be appended
* @return true if the operation succeeds, false otherwise.
*/
- private boolean appendValues(TransactionalMap<DiscreteResource, Set<Resource>> map,
- DiscreteResource key, List<Resource> values) {
+ // computational complexity: O(n) where n is the number of the specified value
+ private boolean appendValues(TransactionalMap<DiscreteResourceId, Set<Resource>> map,
+ DiscreteResourceId key, List<Resource> values) {
Set<Resource> oldValues = map.putIfAbsent(key, new LinkedHashSet<>(values));
if (oldValues == null) {
return true;
@@ -500,8 +513,9 @@
* @param values values to be removed
* @return true if the operation succeeds, false otherwise
*/
- private boolean removeValues(TransactionalMap<DiscreteResource, Set<Resource>> map,
- DiscreteResource key, List<Resource> values) {
+ // computational complexity: O(n) where n is the number of the specified values
+ private boolean removeValues(TransactionalMap<DiscreteResourceId, Set<Resource>> map,
+ DiscreteResourceId key, List<Resource> values) {
Set<Resource> oldValues = map.putIfAbsent(key, new LinkedHashSet<>());
if (oldValues == null) {
log.trace("No-Op removing values. key {} did not exist", key);
@@ -528,14 +542,16 @@
* @return the resource which is regarded as the same as the specified resource
*/
// Naive implementation, which traverses all elements in the list
+ // computational complexity: O(n) where n is the number of elements
+ // in the associated set
private <T extends Resource> Optional<T> lookup(
- TransactionalMap<DiscreteResource, Set<Resource>> map, T resource) {
+ TransactionalMap<DiscreteResourceId, Set<Resource>> map, T resource) {
// if it is root, always returns itself
if (!resource.parent().isPresent()) {
return Optional.of(resource);
}
- Set<Resource> values = map.get(resource.parent().get());
+ Set<Resource> values = map.get(resource.parent().get().id());
if (values == null) {
return Optional.empty();
}
@@ -557,6 +573,7 @@
* @param allocation current allocation of the resource
* @return true if there is enough resource volume. Otherwise, false.
*/
+ // computational complexity: O(n) where n is the number of allocations
private boolean hasEnoughResource(ContinuousResource original,
ContinuousResource request,
ContinuousResourceAllocation allocation) {