@@ -62,6 +62,12 @@ var dbNameToDbNum map[string]uint8
6262//map of lua script loaded
6363var luaScripts map [string ]* redis.Script
6464
65+ type leafRefInfo struct {
66+ path string //leafref path
67+ yangListNames []string //all yang list in path
68+ targetNodeName string //target node name
69+ }
70+
6571//var tmpDbCache map[string]interface{} //map of table storing map of key-value pair
6672 //m["PORT_TABLE] = {"key" : {"f1": "v1"}}
6773//Important schema information to be loaded at bootup time
@@ -74,10 +80,11 @@ type modelTableInfo struct {
7480 redisKeyDelim string
7581 redisKeyPattern string
7682 mapLeaf []string //for 'mapping list'
77- leafRef map [string ][]string //for storing all leafrefs for a leaf in a table,
83+ leafRef map [string ][]* leafRefInfo //for storing all leafrefs for a leaf in a table,
7884 //multiple leafref possible for union
7985 mustExp map [string ]string
8086 tablesForMustExp map [string ]CVLOperation
87+ refFromTables []tblFieldPair //list of table or table/field referring to this table
8188 dfltLeafVal map [string ]string //map of leaf names and default value
8289}
8390
@@ -359,7 +366,7 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo
359366 continue
360367 }
361368
362- tableInfo .leafRef = make (map [string ][]string )
369+ tableInfo .leafRef = make (map [string ][]* leafRefInfo )
363370 for _ , leafRefNode := range leafRefNodes {
364371 if (leafRefNode .Parent == nil || leafRefNode .FirstChild == nil ) {
365372 continue
@@ -378,7 +385,7 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo
378385 //Store the leafref path
379386 if (leafName != "" ) {
380387 tableInfo .leafRef [leafName ] = append (tableInfo .leafRef [leafName ],
381- getXmlNodeAttr (leafRefNode .FirstChild , "value" ))
388+ & leafRefInfo { path : getXmlNodeAttr (leafRefNode .FirstChild , "value" )} )
382389 }
383390 }
384391
@@ -429,6 +436,69 @@ func getYangListToRedisTbl(yangListName string) string {
429436 return yangListName
430437}
431438
439+ //This functions build info of dependent table/fields
440+ //which uses a particular table through leafref
441+ func buildRefTableInfo () {
442+
443+ CVL_LOG (INFO_API , "Building reverse reference info from leafref" )
444+
445+ for tblName , tblInfo := range modelInfo .tableInfo {
446+ if (len (tblInfo .leafRef ) == 0 ) {
447+ continue
448+ }
449+
450+ //For each leafref update the table used through leafref
451+ for fieldName , leafRefs := range tblInfo .leafRef {
452+ for _ , leafRef := range leafRefs {
453+
454+ for _ , yangListName := range leafRef .yangListNames {
455+ refTblInfo := modelInfo .tableInfo [yangListName ]
456+
457+ refFromTables := & refTblInfo .refFromTables
458+ * refFromTables = append (* refFromTables , tblFieldPair {tblName , fieldName })
459+ modelInfo .tableInfo [yangListName ] = refTblInfo
460+ }
461+
462+ }
463+ }
464+
465+ }
466+
467+ //Now sort list 'refFromTables' under each table based on dependency among them
468+ for tblName , tblInfo := range modelInfo .tableInfo {
469+ if (len (tblInfo .refFromTables ) == 0 ) {
470+ continue
471+ }
472+
473+ depTableList := []string {}
474+ for i := 0 ; i < len (tblInfo .refFromTables ); i ++ {
475+ depTableList = append (depTableList , tblInfo .refFromTables [i ].tableName )
476+ }
477+
478+ sortedTableList , _ := cvg .cv .SortDepTables (depTableList )
479+ if (len (sortedTableList ) == 0 ) {
480+ continue
481+ }
482+
483+ newRefFromTables := []tblFieldPair {}
484+
485+ for i := 0 ; i < len (sortedTableList ); i ++ {
486+ //Find fieldName
487+ fieldName := ""
488+ for j := 0 ; j < len (tblInfo .refFromTables ); j ++ {
489+ if (sortedTableList [i ] == tblInfo .refFromTables [j ].tableName ) {
490+ fieldName = tblInfo .refFromTables [j ].field
491+ newRefFromTables = append (newRefFromTables , tblFieldPair {sortedTableList [i ], fieldName })
492+ }
493+ }
494+ }
495+ //Update sorted refFromTables
496+ tblInfo .refFromTables = newRefFromTables
497+ modelInfo .tableInfo [tblName ] = tblInfo
498+ }
499+
500+ }
501+
432502//Find the tables names in must expression, these tables data need to be fetched
433503//during semantic validation
434504func addTableNamesForMustExp () {
@@ -998,8 +1068,8 @@ func (c *CVL) findUsedAsLeafRef(tableName, field string) []tblFieldPair {
9981068 found := false
9991069 //Find leafref by searching table and field name
10001070 for _ , leafRef := range leafRefs {
1001- if ((strings .Contains (leafRef , tableName ) == true ) &&
1002- (strings .Contains (leafRef , field ) == true )) {
1071+ if ((strings .Contains (leafRef . path , tableName ) == true ) &&
1072+ (strings .Contains (leafRef . path , field ) == true )) {
10031073 tblFieldPairArr = append (tblFieldPairArr ,
10041074 tblFieldPair {tblName , fieldName })
10051075 //Found as leafref, no need to search further
@@ -1030,7 +1100,7 @@ func (c *CVL) addLeafRef(config bool, tableName string, name string, value strin
10301100 for _ , leafRef := range modelInfo .tableInfo [tableName ].leafRef [name ] {
10311101
10321102 //Get reference table name from the path and the leaf name
1033- matches := reLeafRef .FindStringSubmatch (leafRef )
1103+ matches := reLeafRef .FindStringSubmatch (leafRef . path )
10341104
10351105 //We have the leafref table name and the leaf name as well
10361106 if (matches != nil && len (matches ) == 5 ) { //whole + 4 sub matches
0 commit comments