New P4RuntimeClient implementation that supports batching and error reporting

The new client API supports batching and provides detailed response for
write requests (e.g. if entity already exists when inserting), which was
not possible with the old one.

This patch includes:
- New more efficient implementation of P4RuntimeClient (no more locking,
use native gRPC executor, use stub deadlines)
- Ported all codecs to new AbstractCodec-based implementation (needed to
implement codec cache in the future)
- Uses batching in P4RuntimeFlowRuleProgrammable and
P4RuntimeGroupActionProgrammable
- Minor changes to PI framework runtime classes

Change-Id: I3fac42057bb4e1389d761006a32600c786598683
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCell.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCell.java
index 9508cbc..34ebd7b 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCell.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCell.java
@@ -19,21 +19,23 @@
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
+import org.onosproject.net.DeviceId;
 
 /**
  * Counter cell of a protocol-independent pipeline.
  */
 @Beta
-public final class PiCounterCell {
+public final class PiCounterCell implements PiEntity {
 
     private final PiCounterCellId cellId;
     private final PiCounterCellData counterData;
 
     /**
-     * Creates a new counter cell for the given cell identifier and counter cell data.
+     * Creates a new counter cell for the given cell identifier and counter cell
+     * data.
      *
-     * @param cellId  counter cell identifier
-     * @param piCounterCellData  counter cell data
+     * @param cellId            counter cell identifier
+     * @param piCounterCellData counter cell data
      */
     public PiCounterCell(PiCounterCellId cellId, PiCounterCellData piCounterCellData) {
         this.cellId = cellId;
@@ -41,11 +43,12 @@
     }
 
     /**
-     * Creates a new counter cell for the given cell identifier, number of packets and bytes.
+     * Creates a new counter cell for the given cell identifier, number of
+     * packets and bytes.
      *
      * @param cellId  counter cell identifier
-     * @param packets  number of packets
-     * @param bytes  number of bytes
+     * @param packets number of packets
+     * @param bytes   number of bytes
      */
     public PiCounterCell(PiCounterCellId cellId, long packets, long bytes) {
         this.cellId = cellId;
@@ -71,6 +74,16 @@
     }
 
     @Override
+    public PiEntityType piEntityType() {
+        return PiEntityType.COUNTER_CELL;
+    }
+
+    @Override
+    public PiCounterCellHandle handle(DeviceId deviceId) {
+        return PiCounterCellHandle.of(deviceId, this);
+    }
+
+    @Override
     public boolean equals(Object o) {
         if (this == o) {
             return true;