Submgr restart improvement

Change-Id: I02388dea48b826eac09aec0308d85bcdcf812a6f
Signed-off-by: Anssi Mannila <anssi.mannila@nokia.com>
diff --git a/pkg/control/sdl.go b/pkg/control/sdl.go
new file mode 100644
index 0000000..3a083fb
--- /dev/null
+++ b/pkg/control/sdl.go
@@ -0,0 +1,229 @@
+/*
+==================================================================================
+  Copyright (c) 2019 AT&T Intellectual Property.
+  Copyright (c) 2019 Nokia
+
+   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 control
+
+import (
+	"encoding/json"
+	"fmt"
+	"gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
+	sdl "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
+	"gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
+	"strconv"
+)
+
+type SubscriptionInfo struct {
+	Valid       bool
+	ReqId       RequestId
+	Meid        xapp.RMRMeid
+	EpList      xapp.RmrEndpointList
+	SubReqMsg   e2ap.E2APSubscriptionRequest
+	SubRespMsg  e2ap.E2APSubscriptionResponse
+	SubFailMsg  e2ap.E2APSubscriptionFailure
+	SubRespRcvd string
+}
+
+func CreateSdl() Sdlnterface {
+	return sdl.NewSdlInstance("submgr", sdl.NewDatabase())
+}
+
+func (c *Control) WriteSubscriptionToSdl(subId uint32, subs *Subscription) error {
+
+	var subscriptionInfo SubscriptionInfo
+	subscriptionInfo.Valid = subs.valid
+	subscriptionInfo.ReqId = subs.ReqId
+	subscriptionInfo.Meid = *subs.Meid
+	subscriptionInfo.EpList = subs.EpList
+	subscriptionInfo.SubReqMsg = *subs.SubReqMsg
+
+	if typeofSubsMessage(subs.SubRFMsg) == "SubResp" {
+		subscriptionInfo.SubRespRcvd = "SubResp"
+		subscriptionInfo.SubRespMsg = *subs.SubRFMsg.(*e2ap.E2APSubscriptionResponse)
+	} else if typeofSubsMessage(subs.SubRFMsg) == "SubFail" {
+		subscriptionInfo.SubRespRcvd = "SubFail"
+		subscriptionInfo.SubFailMsg = *subs.SubRFMsg.(*e2ap.E2APSubscriptionFailure)
+	} else {
+		subscriptionInfo.SubRespRcvd = ""
+	}
+
+	jsonData, err := json.Marshal(subscriptionInfo)
+	if err != nil {
+		return fmt.Errorf("SDL: WriteSubscriptionToSdl() json.Marshal error: %s", err.Error())
+	}
+
+	err = c.db.Set(strconv.FormatUint(uint64(subId), 10), jsonData)
+	if err != nil {
+		return fmt.Errorf("SDL: WriteSubscriptionToSdl(): %s", err.Error())
+	} else {
+		xapp.Logger.Debug("SDL: Subscription written in db. subId = %v", subId)
+	}
+	return nil
+}
+
+func (c *Control) ReadSubscriptionFromSdl(subId uint32) (*Subscription, error) {
+
+	// This function is now just for testing purpose
+	key := strconv.FormatUint(uint64(subId), 10)
+	retMap, err := c.db.Get([]string{key})
+	if err != nil {
+		return nil, fmt.Errorf("SDL: ReadSubscriptionFromSdl(): %s", err.Error())
+	} else {
+		xapp.Logger.Debug("SDL: Subscription read from db.  subId = %v", subId)
+	}
+
+	subs := &Subscription{}
+	for _, iSubscriptionInfo := range retMap {
+
+		if iSubscriptionInfo == nil {
+			return nil, fmt.Errorf("SDL: ReadSubscriptionFromSdl() subscription not found. subId = %v\n", subId)
+		}
+
+		subscriptionInfo := &SubscriptionInfo{}
+		jsonSubscriptionInfo := iSubscriptionInfo.(string)
+
+		err := json.Unmarshal([]byte(jsonSubscriptionInfo), subscriptionInfo)
+		if err != nil {
+			return nil, fmt.Errorf("SDL: ReadSubscriptionFromSdl() json.unmarshal error: %s\n", err.Error())
+		}
+
+		subs = c.CreateSubscription(subscriptionInfo, &jsonSubscriptionInfo)
+	}
+	return subs, nil
+}
+
+func (c *Control) CreateSubscription(subscriptionInfo *SubscriptionInfo, jsonSubscriptionInfo *string) *Subscription {
+
+	subs := &Subscription{}
+	subs.registry = c.registry
+	subs.valid = subscriptionInfo.Valid
+	subs.ReqId = subscriptionInfo.ReqId
+	meid := xapp.RMRMeid{}
+	meid = subscriptionInfo.Meid
+	subs.Meid = &meid
+	subs.EpList = subscriptionInfo.EpList
+	subs.TheTrans = nil
+	subReq := e2ap.E2APSubscriptionRequest{}
+	subReq = subscriptionInfo.SubReqMsg
+	subs.SubReqMsg = &subReq
+
+	if subscriptionInfo.SubRespRcvd == "SubResp" {
+		subs.SubRespRcvd = true
+		subResp := e2ap.E2APSubscriptionResponse{}
+		subResp = subscriptionInfo.SubRespMsg
+		subs.SubRFMsg = &subResp
+	} else if subscriptionInfo.SubRespRcvd == "SubFail" {
+		subs.SubRespRcvd = false
+		subFail := e2ap.E2APSubscriptionFailure{}
+		subFail = subscriptionInfo.SubFailMsg
+		subs.SubRFMsg = &subFail
+	} else {
+		subs.SubRespRcvd = false
+		subs.SubRFMsg = nil
+		xapp.Logger.Debug("SDL: CreateSubscription() subscriptionInfo.SubRespRcvd == '', InstanceId=%v ", subscriptionInfo.ReqId.InstanceId)
+	}
+	return subs
+}
+
+func (c *Control) RemoveSubscriptionFromSdl(subId uint32) error {
+
+	key := strconv.FormatUint(uint64(subId), 10)
+	err := c.db.Remove([]string{key})
+	if err != nil {
+		return fmt.Errorf("SDL: RemoveSubscriptionfromSdl(): %s\n", err.Error())
+	} else {
+		xapp.Logger.Debug("SDL: Subscription removed from db. subId = %v", subId)
+	}
+	return nil
+}
+
+func (c *Control) ReadAllSubscriptionsFromSdl() ([]uint32, map[uint32]*Subscription, error) {
+
+	// Read all subscriptionInfos
+	var subIds []uint32
+	var i uint32
+	for i = 1; i < 65535; i++ {
+		subIds = append(subIds, i)
+	}
+
+	retMap := make(map[uint32]*Subscription)
+	// Get all keys
+	keys, err := c.db.GetAll()
+	if err != nil {
+		return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), GetAll(). Error while reading keys from DBAAS %s\n", err.Error())
+	}
+
+	if len(keys) == 0 {
+		return subIds, retMap, nil
+	}
+
+	// Get all subscriptionInfos
+	iSubscriptionMap, err := c.db.Get(keys)
+	if err != nil {
+		return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), Get():  Error while reading subscriptions from DBAAS %s\n", err.Error())
+	}
+
+	for _, iSubscriptionInfo := range iSubscriptionMap {
+
+		if iSubscriptionInfo == nil {
+			return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl() iSubscriptionInfo = nil\n")
+		}
+
+		subscriptionInfo := &SubscriptionInfo{}
+		jsonSubscriptionInfo := iSubscriptionInfo.(string)
+
+		err := json.Unmarshal([]byte(jsonSubscriptionInfo), subscriptionInfo)
+		if err != nil {
+			return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl() json.unmarshal error: %s\n", err.Error())
+		}
+
+		subs := c.CreateSubscription(subscriptionInfo, &jsonSubscriptionInfo)
+
+		if int(subscriptionInfo.ReqId.InstanceId) >= len(subIds) {
+			return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl() index is out of range. Index is %d with slice length %d", subscriptionInfo.ReqId.InstanceId, len(subIds))
+		}
+		retMap[subscriptionInfo.ReqId.InstanceId] = subs
+
+		// Remove subId from free subIds. Original slice is modified here!
+		subIds, err = removeNumber(subIds, subscriptionInfo.ReqId.InstanceId)
+		if err != nil {
+			return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl() error: %s\n", err.Error())
+		}
+	}
+	return subIds, retMap, nil
+}
+
+func removeNumber(s []uint32, removedNum uint32) ([]uint32, error) {
+	for i, num := range s {
+		if removedNum == uint32(num) {
+			s = append(s[:i], s[i+1:]...)
+			return s[:len(s)], nil
+		}
+	}
+	return nil, fmt.Errorf("SDL: To be removed number not in the slice. removedNum: %v", removedNum)
+}
+func (c *Control) RemoveAllSubscriptionsFromSdl() error {
+
+	err := c.db.RemoveAll()
+	if err != nil {
+		return fmt.Errorf("SDL: RemoveAllSubscriptionsFromSdl(): %s\n", err.Error())
+	} else {
+		xapp.Logger.Debug("SDL: All subscriptions removed from db")
+	}
+	return nil
+}