import (
"fmt"
+ "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
"gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
"strconv"
"sync"
+ "time"
)
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
type Subscription struct {
- mutex sync.Mutex
- Seq uint16
- Active bool
- //
- Meid *xapp.RMRMeid
- RmrEndpoint // xapp endpoint. Now only one xapp can have relation to single subscription. To be changed in merge
- Trans *Transaction
+ mutex sync.Mutex // Lock
+ registry *Registry // Registry
+ Seq uint16 // SubsId
+ Meid *xapp.RMRMeid // Meid/ RanName
+ EpList RmrEndpointList // Endpoints
+ DelEpList RmrEndpointList // Endpoints
+ DelSeq uint64
+ TransLock sync.Mutex // Lock transactions, only one executed per time for subs
+ TheTrans *Transaction // Ongoing transaction from xapp
+ SubReqMsg *e2ap.E2APSubscriptionRequest // Subscription information
+ SubRespMsg *e2ap.E2APSubscriptionResponse // Subscription information
+}
+
+func (s *Subscription) stringImpl() string {
+ return "subs(" + strconv.FormatUint(uint64(s.Seq), 10) + "/" + s.Meid.RanName + "/" + s.EpList.String() + ")"
}
func (s *Subscription) String() string {
s.mutex.Lock()
defer s.mutex.Unlock()
- return strconv.FormatUint(uint64(s.Seq), 10) + "/" + s.RmrEndpoint.String() + "/" + s.Meid.RanName
+ return s.stringImpl()
}
-func (s *Subscription) Confirmed() {
+func (s *Subscription) GetSubId() uint16 {
s.mutex.Lock()
defer s.mutex.Unlock()
- s.Active = true
+ return s.Seq
}
-func (s *Subscription) UnConfirmed() {
+func (s *Subscription) GetMeid() *xapp.RMRMeid {
s.mutex.Lock()
defer s.mutex.Unlock()
- s.Active = false
+ if s.Meid != nil {
+ return s.Meid
+ }
+ return nil
}
-func (s *Subscription) IsConfirmed() bool {
+func (s *Subscription) AddEndpoint(ep *RmrEndpoint) error {
s.mutex.Lock()
defer s.mutex.Unlock()
- return s.Active
+ if ep == nil {
+ return fmt.Errorf("AddEndpoint no endpoint given")
+ }
+ if s.EpList.AddEndpoint(ep) {
+ s.DelEpList.DelEndpoint(ep)
+ if s.EpList.Size() == 1 {
+ return s.updateRouteImpl(CREATE)
+ }
+ return s.updateRouteImpl(MERGE)
+ }
+ return nil
}
-func (s *Subscription) SetTransaction(trans *Transaction) error {
+func (s *Subscription) DelEndpoint(ep *RmrEndpoint) error {
s.mutex.Lock()
defer s.mutex.Unlock()
+ var err error
+ if ep == nil {
+ return fmt.Errorf("DelEndpoint no endpoint given")
+ }
+ if s.EpList.HasEndpoint(ep) == false {
+ return fmt.Errorf("DelEndpoint endpoint not found")
+ }
+ if s.DelEpList.HasEndpoint(ep) == true {
+ return fmt.Errorf("DelEndpoint endpoint already under del")
+ }
+ s.DelEpList.AddEndpoint(ep)
+ go s.CleanCheck()
+ return err
+}
- subString := strconv.FormatUint(uint64(s.Seq), 10) + "/" + s.RmrEndpoint.String() + "/" + s.Meid.RanName
-
- if (s.RmrEndpoint.Addr != trans.RmrEndpoint.Addr) || (s.RmrEndpoint.Port != trans.RmrEndpoint.Port) {
- return fmt.Errorf("Subscription: %s endpoint mismatch with trans: %s", subString, trans)
+func (s *Subscription) CleanCheck() {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+ s.DelSeq++
+ // Only one clean ongoing
+ if s.DelSeq > 1 {
+ return
}
- if s.Trans != nil {
- return fmt.Errorf("Subscription: %s trans %s exist, can not register %s", subString, s.Trans, trans)
+ var currSeq uint64 = 0
+ // Make sure that routes to be deleted
+ // are not deleted too fast
+ for currSeq < s.DelSeq {
+ currSeq = s.DelSeq
+ s.mutex.Unlock()
+ time.Sleep(5 * time.Second)
+ s.mutex.Lock()
}
- trans.Subs = s
- s.Trans = trans
- return nil
+ xapp.Logger.Info("DelEndpoint: delete cleaning %s", s.stringImpl())
+ if s.EpList.Size() <= s.DelEpList.Size() {
+ s.updateRouteImpl(DELETE)
+ go s.registry.DelSubscription(s.Seq)
+ } else if s.EpList.DelEndpoints(&s.DelEpList) {
+ s.updateRouteImpl(MERGE)
+ }
+ s.DelSeq = 0
+
}
-func (s *Subscription) UnSetTransaction(trans *Transaction) bool {
+func (s *Subscription) IsTransactionReserved() bool {
s.mutex.Lock()
defer s.mutex.Unlock()
- if trans == nil || trans == s.Trans {
- s.Trans = nil
+ if s.TheTrans != nil {
return true
}
return false
+
}
func (s *Subscription) GetTransaction() *Transaction {
s.mutex.Lock()
defer s.mutex.Unlock()
- return s.Trans
+ return s.TheTrans
}
-func (s *Subscription) UpdateRoute(act Action, rtmgrClient *RtmgrClient) error {
+func (s *Subscription) WaitTransactionTurn(trans *Transaction) {
+ s.TransLock.Lock()
s.mutex.Lock()
- defer s.mutex.Unlock()
- xapp.Logger.Info("Subscription: Starting routing manager route add. SubId: %d, RmrEndpoint: %s", s.Seq, s.RmrEndpoint)
- subRouteAction := SubRouteInfo{act, s.RmrEndpoint.Addr, s.RmrEndpoint.Port, s.Seq}
- err := rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
+ s.TheTrans = trans
+ s.mutex.Unlock()
+}
+
+func (s *Subscription) ReleaseTransactionTurn(trans *Transaction) {
+ s.mutex.Lock()
+ if trans != nil && trans == s.TheTrans {
+ s.TheTrans = nil
+ }
+ s.mutex.Unlock()
+ s.TransLock.Unlock()
+}
+
+func (s *Subscription) updateRouteImpl(act Action) error {
+ subRouteAction := SubRouteInfo{act, s.EpList, s.Seq}
+ err := s.registry.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
if err != nil {
- return fmt.Errorf("Subscription: Failed to add route. SubId: %d, RmrEndpoint: %s", s.Seq, s.RmrEndpoint)
+ return fmt.Errorf("%s %s", s.stringImpl(), err.Error())
}
return nil
}