HIGUCHI Yuta
Committed by Yuta HIGUCHI

Bugfix and cosmetic changes to resource subsystem

- Continuous resource was always considered not available
- Support querying for child resource against Continuous
   (result is no children)
- Resource equality to compare id and exact type

- Add missing information in Continuous resource toString()
- More concise String representation for ResourceId

- additional logging added during above bug investigation.

Change-Id: I58a95b95b91c246c3c5dbb136a1820f988c6fccd
......@@ -208,7 +208,11 @@ public abstract class Resource {
if (this == obj) {
return true;
}
if (!(obj instanceof Resource)) {
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final Resource that = (Resource) obj;
......@@ -259,25 +263,14 @@ public abstract class Resource {
@Override
public int hashCode() {
return Objects.hash(this.id(), this.value);
return super.hashCode();
}
// explicitly overriding to express that we intentionally ignore
// `value` in equality comparison
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Continuous)) {
return false;
}
if (!super.equals(obj)) {
return false;
}
final Continuous other = (Continuous) obj;
return Objects.equals(this.id(), other.id());
return super.equals(obj);
}
/**
......@@ -288,6 +281,14 @@ public abstract class Resource {
public double value() {
return value;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id())
.add("value", value)
.toString();
}
}
}
......
......@@ -16,7 +16,6 @@
package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
......@@ -95,8 +94,6 @@ public final class ResourceId {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("components", components)
.toString();
return components.toString();
}
}
......
......@@ -34,12 +34,14 @@ import org.onosproject.net.newresource.ResourceService;
import org.onosproject.net.newresource.Resource;
import org.onosproject.net.newresource.ResourceStore;
import org.onosproject.net.newresource.ResourceStoreDelegate;
import org.slf4j.Logger;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* An implementation of ResourceService.
......@@ -53,18 +55,24 @@ public final class ResourceManager extends AbstractListenerManager<ResourceEvent
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceStore store;
private final Logger log = getLogger(getClass());
private final ResourceStoreDelegate delegate = new InternalStoreDelegate();
@Activate
public void activate() {
store.setDelegate(delegate);
eventDispatcher.addSink(ResourceEvent.class, listenerRegistry);
log.info("Started");
}
@Deactivate
public void deactivate() {
store.unsetDelegate(delegate);
eventDispatcher.removeSink(ResourceEvent.class);
log.info("Stopped");
}
@Override
......
......@@ -143,6 +143,9 @@ public class ConsistentResourceStore extends AbstractStore<ResourceEvent, Resour
@Override
public boolean register(List<Resource> resources) {
checkNotNull(resources);
if (log.isTraceEnabled()) {
resources.forEach(r -> log.trace("registering {}", r));
}
TransactionContext tx = service.transactionContextBuilder().build();
tx.begin();
......@@ -324,17 +327,36 @@ public class ConsistentResourceStore extends AbstractStore<ResourceEvent, Resour
checkNotNull(resource);
checkArgument(resource instanceof Resource.Discrete || resource instanceof Resource.Continuous);
// check if it's registered or not.
Versioned<Set<Resource>> v = childMap.get(resource.parent().get());
if (v == null || !v.value().contains(resource)) {
return false;
}
if (resource instanceof Resource.Discrete) {
// check if already consumed
return getConsumer((Resource.Discrete) resource).isEmpty();
} else {
return isAvailable((Resource.Continuous) resource);
Resource.Continuous requested = (Resource.Continuous) resource;
Resource.Continuous registered = v.value().stream()
.filter(c -> c.equals(resource))
.findFirst()
.map(c -> (Resource.Continuous) c)
.get();
if (registered.value() < requested.value()) {
// Capacity < requested, can never satisfy
return false;
}
// check if there's enough left
return isAvailable(requested);
}
}
private boolean isAvailable(Resource.Continuous resource) {
Versioned<ContinuousResourceAllocation> allocation = continuousConsumers.get(resource.id());
if (allocation == null) {
return false;
// no allocation (=no consumer) full registered resources available
return true;
}
return hasEnoughResource(allocation.value().original(), resource, allocation.value());
......@@ -362,7 +384,10 @@ public class ConsistentResourceStore extends AbstractStore<ResourceEvent, Resour
@Override
public Collection<Resource> getChildResources(Resource parent) {
checkNotNull(parent);
checkArgument(parent instanceof Resource.Discrete);
if (!(parent instanceof Resource.Discrete)) {
// only Discrete resource can have child resource
return ImmutableList.of();
}
Versioned<Set<Resource>> children = childMap.get((Resource.Discrete) parent);
if (children == null) {
......