Merge "Add prefixes to type attribute in generated xml from netconf Add support for...
authorEd Warnicke <eaw@cisco.com>
Mon, 25 Nov 2013 09:42:51 +0000 (09:42 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 25 Nov 2013 09:42:51 +0000 (09:42 +0000)
15 files changed:
opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerFlowConfig.java
opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FlowConsumerImpl.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/GroupConsumerImpl.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/MeterConsumerImpl.java
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/TableFeaturesConsumerImpl.java [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiter.java
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java
opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java
opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java

index baa2c782538255b6da9dfff772d10406e9eabf47..9740a9259833c0ef9d60ad821eaea1e0ee723aef 100644 (file)
@@ -114,6 +114,17 @@ public class ContainerFlowConfig implements Serializable {
         //this.unidirectional = false;
     }
 
+    public ContainerFlowConfig(String name, String dlVlan, String srcIP, String dstIP, String proto, String srcPort,
+            String dstPort) {
+        this.name = name;
+        this.dlVlan = dlVlan;
+        this.nwSrc = srcIP;
+        this.nwDst = dstIP;
+        this.protocol = proto;
+        this.tpSrc = srcPort;
+        this.tpDst = dstPort;
+    }
+
 
     public ContainerFlowConfig(ContainerFlowConfig containerFlowConfig) {
         this.name = containerFlowConfig.name;
index c61b41c06542a24167fa863474b18198a7c32d3a..3ad0c61d4f66ffb8763354e65bc2d196d88929df 100644 (file)
@@ -62,6 +62,8 @@
   <logger name="org.opendaylight.controller.sal.implementation" level="INFO"/>
   <logger name="org.opendaylight.controller.sal.implementation.internal.Inventory" level="INFO"/>
   <logger name="org.opendaylight.controller.sal.implementation.internal.Topology" level="INFO"/>
+     <!-- zeromq router and zeromq routing table -->
+  <logger name="org.opendaylight.controller.sal.connector.remoterpc" level="INFO" />
   <!-- Functional Modules -->
   <logger name="org.opendaylight.controller.arphandler" level="INFO"/>
   <logger name="org.opendaylight.controller.hosttracker" level="INFO"/>
index 82db78e7b9b25f986cce56b38de5ebba2752ed83..2ffe0ecd87eee775b08f6e5b51c1e0febcb66baf 100644 (file)
@@ -71,7 +71,7 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
     private IContainer container;
     private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
     private static ConcurrentMap<Integer, Flow> staticFlows;
-    private static ConcurrentMap<Integer, Integer> staticFlowsOrdinal;
+    private static ConcurrentMap<Integer, Integer> staticFlowsOrdinal = new ConcurrentHashMap<Integer, Integer>();
     /*
      * Inactive flow list. This is for the global instance of FRM It will
      * contain all the flow entries which were installed on the global container
@@ -86,7 +86,8 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
     private boolean inContainerMode; // being used by global instance only
 
     public FlowConsumerImpl() {
-        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Flows.class).toInstance();
+        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Flows.class).child(Flow.class)
+                .toInstance();
         flowService = FRMConsumerImpl.getProviderSession().getRpcService(SalFlowService.class);
 
         if (null == flowService) {
@@ -499,14 +500,13 @@ public class FlowConsumerImpl implements IForwardingRulesManager {
         @Override
         public void onNodeErrorNotification(NodeErrorNotification notification) {
             // TODO Auto-generated method stub
-            
+
         }
 
         @Override
-        public void onNodeExperimenterErrorNotification(
-                NodeExperimenterErrorNotification notification) {
+        public void onNodeExperimenterErrorNotification(NodeExperimenterErrorNotification notification) {
             // TODO Auto-generated method stub
-            
+
         };
 
     }
index 85954910167730d4949f2422706a5d9579e81458..851e7d9b2685420b5093d8771770a64a3fe52250 100644 (file)
@@ -68,8 +68,8 @@ public class GroupConsumerImpl implements IForwardingRulesManager {
 
     public GroupConsumerImpl() {
 
-        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class)
-                .node(Group.class).toInstance();
+        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Groups.class).child(Group.class)
+                .toInstance();
         groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
 
         clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
index 7f7db3ba58ccb8d142c91a5b2c679f56213a70c6..bd0ceb3fea8011aaa575dea0e71e4cbb8a1032c9 100644 (file)
@@ -66,8 +66,8 @@ public class MeterConsumerImpl implements IForwardingRulesManager {
     private IContainer container;
 
     public MeterConsumerImpl() {
-        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Meters.class)
-                .node(Meter.class).toInstance();
+        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Meters.class).child(Meter.class)
+                .toInstance();
         meterService = FRMConsumerImpl.getProviderSession().getRpcService(SalMeterService.class);
         clusterMeterContainerService = FRMConsumerImpl.getClusterContainerService();
 
diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/TableFeaturesConsumerImpl.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/TableFeaturesConsumerImpl.java
new file mode 100644 (file)
index 0000000..30556e4
--- /dev/null
@@ -0,0 +1,192 @@
+package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.config.rev131024.Tables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.config.rev131024.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.UpdatedTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TableFeaturesConsumerImpl {
+    protected static final Logger logger = LoggerFactory.getLogger(TableFeaturesConsumerImpl.class);
+    private SalTableService tableService;
+    private TableDataCommitHandler commitHandler;
+    private final IClusterContainerServices clusterContainerService = null;
+    private IContainer container;
+    private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+    private boolean inContainerMode; // being used by global instance only
+
+    public TableFeaturesConsumerImpl() {
+        InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Tables.class).child(Table.class)
+                .toInstance();
+        tableService = FRMConsumerImpl.getProviderSession().getRpcService(SalTableService.class);
+
+        if (null == tableService) {
+            logger.error("Consumer SAL Service is down or NULL. FRM may not function as intended");
+            System.out.println("Consumer SAL Service is down or NULL.");
+            return;
+        }
+
+        System.out.println("-------------------------------------------------------------------");
+        commitHandler = new TableDataCommitHandler();
+        FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
+        container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+    }
+
+    /**
+     * Updates TableFeatures to the southbound plugin and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private void updateTableFeatures(InstanceIdentifier<?> path, TableFeatures dataObject) {
+
+        UpdateTableInputBuilder input = new UpdateTableInputBuilder();
+        UpdatedTableBuilder updatedtablebuilder = new UpdatedTableBuilder();
+        updatedtablebuilder.fieldsFrom(dataObject);
+        List<TableFeatures> features = updatedtablebuilder.build().getTableFeatures();
+        for (TableFeatures feature : features) {
+            if (feature != null && feature.getMaxEntries() != null) {
+                logger.error("Max Entries field is read-only, cannot be changed");
+                return;
+            }
+        }
+        input.setUpdatedTable(updatedtablebuilder.build());
+
+        // We send table feature update request to the sounthbound plugin
+        tableService.updateTable(input.build());
+    }
+
+    @SuppressWarnings("unchecked")
+    private void commitToPlugin(internalTransaction transaction) {
+
+        for (@SuppressWarnings("unused")
+        Entry<InstanceIdentifier<?>, TableFeatures> entry : transaction.updates.entrySet()) {
+            System.out.println("Coming update cc in TableDatacommitHandler");
+            updateTableFeatures(entry.getKey(), entry.getValue());
+        }
+
+    }
+
+    private final class TableDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+            // We should verify transaction
+            System.out.println("Coming in TableFeaturesDatacommitHandler");
+            internalTransaction transaction = new internalTransaction(modification);
+            transaction.prepareUpdate();
+            return transaction;
+        }
+    }
+
+    private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+
+        private final DataModification<InstanceIdentifier<?>, DataObject> modification;
+
+        @Override
+        public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
+            return modification;
+        }
+
+        public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+            this.modification = modification;
+        }
+
+        Map<InstanceIdentifier<?>, TableFeatures> updates = new HashMap<>();
+
+        /**
+         * We create a plan which table features will be updated.
+         *
+         */
+        void prepareUpdate() {
+
+            Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
+            for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+
+                // validating the DataObject
+
+                Status status = validate(container, (TableFeatures) entry);
+                if (!status.isSuccess()) {
+                    logger.warn("Invalid Configuration for table features The failure is {}", entry,
+                            status.getDescription());
+                    String error = "Invalid Configuration (" + status.getDescription() + ")";
+                    logger.error(error);
+                    return;
+                }
+                if (entry.getValue() instanceof TableFeatures) {
+                    TableFeatures tablefeatures = (TableFeatures) entry.getValue();
+                    preparePutEntry(entry.getKey(), tablefeatures);
+                }
+
+            }
+        }
+
+        private void preparePutEntry(InstanceIdentifier<?> key, TableFeatures tablefeatures) {
+            if (tablefeatures != null) {
+                // Updating the Map
+                System.out.println("Coming update  in TableFeaturesDatacommitHandler");
+                updates.put(key, tablefeatures);
+            }
+        }
+
+        /**
+         * We are OK to go with execution of plan
+         *
+         */
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+
+            commitToPlugin(this);
+            // We return true if internal transaction is successful.
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return Rpcs.getRpcResult(true, null, null);
+        }
+
+        /**
+         *
+         * We should rollback our preparation
+         *
+         */
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            // NOOP - we did not modified any internal state during
+            // requestCommit phase
+            // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return Rpcs.getRpcResult(true, null, null);
+
+        }
+
+        public Status validate(IContainer container, TableFeatures dataObject) {
+
+            String tablename = dataObject.getName();
+            if (tablename == null || tablename.trim().isEmpty() || !tablename.matches(NAMEREGEX)
+                    || tablename.length() != 32) {
+                return new Status(StatusCode.BADREQUEST, "Invalid table name");
+            }
+
+            return new Status(StatusCode.SUCCESS);
+        }
+    }
+}
index 97ca8b3c71491063d21ac4284b62e537c3b56dd6..25e8e7aa577968ffc20fccaac459c1e958f4d586 100644 (file)
@@ -18,13 +18,23 @@ module opendaylight-group-types {
         leaf group-type {
             type enumeration {
                 enum group-all;
-                enum group_select;
-                enum group_indirect;
-                enum group_ff;
+                enum group-select;
+                enum group-indirect;
+                enum group-ff;
             }
         }
     }
     
+    typedef group-capabilities { 
+               type enumeration {
+                enum select-weight;
+                enum select-liveness;
+                enum chaining;
+                enum chaining-checks;
+            }   
+        }
+    
+    
     grouping group {
         
         uses group-types;
@@ -119,14 +129,21 @@ module opendaylight-group-types {
     }
 
     grouping group-features {
-        uses group-types;
+        leaf types {
+            type bits {
+               bit group-all;
+               bit group-select;
+               bit group-indirect;
+               bit group-ff;
+            }
+        }
             
         leaf capabilities { 
-               type enumeration {
-                enum select-weight;
-                enum select-liveness;
-                enum chaining;
-                enum chaining-checks;
+               type bits {
+                bit select-weight;
+                bit select-liveness;
+                bit chaining;
+                bit chaining-checks;
             }   
         }
 
index 5b565365a5894f9912fde799a5a8f1b56855094b..d29ddc0ddd68bcef17b84cfec9ac92eab6d5cc24 100644 (file)
@@ -54,6 +54,10 @@ module opendaylight-group-statistics {
        rpc get-group-statistics {
                input {
             uses inv:node;
+            leaf group-id{
+               type group-types:group-id;
+            }
+           
         }
         output {
             uses group-types:group-statistics-reply;
index c207db0478c9696ae68c28b00566b42085e4244b..bbbb5c856646cf273445f47e84e8a1a5e46df844 100644 (file)
@@ -232,7 +232,7 @@ public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsList
         GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder();
         groupFeatures.setActions(notification.getActions());
         groupFeatures.setCapabilities(notification.getCapabilities());
-        groupFeatures.setGroupType(notification.getGroupType());
+        groupFeatures.setTypes(notification.getTypes());
         groupFeatures.setMaxGroups(notification.getMaxGroups());
         cache.get(notification.getId()).setGroupFeatures(groupFeatures.build());
         
index 97d2a6d02a40a054135b7bf390279fb669208f87..6ec4c2ce01f7ccb675873890a3ff80bfa6102963 100644 (file)
@@ -19,10 +19,12 @@ public interface RoutingTable<I,R> {
    *
    * @param routeId route identifier
    * @param route network address
+   * @throws RoutingTableException for any logical exception
+   * @throws SystemException
    */
-  public void addRoute(I routeId, R route) throws SystemException,  RoutingTableException;
+  public void addRoute(I routeId, R route) throws  RoutingTableException,SystemException;
 
-  /**
+    /**
    * Adds a network address for the route. If the route already exists,
    * it throws <code>DuplicateRouteException</code>.
    * This method would be used when registering a global service.
@@ -31,6 +33,7 @@ public interface RoutingTable<I,R> {
    * @param routeId route identifier
    * @param route network address
    * @throws DuplicateRouteException
+   * @throws RoutingTableException
    */
   public void addGlobalRoute(I routeId, R route) throws  RoutingTableException, SystemException;
 
@@ -50,8 +53,10 @@ public interface RoutingTable<I,R> {
      * Remove the route.
      * This method would be used when registering a global service.
      * @param routeId
+     * @throws RoutingTableException
+     * @throws SystemException
      */
-    public void removeGlobalRoute(I routeId);
+    public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException;
 
   /**
    * Returns a set of network addresses associated with this route
@@ -69,6 +74,13 @@ public interface RoutingTable<I,R> {
    */
   public R getARoute(I routeId);
 
+    /**
+     *
+     * This will be removed after listeners
+     * have made change on their end to use whiteboard pattern
+     * @deprecated
+     */
+
   public void registerRouteChangeListener(RouteChangeListener listener);
 
   public class DuplicateRouteException extends RoutingTableException {
index 45414437ccb3d3afe6279fd1d428a8dc930d60fc..6e2d280a89f5158358c3d6757c7c1e4e2f72e64e 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.sal.connector.remoterpc.impl;
 import org.apache.felix.dm.Component;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
 import org.slf4j.Logger;
@@ -72,6 +73,15 @@ public class Activator extends ComponentActivatorAbstractBase {
             c.setInterface(new String[] { RoutingTable.class.getName(),ICacheUpdateAware.class.getName()  }, props);
             logger.debug("configureGlobalInstance adding dependency:", IClusterGlobalServices.class);
 
+
+            // RouteChangeListener services will be none or many so the
+            // dependency is optional
+            c.add(createServiceDependency()
+                    .setService(RouteChangeListener.class)
+                    .setCallbacks("setRouteChangeListener", "unsetRouteChangeListener")
+                    .setRequired(false));
+
+            //dependency is required as it provides us the caching support
             c.add(createServiceDependency().setService(
                     IClusterGlobalServices.class).setCallbacks(
                     "setClusterGlobalServices",
index 558c8a80d32b59aaf092a4505e680c9eabb14190..4e1dfb00588a3e2ae566a744ea1f05eb51ca4bf1 100644 (file)
@@ -10,12 +10,16 @@ package org.opendaylight.controller.sal.connector.remoterpc.impl;
 
 import com.google.common.base.Preconditions;
 import org.apache.felix.dm.Component;
-import org.opendaylight.controller.clustering.services.*;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.CacheListenerAddException;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
 import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
-import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -23,243 +27,298 @@ import javax.transaction.HeuristicMixedException;
 import javax.transaction.HeuristicRollbackException;
 import javax.transaction.NotSupportedException;
 import javax.transaction.RollbackException;
-import java.util.*;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 
 /**
  * @author: syedbahm
  */
-public class RoutingTableImpl<I, R> implements RoutingTable<I, R>,ICacheUpdateAware<I,R> {
+public class RoutingTableImpl<I, R> implements RoutingTable<I, R>, ICacheUpdateAware<I, R> {
     public static final String ROUTING_TABLE_GLOBAL_CACHE = "routing_table_global_cache";
 
-  private Logger log = LoggerFactory
-            .getLogger(RoutingTableImpl.class);
-
-  private IClusterGlobalServices clusterGlobalServices = null;
-  private RoutingTableImpl routingTableInstance = null;
-  private ConcurrentMap routingTableCache = null;
-  private List<RouteChangeListener>  routeChangeListeners = new ArrayList<RouteChangeListener>();
-  private ServiceRegistration cacheAwareRegistration = null;
-                                                      
- public RoutingTableImpl() {
-  }
-
-  @Override
-  public void addRoute(I routeId, R route) throws RoutingTableException {
-       throw new UnsupportedOperationException(" Not implemented yet!");
-  }
-
-  @Override
-  public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException {
-    Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
-    Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
-    try {
-
-      Set<R> existingRoute = null;
-      // ok does the global route is already registered ?
-      if ((existingRoute = getRoutes(routeId)) == null) {
-
-          if(log.isDebugEnabled()){
-              log.debug("addGlobalRoute: adding  a new route with id"+ routeId + " and value = "+route);
-          }
-        // lets start a transaction
-        clusterGlobalServices.tbegin();
-        Set<R> routes  = new HashSet<R>();
-        routes.add(route);
-        routingTableCache.put(routeId, routes);
-        clusterGlobalServices.tcommit();
-      } else {
-        throw new DuplicateRouteException(" There is already existing route " + existingRoute);
-      }
-
-    } catch (NotSupportedException e) {
-      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
-    } catch (HeuristicRollbackException e) {
-      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
-    } catch (RollbackException e) {
-      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
-    } catch (HeuristicMixedException e) {
-      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
-    } catch (javax.transaction.SystemException e){
-        throw new SystemException ( "System error occurred - while trying to create with value",e);
+    private Logger log = LoggerFactory.getLogger(RoutingTableImpl.class);
+
+    private IClusterGlobalServices clusterGlobalServices = null;
+    private RoutingTableImpl routingTableInstance = null;
+    private ConcurrentMap routingTableCache = null;
+    private Set<RouteChangeListener> routeChangeListeners = Collections
+            .synchronizedSet(new HashSet<RouteChangeListener>());
+
+    public RoutingTableImpl() {
     }
 
-  }
+    @Override
+    public void addRoute(I routeId, R route) throws RoutingTableException {
+        throw new UnsupportedOperationException(" Not implemented yet!");
+    }
 
-  @Override
-  public void removeRoute(I routeId, R route) {
-         throw new UnsupportedOperationException("Not implemented yet!");
-  }
     @Override
-    public void removeGlobalRoute(I routeId) {
-        routingTableCache.remove(routeId);
+    public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException {
+        Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
+        Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
+        try {
+
+            Set<R> existingRoute = null;
+            // ok does the global route is already registered ?
+            if ((existingRoute = getRoutes(routeId)) == null) {
+
+                if (log.isDebugEnabled()) {
+                    log.debug("addGlobalRoute: adding  a new route with id" + routeId + " and value = "
+                            + route);
+                }
+                // lets start a transaction
+                clusterGlobalServices.tbegin();
+                Set<R> routes = new HashSet<R>();
+                routes.add(route);
+                routingTableCache.put(routeId, routes);
+                clusterGlobalServices.tcommit();
+            } else {
+                throw new DuplicateRouteException(" There is already existing route " + existingRoute);
+            }
+
+        } catch (NotSupportedException e) {
+            throw new RoutingTableException("Transaction error - while trying to create route id="
+                    + routeId + "with route" + route, e);
+        } catch (HeuristicRollbackException e) {
+            throw new RoutingTableException("Transaction error - while trying to create route id="
+                    + routeId + "with route" + route, e);
+        } catch (RollbackException e) {
+            throw new RoutingTableException("Transaction error - while trying to create route id="
+                    + routeId + "with route" + route, e);
+        } catch (HeuristicMixedException e) {
+            throw new RoutingTableException("Transaction error - while trying to create route id="
+                    + routeId + "with route" + route, e);
+        } catch (javax.transaction.SystemException e) {
+            throw new SystemException("System error occurred - while trying to create with value", e);
+        }
+
     }
 
-  @Override
-  public Set<R> getRoutes(I routeId) {
+    @Override
+    public void removeRoute(I routeId, R route) {
+        throw new UnsupportedOperationException("Not implemented yet!");
+    }
 
-      //Note: currently works for global routes only wherein there is just single route
-      Preconditions.checkNotNull(routeId, "getARoute: routeId cannot be null!");
-      return (Set<R>) routingTableCache.get(routeId);
-  }
+    @Override
+    public void removeGlobalRoute(I routeId) throws RoutingTableException, SystemException {
+        Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("removeGlobalRoute: removing  a new route with id" + routeId);
+            }
+            // lets start a transaction
+            clusterGlobalServices.tbegin();
+
+            routingTableCache.remove(routeId);
+            clusterGlobalServices.tcommit();
+
+        } catch (NotSupportedException e) {
+            throw new RoutingTableException("Transaction error - while trying to remove route id="
+                    + routeId, e);
+        } catch (HeuristicRollbackException e) {
+            throw new RoutingTableException("Transaction error - while trying to remove route id="
+                    + routeId, e);
+        } catch (RollbackException e) {
+            throw new RoutingTableException("Transaction error - while trying to remove route id="
+                    + routeId, e);
+        } catch (HeuristicMixedException e) {
+            throw new RoutingTableException("Transaction error - while trying to remove route id="
+                    + routeId, e);
+        } catch (javax.transaction.SystemException e) {
+            throw new SystemException("System error occurred - while trying to remove with value", e);
+        }
+    }
 
-  @Override
-  public R getARoute(I routeId) {
-       throw new UnsupportedOperationException("Not implemented yet!");
-  }
+    @Override
+    public Set<R> getRoutes(I routeId) {
 
-  /**
-   * Registers listener for sending any change notification
-   * 
-   * @param listener
-   */
-  @Override
-  public void registerRouteChangeListener(RouteChangeListener listener) {
-      routeChangeListeners.add(listener);
-  }
+        // Note: currently works for global routes only wherein there is just single
+        // route
+        Preconditions.checkNotNull(routeId, "getARoute: routeId cannot be null!");
+        return (Set<R>) routingTableCache.get(routeId);
+    }
 
+    @Override
+    public R getARoute(I routeId) {
+        throw new UnsupportedOperationException("Not implemented yet!");
+    }
 
     /**
-     * Returning the list of route change listeners for Unit testing
-     * Note: the package scope is default
-     * @return   List of registered RouteChangeListener<I,R> listeners
+     * @deprecated doesn't do anything will be removed once listeners used
+     *             whiteboard pattern Registers listener for sending any change
+     *             notification
+     * @param listener
      */
-  List<RouteChangeListener> getRegisteredRouteChangeListeners(){
-      return routeChangeListeners;
-  }
+    @Override
+    public void registerRouteChangeListener(RouteChangeListener listener) {
 
-  public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
-    this.clusterGlobalServices = clusterGlobalServices;
-  }
+    }
 
-  public void unsetClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
-    if(cacheAwareRegistration != null) {
-        cacheAwareRegistration.unregister();
+    public void setRouteChangeListener(RouteChangeListener rcl) {
+        if(rcl != null){
+            routeChangeListeners.add(rcl);
+        }else{
+            log.warn("setRouteChangeListener called with null listener");
+        }
+    }
+
+    public void unSetRouteChangeListener(RouteChangeListener rcl) {
+        if(rcl != null){
+         routeChangeListeners.remove(rcl);
+        }else{
+            log.warn("unSetRouteChangeListener called with null listener");
+        }
     }
-    this.clusterGlobalServices = null;
-  }
 
     /**
-     * Creates the Routing Table clustered global services cache
-     * @throws CacheExistException  -- cluster global services exception when cache exist
-     * @throws CacheConfigException -- cluster global services exception during cache config
-     * @throws CacheListenerAddException  -- cluster global services exception during adding of listener
+     * Returning the set of route change listeners for Unit testing Note: the
+     * package scope is default
+     *
+     * @return List of registered RouteChangeListener<I,R> listeners
      */
+    Set<RouteChangeListener> getRegisteredRouteChangeListeners() {
+        return routeChangeListeners;
+    }
 
-  void createRoutingTableCache() throws CacheExistException, CacheConfigException, CacheListenerAddException {
-    // TBD: HOW DO WE DECIDE ON PROPERTIES OF THE CACHE i.e. what duration it
-    // should be caching?
-
-    // let us check here if the cache already exists -- if so don't create
-    if (!clusterGlobalServices.existCache(
-        ROUTING_TABLE_GLOBAL_CACHE)) {
+    public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
+        this.clusterGlobalServices = clusterGlobalServices;
+    }
 
-        if(log.isDebugEnabled()){
-            log.debug("createRoutingTableCache: creating a new routing table cache "+ROUTING_TABLE_GLOBAL_CACHE );
-        }
-      routingTableCache = clusterGlobalServices.createCache(
-          ROUTING_TABLE_GLOBAL_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-    } else {
-        if(log.isDebugEnabled()){
-            log.debug("createRoutingTableCache: found existing routing table cache "+ROUTING_TABLE_GLOBAL_CACHE );
+    public void unsetClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
+        if((clusterGlobalServices != null ) &&  (this.clusterGlobalServices.equals(clusterGlobalServices))){
+            this.clusterGlobalServices = null;
         }
-      routingTableCache = clusterGlobalServices.getCache(
-          ROUTING_TABLE_GLOBAL_CACHE);
     }
 
-  }
-
-  /**
-   * Function called by the dependency manager when all the required
-   * dependencies are satisfied
-   * 
-   */
-  void init(Component c) {
-    try {
-
-      createRoutingTableCache();
-    } catch (CacheExistException e) {
-      throw new IllegalStateException("could not construct routing table cache");
-    } catch (CacheConfigException e) {
-      throw new IllegalStateException("could not construct routing table cache");
-    } catch (CacheListenerAddException e) {
-        throw new IllegalStateException("could not construct routing table cache");
+    /**
+     * Creates the Routing Table clustered global services cache
+     *
+     * @throws CacheExistException
+     *           -- cluster global services exception when cache exist
+     * @throws CacheConfigException
+     *           -- cluster global services exception during cache config
+     * @throws CacheListenerAddException
+     *           -- cluster global services exception during adding of listener
+     */
+
+    void createRoutingTableCache() throws CacheExistException, CacheConfigException,
+            CacheListenerAddException {
+        // TBD: HOW DO WE DECIDE ON PROPERTIES OF THE CACHE i.e. what duration it
+        // should be caching?
+
+        // let us check here if the cache already exists -- if so don't create
+        if (!clusterGlobalServices.existCache(ROUTING_TABLE_GLOBAL_CACHE)) {
+
+            if (log.isDebugEnabled()) {
+                log.debug("createRoutingTableCache: creating a new routing table cache "
+                        + ROUTING_TABLE_GLOBAL_CACHE);
+            }
+            routingTableCache = clusterGlobalServices.createCache(ROUTING_TABLE_GLOBAL_CACHE,
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("createRoutingTableCache: found existing routing table cache "
+                        + ROUTING_TABLE_GLOBAL_CACHE);
+            }
+            routingTableCache = clusterGlobalServices.getCache(ROUTING_TABLE_GLOBAL_CACHE);
+        }
+
     }
-  }
 
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        try {
+
+            createRoutingTableCache();
+        } catch (CacheExistException e) {
+            throw new IllegalStateException("could not construct routing table cache");
+        } catch (CacheConfigException e) {
+            throw new IllegalStateException("could not construct routing table cache");
+        } catch (CacheListenerAddException e) {
+            throw new IllegalStateException("could not construct routing table cache");
+        }
+    }
 
     /**
-     * Get routing table method is useful for unit testing
-     * <note>It has package scope</note>
+     * Get routing table method is useful for unit testing <note>It has package
+     * scope</note>
      */
-    ConcurrentMap getRoutingTableCache(){
+    ConcurrentMap getRoutingTableCache() {
         return this.routingTableCache;
     }
 
+    /**
+     * Invoked when a new entry is available in the cache, the key is only
+     * provided, the value will come as an entryUpdate invocation
+     *
+     * @param key
+     *          Key for the entry just created
+     * @param cacheName
+     *          name of the cache for which update has been received
+     * @param originLocal
+     *          true if the event is generated from this node
+     */
+    @Override
+    public void entryCreated(I key, String cacheName, boolean originLocal) {
+        // TBD: do we require this.
+        if (log.isDebugEnabled()) {
+            log.debug("RoutingTableUpdates: entryCreated  routeId = " + key + " cacheName=" + cacheName);
+        }
+    }
 
-      /**
-       * Invoked when a new entry is available in the cache, the key is
-       * only provided, the value will come as an entryUpdate invocation
-       *
-       * @param key         Key for the entry just created
-       * @param cacheName   name of the cache for which update has been
-       *                    received
-       * @param originLocal true if the event is generated from this
-       *                    node
-       */
-      @Override
-      public void entryCreated(I key, String cacheName, boolean originLocal) {
-          //TBD: do we require this.
-          if(log.isDebugEnabled()){
-              log.debug("RoutingTableUpdates: entryCreated  routeId = "+key
-                      + " cacheName="+cacheName
-                      );
-          }
-      }
-
-      /**
-       * Called anytime a given entry is updated
-       *
-       * @param key         Key for the entry modified
-       * @param new_value   the new value the key will have
-       * @param cacheName   name of the cache for which update has been
-       *                    received
-       * @param originLocal true if the event is generated from this
-       *                    node
-       */
-      @Override
-      public void entryUpdated(I key, R new_value, String cacheName, boolean originLocal) {
-          if(log.isDebugEnabled()){
-              log.debug("RoutingTableUpdates: entryUpdated  routeId = "+key
-                      + ",value = "+ new_value
-                      + " ,cacheName="+cacheName
-                      );
-          }
-          for(RouteChangeListener rcl:routeChangeListeners){
-              rcl.onRouteUpdated(key, new_value);
-          }
-      }
-
-      /**
-       * Called anytime a given key is removed from the
-       * ConcurrentHashMap we are listening to.
-       *
-       * @param key         Key of the entry removed
-       * @param cacheName   name of the cache for which update has been
-       *                    received
-       * @param originLocal true if the event is generated from this
-       *                    node
-       */
-      @Override
-      public void entryDeleted(I key, String cacheName, boolean originLocal) {
-          if(log.isDebugEnabled()){
-              log.debug("RoutingTableUpdates: entryUpdated  routeId = "+key
-                      + " local = "+ originLocal
-                      + " cacheName="+cacheName
-                       );
-          }
-          for(RouteChangeListener rcl:routeChangeListeners){
-              rcl.onRouteDeleted(key);
-          }
-      }
-  }
\ No newline at end of file
+    /**
+     * Called anytime a given entry is updated
+     *
+     * @param key
+     *          Key for the entry modified
+     * @param new_value
+     *          the new value the key will have
+     * @param cacheName
+     *          name of the cache for which update has been received
+     * @param originLocal
+     *          true if the event is generated from this node
+     */
+    @Override
+    public void entryUpdated(I key, R new_value, String cacheName, boolean originLocal) {
+        if (log.isDebugEnabled()) {
+            log.debug("RoutingTableUpdates: entryUpdated  routeId = " + key + ",value = " + new_value
+                    + " ,cacheName=" + cacheName + " originLocal="+originLocal);
+        }
+        if (!originLocal) {
+            for (RouteChangeListener rcl : routeChangeListeners) {
+                rcl.onRouteUpdated(key, new_value);
+            }
+        }
+    }
+
+    /**
+     * Called anytime a given key is removed from the ConcurrentHashMap we are
+     * listening to.
+     *
+     * @param key
+     *          Key of the entry removed
+     * @param cacheName
+     *          name of the cache for which update has been received
+     * @param originLocal
+     *          true if the event is generated from this node
+     */
+    @Override
+    public void entryDeleted(I key, String cacheName, boolean originLocal) {
+        if (log.isDebugEnabled()) {
+            log.debug("RoutingTableUpdates: entryUpdated  routeId = " + key + " local = " + originLocal
+                    + " cacheName=" + cacheName + " originLocal="+originLocal);
+        }
+        if (!originLocal) {
+            for (RouteChangeListener rcl : routeChangeListeners) {
+                rcl.onRouteDeleted(key);
+            }
+        }
+    }
+}
\ No newline at end of file
index 75cc6f5da811a5c073071a71bb0fecf1e256455d..2ef251d9a1f0a642020b2b5d9299970bdf429189 100644 (file)
@@ -103,7 +103,12 @@ public class RoutingTableImplTest {
         Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),0);
         rti.registerRouteChangeListener(new RouteChangeListenerImpl());
 
-        Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),1);
+        Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),0); //old should not work
+        //what about the new approach - using whiteboard pattern
+        rti.setRouteChangeListener(new RouteChangeListenerImpl());
+
+        Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),1); //should not work
+
 
     }
     @Test
index 3b6d398511304f1fc2e3cf23361d977c83d40ebf..a7929e82fce2bce0b9895e2db666afbd26d0f16d 100644 (file)
@@ -21,7 +21,6 @@ import java.io.Serializable;
 import java.net.URI;
 import java.util.Set;
 
-
 import static org.ops4j.pax.exam.CoreOptions.junitBundles;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.options;
@@ -41,6 +40,7 @@ public class
     public static final String YANG = "org.opendaylight.yangtools";
     public static final String CONTROLLER = "org.opendaylight.controller";
     public static final String YANGTOOLS = "org.opendaylight.yangtools";
+    RoutingIdentifierImpl rii  = new RoutingIdentifierImpl();
     // get the OSGI bundle context
     @Inject
     private BundleContext bc;
@@ -171,9 +171,6 @@ public class
 
                 mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
 
-                mavenBundle(YANG, "concepts").versionAsInProject(),
-                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
-                mavenBundle(YANG, "yang-common").versionAsInProject(), //
                 mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(),
                 mavenBundle("com.google.guava", "guava").versionAsInProject(), //
                 mavenBundle("org.javassist", "javassist").versionAsInProject(),
@@ -248,7 +245,7 @@ public class
 
     @Test
   public  void testAddGlobalRoute () throws Exception{
-       RoutingIdentifierImpl rii  = new RoutingIdentifierImpl();
+
        routingTable.addGlobalRoute(rii,"172.27.12.1:5000");
 
        Set<String> routes = routingTable.getRoutes(rii);
@@ -261,6 +258,20 @@ public class
     }
 
 
+    @Test
+    public  void testDeleteGlobalRoute () throws Exception{
+
+        routingTable.removeGlobalRoute(rii);
+
+        Set<String> routes = routingTable.getRoutes(rii);
+
+        Assert.assertNull(routes);
+
+
+    }
+
+
+
    class RoutingIdentifierImpl implements RpcRouter.RouteIdentifier,Serializable {
 
        private final URI namespace = URI.create("http://cisco.com/example");
@@ -281,6 +292,28 @@ public class
        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
            return InstanceIdentifier.of(instance);
        }
+
+       @Override
+       public boolean equals(Object o) {
+           if (this == o) return true;
+           if (o == null || getClass() != o.getClass()) return false;
+
+           RoutingIdentifierImpl that = (RoutingIdentifierImpl) o;
+
+           if (QNAME != null ? !QNAME.equals(that.QNAME) : that.QNAME != null) return false;
+           if (instance != null ? !instance.equals(that.instance) : that.instance != null) return false;
+           if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;
+
+           return true;
+       }
+
+       @Override
+       public int hashCode() {
+           int result = namespace != null ? namespace.hashCode() : 0;
+           result = 31 * result + (QNAME != null ? QNAME.hashCode() : 0);
+           result = 31 * result + (instance != null ? instance.hashCode() : 0);
+           return result;
+       }
    }
 
 
index b163c639a5c53d507988958ef04afc0b1d1d540f..f26bcf718c75216078d4b7f37f16d19603ec20bf 100644 (file)
@@ -415,7 +415,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
              */
             if (inPort == null
                     || container.equals(GlobalConstants.DEFAULT.toString())
-                    || this.containerToNc.get(container).contains(inPort)) {
+                    || (containerToNc.containsKey(container) && containerToNc.get(container).contains(inPort))) {
                 notifier.flowRemoved(node, flow);
             }
         }