general update for library compatibility, [VOL-3202], some TechProf processing restructuring

Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I451c663fea4dc3ea5acd141069e64a1ad2a68d58
diff --git a/internal/pkg/onuadaptercore/onu_uni_tp.go b/internal/pkg/onuadaptercore/onu_uni_tp.go
new file mode 100644
index 0000000..1539b9a
--- /dev/null
+++ b/internal/pkg/onuadaptercore/onu_uni_tp.go
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 adaptercoreonu provides the utility for onu devices, flows and statistics
+package adaptercoreonu
+
+import (
+	"context"
+	"encoding/json"
+	"sync"
+
+	"github.com/opencord/voltha-lib-go/v3/pkg/db"
+	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
+	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
+)
+
+const cBasePathTechProfileKVStore = "service/voltha/technology_profiles"
+
+type resourceEntry int
+
+const (
+	cResourceGemPort resourceEntry = 1
+	cResourceTcont   resourceEntry = 2
+)
+
+type onuSerialNumber struct {
+	sliceVendorID       []byte
+	sliceVendorSpecific []byte
+}
+
+type onuPersistentData struct {
+	persOnuID      uint32
+	persIntfID     uint32
+	persSnr        onuSerialNumber
+	persAdminState string
+	persOperState  string
+	persUniTpPath  map[uint32]string
+	persUniTpData  map[uint32]tp.TechProfile
+}
+
+//OnuUniTechProf structure holds information about the TechProfiles attached to Uni Ports of the ONU
+type OnuUniTechProf struct {
+	deviceID           string
+	baseDeviceHandler  *DeviceHandler
+	tpProcMutex        sync.RWMutex
+	sOnuPersistentData onuPersistentData
+	techProfileKVStore *db.Backend
+}
+
+//NewOnuUniTechProf returns the instance of a OnuUniTechProf
+//(one instance per ONU/deviceHandler for all possible UNI's)
+func NewOnuUniTechProf(ctx context.Context, aDeviceID string, aDeviceHandler *DeviceHandler) *OnuUniTechProf {
+	logger.Infow("init-OnuUniTechProf", log.Fields{"deviceId": aDeviceID})
+	var onuTP OnuUniTechProf
+	onuTP.deviceID = aDeviceID
+	onuTP.baseDeviceHandler = aDeviceHandler
+	onuTP.tpProcMutex = sync.RWMutex{}
+	onuTP.sOnuPersistentData.persUniTpPath = make(map[uint32]string)
+	onuTP.sOnuPersistentData.persUniTpData = make(map[uint32]tp.TechProfile)
+
+	onuTP.techProfileKVStore = aDeviceHandler.SetBackend(cBasePathTechProfileKVStore)
+	if onuTP.techProfileKVStore == nil {
+		logger.Errorw("Can't access techProfileKVStore - no backend connection to service",
+			log.Fields{"deviceID": aDeviceID, "service": cBasePathTechProfileKVStore})
+	}
+	return &onuTP
+}
+
+// lockTpProcMutex locks OnuUniTechProf processing mutex
+func (onuTP *OnuUniTechProf) lockTpProcMutex() {
+	onuTP.tpProcMutex.Lock()
+}
+
+// unlockTpProcMutex unlocks OnuUniTechProf processing mutex
+func (onuTP *OnuUniTechProf) unlockTpProcMutex() {
+	onuTP.tpProcMutex.Unlock()
+}
+
+// updateOnuUniTpPath verifies and updates changes in the kvStore onuUniTpPath
+func (onuTP *OnuUniTechProf) updateOnuUniTpPath(aUniID uint32, aPathString string) bool {
+	/* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
+	   as also the complete sequence is ensured to 'run to  completion' before some new request is accepted
+	   no specific concurrency protection to sOnuPersistentData is required here
+	*/
+	if existingPath, present := onuTP.sOnuPersistentData.persUniTpPath[aUniID]; present {
+		// uni entry already exists
+		//logger.Debugw(" already exists", log.Fields{"for InstanceId": a_uniInstNo})
+		if existingPath != aPathString {
+			if aPathString == "" {
+				//existing entry to be deleted
+				logger.Debugw("UniTp path delete", log.Fields{
+					"deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
+				delete(onuTP.sOnuPersistentData.persUniTpPath, aUniID)
+			} else {
+				//existing entry to be modified
+				logger.Debugw("UniTp path modify", log.Fields{
+					"deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
+				onuTP.sOnuPersistentData.persUniTpPath[aUniID] = aPathString
+			}
+			return true
+		}
+		//entry already exists
+		logger.Debugw("UniTp path already exists", log.Fields{
+			"deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
+		return false
+	}
+	//uni entry does not exist
+	if aPathString == "" {
+		//delete request in non-existing state , accept as no change
+		logger.Debugw("UniTp path already removed", log.Fields{
+			"deviceID": onuTP.deviceID, "uniID": aUniID})
+		return false
+	}
+	//new entry to be set
+	logger.Debugw("New UniTp path set", log.Fields{
+		"deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
+	onuTP.sOnuPersistentData.persUniTpPath[aUniID] = aPathString
+	return true
+}
+
+func (onuTP *OnuUniTechProf) configureUniTp(aUniID uint32, aPathString string, wg *sync.WaitGroup) {
+	defer wg.Done()
+	logger.Debugw("configure the Uni according to TpPath", log.Fields{
+		"deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
+
+	//TODO!!!
+	// reaction on existing tp, deletion of tp, start the corresponding OMCI configuation of the UNI port
+
+	if onuTP.techProfileKVStore == nil {
+		logger.Debug("techProfileKVStore not set - abort")
+		return
+	}
+
+	Value, err := onuTP.techProfileKVStore.Get(context.TODO(), aPathString)
+	if err == nil {
+		if Value != nil {
+			logger.Debugw("tech-profile read",
+				log.Fields{"Key": Value.Key, "Value": Value.Value})
+			tpTmpBytes, _ := kvstore.ToByte(Value.Value)
+
+			var tpInst tp.TechProfile
+			if err = json.Unmarshal(tpTmpBytes, &tpInst); err != nil {
+				logger.Errorw("TechProf - Failed to unmarshal tech-profile into tpInst",
+					log.Fields{"error": err, "device-id": onuTP.deviceID})
+			} else {
+				logger.Debugw("TechProf - tpInst", log.Fields{"tpInst": tpInst})
+				onuTP.sOnuPersistentData.persUniTpData[aUniID] = tpInst
+
+				// access examples
+				logger.Debugw("TechProf - name",
+					log.Fields{"onuTP.sOnuPersistentData.persUniTpData[aUniID].Name": onuTP.sOnuPersistentData.persUniTpData[aUniID].Name})
+				//
+				logger.Debugw("TechProf - instance_control.max_gem_payload_size",
+					log.Fields{"onuTP.sOnuPersistentData.persUniTpData[aUniID].InstanceCtrl.MaxGemPayloadSize": onuTP.sOnuPersistentData.persUniTpData[aUniID].InstanceCtrl.MaxGemPayloadSize})
+				//
+				logger.Debugw("TechProf - downstream_gem_port_attribute_list.discard_config.max_threshold",
+					log.Fields{"onuTP.sOnuPersistentData.persUniTpData[aUniID].DownstreamGemPortAttributeList[0].DiscardConfig.MaxThreshold": onuTP.sOnuPersistentData.persUniTpData[aUniID].DownstreamGemPortAttributeList[0].DiscardConfig.MaxThreshold})
+			}
+		} else {
+			logger.Debugw("No tech-profile found", log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
+		}
+	} else {
+		logger.Errorw("kvstore-get failed for path",
+			log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
+	}
+}
+
+func (onuTP *OnuUniTechProf) updateOnuTpPathKvStore(wg *sync.WaitGroup) {
+	defer wg.Done()
+	logger.Debugw("this would update the ONU's TpPath in KVStore", log.Fields{
+		"deviceID": onuTP.deviceID})
+	//TODO!!!
+	//make use of onuTP.sOnuPersistentData to store the TpPath to KVStore
+}
+
+// deleteTpRessource removes ressources from the ONU's specified Uni
+func (onuTP *OnuUniTechProf) deleteTpRessource(aUniID uint32, aPathString string,
+	aRessource resourceEntry, aEntryID uint32, wg *sync.WaitGroup) {
+	defer wg.Done()
+	logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
+		"deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "ressource": aRessource})
+	//TODO!!!
+}
+
+func (onuTP *OnuUniTechProf) waitForTpCompletion(wg *sync.WaitGroup) {
+	wg.Wait()
+	logger.Debug("some TechProfile Processing completed")
+	onuTP.tpProcMutex.Unlock() //allow further TP related processing
+}