Sho SHIMIZU

Implement event notification of resource event

When a resource is registered or unregistered, a resource event is notified

Change-Id: I40e66761966ef2126366424a14bb3193fc850e5a
/*
* Copyright 2015 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.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import org.onosproject.event.AbstractEvent;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Describes an event related to a resource.
*/
@Beta
public final class ResourceEvent extends AbstractEvent<ResourceEvent.Type, ResourcePath> {
/**
* Type of resource events.
*/
@Beta
public enum Type {
/**
* Signifies that a new resource has been detected.
*/
RESOURCE_ADDED,
/**
* Signifies that a resource has been removed.
*/
RESOURCE_REMOVED
}
/**
* Create a resource event.
*
* @param type type of resource event
* @param subject subject of resource event
*/
public ResourceEvent(Type type, ResourcePath subject) {
super(checkNotNull(type), checkNotNull(subject));
}
}
/*
* Copyright 2015 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.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import org.onosproject.event.EventListener;
/**
* Entity capable of receiving resource related events.
*/
@Beta
public interface ResourceListener extends EventListener<ResourceEvent> {
}
......@@ -17,6 +17,7 @@ package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import org.onosproject.event.ListenerService;
import java.util.Arrays;
import java.util.Collection;
......@@ -29,7 +30,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Service for allocating/releasing resource(s) and retrieving allocation(s) and availability.
*/
@Beta
public interface ResourceService {
public interface ResourceService extends ListenerService<ResourceEvent, ResourceListener> {
/**
* Allocates the specified resource to the specified user.
*
......
......@@ -16,6 +16,7 @@
package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import org.onosproject.store.Store;
import java.util.Collection;
import java.util.List;
......@@ -25,7 +26,7 @@ import java.util.Optional;
* Service for storing resource and consumer information.
*/
@Beta
public interface ResourceStore {
public interface ResourceStore extends Store<ResourceEvent, ResourceStoreDelegate> {
/**
* Registers the resources in transactional way.
......
/*
* Copyright 2015 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.onosproject.net.newresource;
import org.onosproject.store.StoreDelegate;
/**
* Resource store delegate abstraction.
*/
public interface ResourceStoreDelegate extends StoreDelegate<ResourceEvent> {
}
......@@ -18,16 +18,22 @@ package org.onosproject.net.newresource.impl;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
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.AbstractListenerManager;
import org.onosproject.net.newresource.ResourceAdminService;
import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourceConsumer;
import org.onosproject.net.newresource.ResourceEvent;
import org.onosproject.net.newresource.ResourceListener;
import org.onosproject.net.newresource.ResourceService;
import org.onosproject.net.newresource.ResourcePath;
import org.onosproject.net.newresource.ResourceStore;
import org.onosproject.net.newresource.ResourceStoreDelegate;
import java.util.ArrayList;
import java.util.Collection;
......@@ -44,11 +50,26 @@ import static com.google.common.base.Preconditions.checkNotNull;
@Component(immediate = true)
@Service
@Beta
public final class ResourceManager implements ResourceService, ResourceAdminService {
public final class ResourceManager extends AbstractListenerManager<ResourceEvent, ResourceListener>
implements ResourceService, ResourceAdminService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceStore store;
private final ResourceStoreDelegate delegate = new InternalStoreDelegate();
@Activate
public void activate() {
store.setDelegate(delegate);
eventDispatcher.addSink(ResourceEvent.class, listenerRegistry);
}
@Deactivate
public void deactivate() {
store.unsetDelegate(delegate);
eventDispatcher.addSink(ResourceEvent.class, listenerRegistry);
}
@Override
public List<ResourceAllocation> allocate(ResourceConsumer consumer,
List<ResourcePath> resources) {
......@@ -161,4 +182,11 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ
List<ResourcePath> resources = Lists.transform(children, x -> ResourcePath.child(parent, x));
return store.unregister(resources);
}
private class InternalStoreDelegate implements ResourceStoreDelegate {
@Override
public void notify(ResourceEvent event) {
post(event);
}
}
}
......
......@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList;
import org.onlab.packet.MplsLabel;
import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourceConsumer;
import org.onosproject.net.newresource.ResourceListener;
import org.onosproject.net.newresource.ResourcePath;
import org.onosproject.net.newresource.ResourceService;
......@@ -97,4 +98,10 @@ class MockResourceService implements ResourceService {
public boolean isAvailable(ResourcePath resource) {
return true;
}
@Override
public void addListener(ResourceListener listener) {}
@Override
public void removeListener(ResourceListener listener) {}
}
......
......@@ -22,8 +22,11 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.net.newresource.ResourceConsumer;
import org.onosproject.net.newresource.ResourceEvent;
import org.onosproject.net.newresource.ResourcePath;
import org.onosproject.net.newresource.ResourceStore;
import org.onosproject.net.newresource.ResourceStoreDelegate;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.Serializer;
......@@ -47,6 +50,7 @@ import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.newresource.ResourceEvent.Type.*;
/**
* Implementation of ResourceStore using TransactionalMap.
......@@ -54,7 +58,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
@Component(immediate = true)
@Service
@Beta
public class ConsistentResourceStore implements ResourceStore {
public class ConsistentResourceStore extends AbstractStore<ResourceEvent, ResourceStoreDelegate>
implements ResourceStore {
private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class);
private static final String CONSUMER_MAP = "onos-resource-consumers";
......@@ -116,7 +121,15 @@ public class ConsistentResourceStore implements ResourceStore {
}
}
return tx.commit();
boolean success = tx.commit();
if (success) {
List<ResourceEvent> events = resources.stream()
.filter(x -> x.parent().isPresent())
.map(x -> new ResourceEvent(RESOURCE_ADDED, x))
.collect(Collectors.toList());
notifyDelegate(events);
}
return success;
}
@Override
......@@ -147,7 +160,15 @@ public class ConsistentResourceStore implements ResourceStore {
}
}
return tx.commit();
boolean success = tx.commit();
if (success) {
List<ResourceEvent> events = resources.stream()
.filter(x -> x.parent().isPresent())
.map(x -> new ResourceEvent(RESOURCE_REMOVED, x))
.collect(Collectors.toList());
notifyDelegate(events);
}
return success;
}
@Override
......