Add batch insert/delete queues to QoS for QosConfigBehaviour.

Change-Id: I9331f4ecbc95fc47be313f92aa07413fb2df5ed8
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/QosConfigBehaviour.java b/core/api/src/main/java/org/onosproject/net/behaviour/QosConfigBehaviour.java
index d87af71..3f176ed 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/QosConfigBehaviour.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/QosConfigBehaviour.java
@@ -18,6 +18,8 @@
 import org.onosproject.net.driver.HandlerBehaviour;
 
 import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Behaviour for handling various operations for qos configurations.
@@ -51,4 +53,20 @@
      * @param qosId qos identifier
      */
     void deleteQoS(QosId qosId);
+
+    /**
+     * bind queue to qos.
+     *
+     * @param  qosId the qos name
+     * @param  queues qos queues, map of QueueKey - QueueDescription
+     */
+    void insertQueues(QosId qosId, Map<Long, QueueDescription> queues);
+
+    /**
+     * delete queue from qos.
+     *
+     * @param  qosId the qos name
+     * @param  queueKeys queue id to delete
+     */
+    void deleteQueues(QosId qosId, List<Long> queueKeys);
 }
\ No newline at end of file
diff --git a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbQosConfig.java b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbQosConfig.java
index bc60fd2..27f6954 100644
--- a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbQosConfig.java
+++ b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbQosConfig.java
@@ -23,6 +23,7 @@
 import org.onosproject.net.behaviour.QosConfigBehaviour;
 import org.onosproject.net.behaviour.QosDescription;
 import org.onosproject.net.behaviour.QosId;
+import org.onosproject.net.behaviour.QueueDescription;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.driver.DriverHandler;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
@@ -32,6 +33,8 @@
 import org.slf4j.Logger;
 
 import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -117,6 +120,18 @@
         ovsdbClient.dropQos(qosId);
     }
 
+    @Override
+    public void insertQueues(QosId qosId, Map<Long, QueueDescription> queues) {
+        OvsdbClientService ovsdbClient = getOvsdbClient(handler());
+        ovsdbClient.bindQueues(qosId, queues);
+    }
+
+    @Override
+    public void deleteQueues(QosId qosId, List<Long> queueKeys) {
+        OvsdbClientService ovsdbClient = getOvsdbClient(handler());
+        ovsdbClient.unbindQueues(qosId, queueKeys);
+    }
+
     // OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
     // is used in the core. So DeviceId need be changed to OvsdbNodeId.
     private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
index f1de521..dfa1518 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
@@ -16,6 +16,7 @@
 package org.onosproject.ovsdb.controller;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.onosproject.net.DeviceId;
@@ -24,6 +25,7 @@
 import org.onosproject.net.behaviour.MirroringName;
 import org.onosproject.net.behaviour.MirroringStatistics;
 import org.onosproject.net.behaviour.QosId;
+import org.onosproject.net.behaviour.QueueDescription;
 import org.onosproject.net.behaviour.QueueId;
 import org.onosproject.ovsdb.rfc.jsonrpc.OvsdbRpc;
 import org.onosproject.ovsdb.rfc.message.TableUpdates;
@@ -125,6 +127,22 @@
     Set<OvsdbQos> getQoses();
 
     /**
+     * Bind Queue to QoS.
+     *
+     * @param qosId qos identifier
+     * @param queues the Queue key and Queue description
+     */
+    void bindQueues(QosId qosId, Map<Long, QueueDescription> queues);
+
+    /**
+     * Unbind Queue from QoS.
+     *
+     * @param qosId qos identifier
+     * @param queueKeys queue key
+     */
+    void unbindQueues(QosId qosId, List<Long> queueKeys);
+
+    /**
      * Creates queues. limits the rate of each flow
      * depend on itself priority.
      *
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index 3f8ec1c..0d3bf36 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -43,6 +43,7 @@
 import org.onosproject.net.behaviour.MirroringName;
 import org.onosproject.net.behaviour.MirroringStatistics;
 import org.onosproject.net.behaviour.QosId;
+import org.onosproject.net.behaviour.QueueDescription;
 import org.onosproject.net.behaviour.QueueId;
 import org.onosproject.ovsdb.controller.OvsdbBridge;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
@@ -773,6 +774,107 @@
     }
 
     @Override
+    public void bindQueues(QosId qosId, Map<Long, QueueDescription> queues) {
+        DatabaseSchema dbSchema = schema.get(DATABASENAME);
+        OvsdbRowStore qosRowStore = getRowStore(DATABASENAME, QOS);
+        if (qosRowStore == null) {
+            log.debug("The qos uuid is null");
+            return;
+        }
+        OvsdbRowStore queueRowStore = getRowStore(DATABASENAME, QUEUE);
+        if (queueRowStore == null) {
+            log.debug("The queue uuid is null");
+            return;
+        }
+
+        ConcurrentMap<String, Row> qosTableRows = qosRowStore.getRowStore();
+        ConcurrentMap<String, Row> queueTableRows = queueRowStore.getRowStore();
+
+        Row qosRow = qosTableRows.values().stream().filter(r -> {
+            OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
+            return qosId.name().equals(ovsdbMap.map().get(QOS_EXTERNAL_ID_KEY));
+        }).findFirst().orElse(null);
+
+        if (qosRow == null) {
+            log.warn("Can't find QoS {}", qosId);
+            return;
+        }
+
+        Uuid qosUuid = qosRow.uuid();
+
+        Map<Long, Uuid> newQueues = new HashMap<Long, Uuid>();
+        for (Map.Entry<Long, QueueDescription> entry : queues.entrySet()) {
+            Row queueRow = queueTableRows.values().stream().filter(r -> {
+                OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
+                return entry.getValue().queueId().name().equals(ovsdbMap.map().get(QUEUE_EXTERNAL_ID_KEY));
+            }).findFirst().orElse(null);
+            if (queueRow != null) {
+                newQueues.put(entry.getKey(), queueRow.uuid());
+            }
+        }
+
+        // update the qos table
+        ArrayList<Operation> operations = Lists.newArrayList();
+        Condition condition = ConditionUtil.isEqual(UUID, qosUuid);
+        Mutation mutation = MutationUtil.insert(QUEUES, newQueues);
+        List<Condition> conditions = Collections.singletonList(condition);
+        List<Mutation> mutations = Collections.singletonList(mutation);
+        operations.add(new Mutate(dbSchema.getTableSchema(QOS), conditions, mutations));
+
+        transactConfig(DATABASENAME, operations);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void unbindQueues(QosId qosId, List<Long> queueKeys) {
+        DatabaseSchema dbSchema = schema.get(DATABASENAME);
+        OvsdbRowStore qosRowStore = getRowStore(DATABASENAME, QOS);
+        if (qosRowStore == null) {
+            return;
+        }
+
+        ConcurrentMap<String, Row> qosTableRows = qosRowStore.getRowStore();
+
+        Row qosRow = qosTableRows.values().stream().filter(r -> {
+            OvsdbMap ovsdbMap = (OvsdbMap) (r.getColumn(EXTERNAL_ID).data());
+            return qosId.name().equals(ovsdbMap.map().get(QOS_EXTERNAL_ID_KEY));
+        }).findFirst().orElse(null);
+
+        if (qosRow == null) {
+            log.warn("Can't find QoS {}", qosId);
+            return;
+        }
+
+        Map<Long, Uuid> deleteQueuesMap = new HashMap<>();
+        Map<Integer, Uuid> queuesMap = ((OvsdbMap) qosRow.getColumn(QUEUES).data()).map();
+
+        queueKeys.forEach(key -> {
+            if (queuesMap.containsKey(key.intValue())) {
+                deleteQueuesMap.put(key, queuesMap.get(key.intValue()));
+            }
+        });
+
+        if (deleteQueuesMap.size() != 0) {
+            TableSchema parentTableSchema = dbSchema
+                    .getTableSchema(QOS);
+            ColumnSchema parentColumnSchema = parentTableSchema
+                    .getColumnSchema(QUEUES);
+
+            Mutation mutation = MutationUtil.delete(parentColumnSchema.name(), OvsdbMap.ovsdbMap(deleteQueuesMap));
+            List<Mutation> mutations = Collections.singletonList(mutation);
+
+            Condition condition = ConditionUtil.isEqual(UUID, qosRow.uuid());
+            List<Condition> conditionList = Collections.singletonList(condition);
+            List<Operation> operations = Collections.singletonList(
+                    new Mutate(parentTableSchema, conditionList, mutations));
+
+            transactConfig(DATABASENAME, operations);
+        }
+    }
+
+
+    @Override
     public boolean createQueue(OvsdbQueue ovsdbQueue) {
         DatabaseSchema dbSchema = schema.get(DATABASENAME);
         Queue queue = (Queue) TableGenerator.createTable(dbSchema, OvsdbTable.QUEUE);
diff --git a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
index a548255..7e05c4c 100644
--- a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
+++ b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
@@ -18,6 +18,7 @@
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.onosproject.net.DeviceId;
@@ -26,6 +27,7 @@
 import org.onosproject.net.behaviour.MirroringName;
 import org.onosproject.net.behaviour.MirroringStatistics;
 import org.onosproject.net.behaviour.QosId;
+import org.onosproject.net.behaviour.QueueDescription;
 import org.onosproject.net.behaviour.QueueId;
 import org.onosproject.ovsdb.controller.OvsdbBridge;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
@@ -120,6 +122,16 @@
     }
 
     @Override
+    public void bindQueues(QosId qosId, Map<Long, QueueDescription> queues) {
+
+    }
+
+    @Override
+    public void unbindQueues(QosId qosId, List<Long> queueKeys) {
+
+    }
+
+    @Override
     public boolean createQueue(OvsdbQueue queue) {
         return false;
     }