[VOL-2688] Improve core model performance

This commit addresses the low-hanging performance hogs in the
core model.  In particular, the following changes are made:

1) Remove proto message comparision when it's possible.  The proto
message deep comparison is quite expensive.
2) Since the Core already has a lock on the device/logicaldevice/
adapters/etc before invoking the model proxy then there is no
need for the latter to create an additional lock on these artifacts
duting an update
3) The model creates a watch on every artifacts it adds to the KV
store.   Since in the next Voltha release we will not be using Voltha
Core in pairs then there is no point in keeping these watches (these
is only 1 Core that will ever update an artifact in the next
deployment).  This update removes these watch.
4) Additional unit tests has been created, mostly around flows, in an
attempt to exercise both the core and the model further.

Change-Id: Ieaf1f6b9b05c56e819600bc55b46a05f73b8efcf
diff --git a/rw_core/mocks/adapter_olt.go b/rw_core/mocks/adapter_olt.go
index 2ab98a3..303bae3 100644
--- a/rw_core/mocks/adapter_olt.go
+++ b/rw_core/mocks/adapter_olt.go
@@ -20,6 +20,7 @@
 	"context"
 	"fmt"
 	"strings"
+	"sync"
 
 	"github.com/gogo/protobuf/proto"
 	"github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
@@ -31,19 +32,25 @@
 )
 
 const (
-	numONUPerOLT = 4
+	numONUPerOLT      = 4
+	startingUNIPortNo = 100
 )
 
 // OLTAdapter represent OLT adapter
 type OLTAdapter struct {
+	flows map[uint64]*voltha.OfpFlowStats
+	lock  sync.Mutex
 	Adapter
 }
 
 // NewOLTAdapter - creates OLT adapter instance
 func NewOLTAdapter(cp adapterif.CoreProxy) *OLTAdapter {
-	a := &OLTAdapter{}
-	a.coreProxy = cp
-	return a
+	return &OLTAdapter{
+		flows: map[uint64]*voltha.OfpFlowStats{},
+		Adapter: Adapter{
+			coreProxy: cp,
+		},
+	}
 }
 
 // Adopt_device creates new handler for added device
@@ -97,7 +104,7 @@
 		}
 
 		// Register Child devices
-		initialUniPortNo := 100
+		initialUniPortNo := startingUNIPortNo
 		for i := 0; i < numONUPerOLT; i++ {
 			go func(seqNo int) {
 				if _, err := oltA.coreProxy.ChildDeviceDetected(
@@ -168,6 +175,11 @@
 	return numONUPerOLT
 }
 
+// Returns the starting UNI port number
+func (oltA *OLTAdapter) GetStartingUNIPortNo() int {
+	return startingUNIPortNo
+}
+
 // Disable_device disables device
 func (oltA *OLTAdapter) Disable_device(device *voltha.Device) error { // nolint
 	go func() {
@@ -261,3 +273,37 @@
 func (oltA *OLTAdapter) Child_device_lost(deviceID string, pPortNo uint32, onuID uint32) error { // nolint
 	return nil
 }
+
+// Update_flows_incrementally mocks the incremental flow update
+func (oltA *OLTAdapter) Update_flows_incrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error { // nolint
+	oltA.lock.Lock()
+	defer oltA.lock.Unlock()
+
+	if flows.ToAdd != nil {
+		for _, f := range flows.ToAdd.Items {
+			oltA.flows[f.Id] = f
+		}
+	}
+	if flows.ToRemove != nil {
+		for _, f := range flows.ToRemove.Items {
+			delete(oltA.flows, f.Id)
+		}
+	}
+	return nil
+}
+
+// GetFlowCount returns the total number of flows presently under this adapter
+func (oltA *OLTAdapter) GetFlowCount() int {
+	oltA.lock.Lock()
+	defer oltA.lock.Unlock()
+
+	return len(oltA.flows)
+}
+
+// ClearFlows removes all flows in this adapter
+func (oltA *OLTAdapter) ClearFlows() {
+	oltA.lock.Lock()
+	defer oltA.lock.Unlock()
+
+	oltA.flows = map[uint64]*voltha.OfpFlowStats{}
+}