Skip to content

Commit 4aa0899

Browse files
authored
CVL Changes sonic-net#9: Clean up CVL code and integrate custom xpath engine for leafref, when, must expression evaluation (sonic-net#33)
Clean up CVL code YIN schema reading using libyang API Integrate with xpath custom engine for leafref, when, must expression evaluation Add delete constraint check Add max-element constraint Add CVL trace log to /tmp/cvl.log based on config file
1 parent 86c1108 commit 4aa0899

10 files changed

+1493
-1518
lines changed

cvl/cvl.go

+350-957
Large diffs are not rendered by default.

cvl/cvl_api.go

+209-167
Large diffs are not rendered by default.

cvl/cvl_cache.go

+77-28
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,30 @@
2020
package cvl
2121
import (
2222
"encoding/json"
23-
"github.com/go-redis/redis"
23+
"github.com/go-redis/redis/v7"
2424
//lint:ignore ST1001 This is safe to dot import for util package
2525
. "github.com/Azure/sonic-mgmt-common/cvl/internal/util"
2626
"github.com/Azure/sonic-mgmt-common/cvl/internal/yparser"
2727
"time"
2828
"runtime"
2929
"github.com/antchfx/jsonquery"
30+
"github.com/antchfx/xmlquery"
3031
)
3132

33+
func (c *CVL) addTableEntryToCache(tableName string, redisKey string) {
34+
if (tableName == "" || redisKey == "") {
35+
return
36+
}
37+
38+
if (c.tmpDbCache[tableName] == nil) {
39+
c.tmpDbCache[tableName] = map[string]interface{}{redisKey: nil}
40+
} else {
41+
tblMap := c.tmpDbCache[tableName]
42+
tblMap.(map[string]interface{})[redisKey] =nil
43+
c.tmpDbCache[tableName] = tblMap
44+
}
45+
}
46+
3247
// Fetch dependent data from validated data cache,
3348
// Returns the data and flag to indicate that if requested data
3449
// is found in update request, the data should be merged with Redis data
@@ -37,20 +52,18 @@ func (c *CVL) fetchDataFromRequestCache(tableName string, key string) (d map[str
3752
pd := &d
3853
pm := &m
3954

40-
TRACE_LOG(INFO_API, TRACE_CACHE,
55+
TRACE_LOG(TRACE_CACHE,
4156
"Returning data from request cache, data = %v, merge needed = %v",
4257
*pd, *pm)
4358
}()
4459

4560
cfgDataArr := c.requestCache[tableName][key]
46-
if (cfgDataArr != nil) {
47-
for _, cfgReqData := range cfgDataArr {
48-
//Delete request doesn't have depedent data
49-
if (cfgReqData.reqData.VOp == OP_CREATE) {
50-
return cfgReqData.reqData.Data, false
51-
} else if (cfgReqData.reqData.VOp == OP_UPDATE) {
52-
return cfgReqData.reqData.Data, true
53-
}
61+
for _, cfgReqData := range cfgDataArr {
62+
//Delete request doesn't have depedent data
63+
if (cfgReqData.reqData.VOp == OP_CREATE) {
64+
return cfgReqData.reqData.Data, false
65+
} else if (cfgReqData.reqData.VOp == OP_UPDATE) {
66+
return cfgReqData.reqData.Data, true
5467
}
5568
}
5669

@@ -60,7 +73,7 @@ func (c *CVL) fetchDataFromRequestCache(tableName string, key string) (d map[str
6073
//Fetch given table entries using pipeline
6174
func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]interface{}) int {
6275

63-
TRACE_LOG(INFO_API, TRACE_CACHE, "\n%v, Entered fetchTableDataToTmpCache", time.Now())
76+
TRACE_LOG(TRACE_CACHE, "\n%v, Entered fetchTableDataToTmpCache", time.Now())
6477

6578
totalCount := len(dbKeys)
6679
if (totalCount == 0) {
@@ -102,25 +115,27 @@ func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]inter
102115
redisKey := tableName + modelInfo.tableInfo[tableName].redisKeyDelim + dbKey
103116
//Check in validated cache first and add as dependent data
104117
if entry, mergeNeeded := c.fetchDataFromRequestCache(tableName, dbKey); (entry != nil) {
105-
c.tmpDbCache[tableName].(map[string]interface{})[dbKey] = entry
106-
entryFetched = entryFetched + 1
107-
//Entry found in validated cache, so skip fetching from Redis
108-
//if merging is not required with Redis DB
109-
if (mergeNeeded == false) {
110-
continue
111-
}
118+
entryFetched = entryFetched + 1
119+
//Entry found in validated cache, so skip fetching from Redis
120+
//if merging is not required with Redis DB
121+
if !mergeNeeded {
122+
fieldMap := c.checkFieldMap(&entry)
123+
c.tmpDbCache[tableName].(map[string]interface{})[dbKey] = fieldMap
124+
continue
125+
}
126+
c.tmpDbCache[tableName].(map[string]interface{})[dbKey] = entry
112127
}
113128

114129
//Otherwise fetch it from Redis
115130
mCmd[dbKey] = pipe.HGetAll(redisKey) //write into pipeline
116131
if mCmd[dbKey] == nil {
117-
CVL_LOG(ERROR, "Failed pipe.HGetAll('%s')", redisKey)
132+
CVL_LOG(WARNING, "Failed pipe.HGetAll('%s')", redisKey)
118133
}
119134
}
120135

121136
_, err := pipe.Exec()
122137
if err != nil {
123-
CVL_LOG(ERROR, "Failed to fetch details for table %s", tableName)
138+
CVL_LOG(WARNING, "Failed to fetch details for table %s", tableName)
124139
return 0
125140
}
126141
pipe.Close()
@@ -130,6 +145,11 @@ func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]inter
130145

131146
for key, val := range mCmd {
132147
res, err := val.Result()
148+
149+
if (mapTable == nil) {
150+
break
151+
}
152+
133153
if (err != nil || len(res) == 0) {
134154
//no data found, don't keep blank entry
135155
delete(mapTable.(map[string]interface{}), key)
@@ -155,14 +175,14 @@ func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]inter
155175
runtime.Gosched()
156176
}
157177

158-
TRACE_LOG(INFO_API, TRACE_CACHE,"\n%v, Exiting fetchTableDataToTmpCache", time.Now())
178+
TRACE_LOG(TRACE_CACHE,"\n%v, Exiting fetchTableDataToTmpCache", time.Now())
159179

160180
return entryFetched
161181
}
162182

163183
//populate redis data to cache
164184
func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode {
165-
TRACE_LOG(INFO_API, TRACE_CACHE, "\n%v, Entered fetchToTmpCache", time.Now())
185+
TRACE_LOG(TRACE_CACHE, "\n%v, Entered fetchToTmpCache", time.Now())
166186

167187
entryToFetch := 0
168188
var root *yparser.YParserNode = nil
@@ -191,7 +211,7 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode {
191211
if Tracing {
192212
jsonDataBytes, _ := json.Marshal(c.tmpDbCache)
193213
jsonData := string(jsonDataBytes)
194-
TRACE_LOG(INFO_API, TRACE_CACHE, "Top Node=%v\n", jsonData)
214+
TRACE_LOG(TRACE_CACHE, "Top Node=%v\n", jsonData)
195215
}
196216

197217
data, err := jsonquery.ParseJsonMap(&c.tmpDbCache)
@@ -202,7 +222,7 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode {
202222

203223
//Build yang tree for each table and cache it
204224
for jsonNode := data.FirstChild; jsonNode != nil; jsonNode=jsonNode.NextSibling {
205-
TRACE_LOG(INFO_API, TRACE_CACHE, "Top Node=%v\n", jsonNode.Data)
225+
TRACE_LOG(TRACE_CACHE, "Top Node=%v\n", jsonNode.Data)
206226
//Visit each top level list in a loop for creating table data
207227
topNode, _ := c.generateTableData(true, jsonNode)
208228
if (root == nil) {
@@ -212,15 +232,46 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode {
212232
return nil
213233
}
214234
}
235+
236+
//Generate YANG data for Yang Validator
237+
topYangNode, cvlYErrObj := c.generateYangListData(jsonNode, true)
238+
if topYangNode == nil {
239+
cvlYErrObj.ErrCode = CVL_SYNTAX_ERROR
240+
CVL_LOG(WARNING, "Unable to translate cache data to YANG format")
241+
return nil
242+
}
243+
244+
//Create a full document and merge with main YANG data
245+
doc := &xmlquery.Node{Type: xmlquery.DocumentNode}
246+
doc.FirstChild = topYangNode
247+
doc.LastChild = topYangNode
248+
topYangNode.Parent = doc
249+
250+
if (IsTraceLevelSet(TRACE_CACHE)) {
251+
TRACE_LOG(TRACE_CACHE, "Before cache merge = %s, source = %s",
252+
c.yv.root.OutputXML(false),
253+
doc.OutputXML(false))
254+
}
255+
256+
if c.mergeYangData(c.yv.root, doc) != CVL_SUCCESS {
257+
CVL_LOG(WARNING, "Unable to merge translated YANG data while " +
258+
"translating from cache data to YANG format")
259+
cvlYErrObj.ErrCode = CVL_SYNTAX_ERROR
260+
return nil
261+
}
262+
if (IsTraceLevelSet(TRACE_CACHE)) {
263+
TRACE_LOG(TRACE_CACHE, "After cache merge = %s",
264+
c.yv.root.OutputXML(false))
265+
}
215266
}
216267
} // until all dependent data is fetched
217268

218269
if root != nil && Tracing {
219270
dumpStr := c.yp.NodeDump(root)
220-
TRACE_LOG(INFO_API, TRACE_CACHE, "Dependent Data = %v\n", dumpStr)
271+
TRACE_LOG(TRACE_CACHE, "Dependent Data = %v\n", dumpStr)
221272
}
222273

223-
TRACE_LOG(INFO_API, TRACE_CACHE, "\n%v, Exiting fetchToTmpCache", time.Now())
274+
TRACE_LOG(TRACE_CACHE, "\n%v, Exiting fetchToTmpCache", time.Now())
224275
return root
225276
}
226277

@@ -230,5 +281,3 @@ func (c *CVL) clearTmpDbCache() {
230281
delete(c.tmpDbCache, key)
231282
}
232283
}
233-
234-

0 commit comments

Comments
 (0)