Sho SHIMIZU
Committed by Gerrit Code Review

ONOS-2692: Implement methods to unregister resources

Change-Id: Iae88207c5edecf6645aeff3c15875178b5266634
......@@ -48,4 +48,28 @@ public interface ResourceAdminService {
* succeeds when each resource is not registered or unallocated.
*/
<T> boolean registerResources(ResourcePath parent, List<T> children);
/**
* Unregister resources as the children of the parent resource path.
*
* @param parent parent resource path under which the resource are unregistered
* @param children resources to be unregistered as the children of the parent
* @param <T> type of resources
* @return true if unregistration is successfully done, false otherwise. Unregistration
* succeeds when each resource is not registered or unallocated.
*/
default <T> boolean unregisterResources(ResourcePath parent, T... children) {
return unregisterResources(parent, Arrays.asList(children));
}
/**
* Unregister resources as the children of the parent resource path.
*
* @param parent parent resource path under which the resource are unregistered
* @param children resources to be unregistered as the children of the parent
* @param <T> type of resources
* @return true if unregistration is successfully done, false otherwise. Unregistration
* succeeds when each resource is not registered or unallocated.
*/
<T> boolean unregisterResources(ResourcePath parent, List<T> children);
}
......
......@@ -25,6 +25,18 @@ public interface ResourceStore {
boolean register(ResourcePath parent, List<ResourcePath> children);
/**
* Unregisters the resources as children of the parent resource in transactional way.
* The state after completion of this method is all the resources are unregistered,
* or no resource is unregistered. The whole unregistration fails when any one of the
* resource can't be unregistered.
*
* @param parent resource which is the parent of the resource to be unregistered
* @param children resources to be unregistered
* @return true if the registration succeeds, false otherwise
*/
boolean unregister(ResourcePath parent, List<ResourcePath> children);
/**
* Allocates the specified resources to the specified consumer in transactional way.
* The state after completion of this method is all the resources are allocated to the consumer,
* or no resource is allocated to the consumer. The whole allocation fails when any one of
......
......@@ -130,4 +130,10 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ
List<ResourcePath> resources = Lists.transform(children, x -> ResourcePath.child(parent, x));
return store.register(parent, resources);
}
@Override
public <T> boolean unregisterResources(ResourcePath parent, List<T> children) {
List<ResourcePath> resources = Lists.transform(children, x -> ResourcePath.child(parent, x));
return store.unregister(parent, resources);
}
}
......
......@@ -121,6 +121,37 @@ public class ConsistentResourceStore implements ResourceStore {
}
@Override
public boolean unregister(ResourcePath resource, List<ResourcePath> children) {
checkNotNull(resource);
checkNotNull(children);
TransactionContext tx = service.transactionContextBuilder().build();
tx.begin();
try {
TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap =
tx.getTransactionalMap(CHILD_MAP, SERIALIZER);
TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap =
tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER);
// even if one of the resources is allocated to a consumer,
// all unregistrations are regarded as failure
if (children.stream().anyMatch(x -> consumerTxMap.get(x) != null)) {
return abortTransaction(tx);
}
if (!removeValues(childTxMap, resource, children)) {
return abortTransaction(tx);
}
return commitTransaction(tx);
} catch (TransactionException e) {
log.error("Exception thrown, abort the transaction", e);
return abortTransaction(tx);
}
}
@Override
public boolean allocate(List<ResourcePath> resources, ResourceConsumer consumer) {
checkNotNull(resources);
checkNotNull(consumer);
......@@ -260,6 +291,30 @@ public class ConsistentResourceStore implements ResourceStore {
}
/**
* Removes teh values from the existing values associated with the specified key.
*
* @param map map holding multiple values for a key
* @param key key specifying values
* @param values values to be removed
* @param <K> type of the key
* @param <V> type of the element of the list
* @return true if the operation succeeds, false otherwise
*/
private <K, V> boolean removeValues(TransactionalMap<K, List<V>> map, K key, List<V> values) {
List<V> oldValues = map.get(key);
List<V> newValues;
if (oldValues == null) {
newValues = new ArrayList<>();
} else {
LinkedHashSet<V> newSet = new LinkedHashSet<>(oldValues);
newSet.removeAll(values);
newValues = new ArrayList<>(newSet);
}
return map.replace(key, oldValues, newValues);
}
/**
* Checks if the specified resource is registered as a child of a resource in the map.
*
* @param map map storing parent - child relationship of resources
......