blob: 8b7dcdc18bb48cbf0aac3c25aa75d18a36c0e0ad [file] [log] [blame]
Markku Virtanenb642a192021-06-09 09:08:14 +00001/*
2==================================================================================
3 Copyright (c) 2021 Nokia
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16==================================================================================
17*/
18
19package control
20
21import (
22 "bytes"
23 "crypto/md5"
24 "encoding/gob"
25 "encoding/hex"
26 "fmt"
27 "sync"
28 "time"
29
30 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
31)
32
Anssi Mannila3cdd2e02021-10-14 12:35:41 +030033type RetransEntry struct {
Markku Virtanenb642a192021-06-09 09:08:14 +000034 restSubsId string
35 startTime time.Time
36}
37
Anssi Mannila3cdd2e02021-10-14 12:35:41 +030038type DuplicateCtrl struct {
Markku Virtanen42723e22021-06-15 10:09:23 +030039 mutex sync.Mutex
Anssi Mannila3cdd2e02021-10-14 12:35:41 +030040 ongoingRequestMap map[string]RetransEntry
Markku Virtanen42723e22021-06-15 10:09:23 +030041 previousRequestMap map[string]string
42 collCount int
Markku Virtanenb642a192021-06-09 09:08:14 +000043}
44
Anssi Mannila3cdd2e02021-10-14 12:35:41 +030045func (d *DuplicateCtrl) Init() {
46 d.ongoingRequestMap = make(map[string]RetransEntry)
Markku Virtanen42723e22021-06-15 10:09:23 +030047 d.previousRequestMap = make(map[string]string)
Markku Virtanenb642a192021-06-09 09:08:14 +000048}
49
Anssi Mannila3cdd2e02021-10-14 12:35:41 +030050func (d *DuplicateCtrl) SetMd5sumFromLastOkRequest(restSubsId string, md5sum string) {
Markku Virtanenb642a192021-06-09 09:08:14 +000051
Markku Virtanen42723e22021-06-15 10:09:23 +030052 d.mutex.Lock()
53 defer d.mutex.Unlock()
54
55 if md5sum == "" {
56 xapp.Logger.Error("Attempt to store empty md5sum for restubsId %s retransmission map skipped", restSubsId)
57 return
58 }
59
Anssi Mannila9c4697f2022-07-04 15:51:38 +030060 err := d.removeOngoingTransaction(md5sum)
61 if err != nil {
62 xapp.Logger.Error("removeOngoingTransaction() failed:%s", err.Error())
63 }
Markku Virtanen42723e22021-06-15 10:09:23 +030064
65 prevRestSubsId, exists := d.previousRequestMap[md5sum]
66
67 if exists {
68 if prevRestSubsId != restSubsId {
69 xapp.Logger.Error("Storing md5sum for a processed request for restSubsId %s md5sum %s over a previous restSubsId %s", restSubsId, md5sum, prevRestSubsId)
70 } else {
71 return
72 }
73 } else {
74 xapp.Logger.Debug("Storing md5sum for a processed request for restSubsId %s md5sum %s", restSubsId, md5sum)
75 }
76
77 d.previousRequestMap[md5sum] = restSubsId
78}
79
Anssi Mannila3cdd2e02021-10-14 12:35:41 +030080func (d *DuplicateCtrl) GetLastKnownRestSubsIdBasedOnMd5sum(md5sum string) (string, bool) {
Markku Virtanen42723e22021-06-15 10:09:23 +030081
82 d.mutex.Lock()
83 defer d.mutex.Unlock()
84
85 if md5sum == "" {
86 return "", false
87 }
88
89 m, e := d.previousRequestMap[md5sum]
90
91 return m, e
92}
93
Anssi Mannila3cdd2e02021-10-14 12:35:41 +030094func (d *DuplicateCtrl) DeleteLastKnownRestSubsIdBasedOnMd5sum(md5sum string) {
Markku Virtanen42723e22021-06-15 10:09:23 +030095
96 d.mutex.Lock()
97 defer d.mutex.Unlock()
98
99 restSubsId, exists := d.previousRequestMap[md5sum]
100
101 if !exists {
102 if md5sum == "" {
Anssi Mannilaf682ace2021-09-28 13:11:25 +0300103 xapp.Logger.Debug("Attempted to delete a cached md5sum, md5sum not set yet")
Markku Virtanen42723e22021-06-15 10:09:23 +0300104 } else {
105 xapp.Logger.Error("Attempted to delete a cached md5sum %s, but the value was not found", md5sum)
106 }
107 } else {
108 xapp.Logger.Debug("Deleted a cached md5sum %s for restSubsId %s", md5sum, restSubsId)
109 delete(d.previousRequestMap, md5sum)
110 }
111}
112
113func CalculateRequestMd5sum(payload interface{}) (string, error) {
Markku Virtanenb642a192021-06-09 09:08:14 +0000114 var data bytes.Buffer
115 enc := gob.NewEncoder(&data)
116
117 if err := enc.Encode(payload); err != nil {
Markku Virtanen42723e22021-06-15 10:09:23 +0300118 xapp.Logger.Error("%s", err.Error())
119 return "", err
Markku Virtanenb642a192021-06-09 09:08:14 +0000120 }
121
122 hash := md5.Sum(data.Bytes())
123
Markku Virtanen42723e22021-06-15 10:09:23 +0300124 return hex.EncodeToString(hash[:]), nil
125}
126
Anssi Mannila3cdd2e02021-10-14 12:35:41 +0300127func (d *DuplicateCtrl) IsDuplicateToOngoingTransaction(restSubsId string, md5sum string) bool {
Markku Virtanen42723e22021-06-15 10:09:23 +0300128
129 if md5sum == "" {
130 return false
131 }
Markku Virtanenb642a192021-06-09 09:08:14 +0000132
133 d.mutex.Lock()
134 defer d.mutex.Unlock()
135
Markku Virtanen42723e22021-06-15 10:09:23 +0300136 entry, present := d.ongoingRequestMap[md5sum]
Markku Virtanenb642a192021-06-09 09:08:14 +0000137
138 if present {
Anssi Mannilaf682ace2021-09-28 13:11:25 +0300139 xapp.Logger.Debug("Collision detected. REST subs ID %s has ongoing transaction with md5sum : %s started at %s\n", entry.restSubsId, md5sum, entry.startTime.Format(time.ANSIC))
Markku Virtanenb642a192021-06-09 09:08:14 +0000140 d.collCount++
Markku Virtanen42723e22021-06-15 10:09:23 +0300141 return true
Markku Virtanenb642a192021-06-09 09:08:14 +0000142 }
143
Anssi Mannila3cdd2e02021-10-14 12:35:41 +0300144 entry = RetransEntry{restSubsId: restSubsId, startTime: time.Now()}
Markku Virtanenb642a192021-06-09 09:08:14 +0000145
Markku Virtanen42723e22021-06-15 10:09:23 +0300146 xapp.Logger.Debug("No collision detected against ongoing transaction. Added md5sum %s for restSubsId %s at %s\n", md5sum, entry.restSubsId, entry.startTime)
Markku Virtanenb642a192021-06-09 09:08:14 +0000147
Markku Virtanen42723e22021-06-15 10:09:23 +0300148 d.ongoingRequestMap[md5sum] = entry
Markku Virtanenb642a192021-06-09 09:08:14 +0000149
Markku Virtanen42723e22021-06-15 10:09:23 +0300150 return false
Markku Virtanenb642a192021-06-09 09:08:14 +0000151}
152
Anssi Mannila3cdd2e02021-10-14 12:35:41 +0300153func (d *DuplicateCtrl) TransactionComplete(md5sum string) error {
Markku Virtanenb642a192021-06-09 09:08:14 +0000154
Markku Virtanen42723e22021-06-15 10:09:23 +0300155 if md5sum == "" {
156 return nil
157 }
158
Markku Virtanenb642a192021-06-09 09:08:14 +0000159 d.mutex.Lock()
160 defer d.mutex.Unlock()
161
Markku Virtanen42723e22021-06-15 10:09:23 +0300162 return d.removeOngoingTransaction(md5sum)
163}
164
Anssi Mannila3cdd2e02021-10-14 12:35:41 +0300165func (d *DuplicateCtrl) removeOngoingTransaction(md5sum string) error {
Markku Virtanen42723e22021-06-15 10:09:23 +0300166
167 entry, present := d.ongoingRequestMap[md5sum]
Markku Virtanenb642a192021-06-09 09:08:14 +0000168
169 if !present {
Markku Virtanen42723e22021-06-15 10:09:23 +0300170 xapp.Logger.Error("md5sum : %s NOT found from retransmission table", md5sum)
171 return fmt.Errorf("Retransmission entry not found for md5sum %s", md5sum)
Markku Virtanenb642a192021-06-09 09:08:14 +0000172 }
173
Markku Virtanen42723e22021-06-15 10:09:23 +0300174 xapp.Logger.Debug("Releasing transaction duplicate blocker for %s, md5sum : %s\n", entry.restSubsId, md5sum)
Markku Virtanenb642a192021-06-09 09:08:14 +0000175
Markku Virtanen42723e22021-06-15 10:09:23 +0300176 delete(d.ongoingRequestMap, md5sum)
Markku Virtanenb642a192021-06-09 09:08:14 +0000177
178 return nil
179}