From 81b09ac7560e282cd4e8289243c5f9aea7ed6e38 Mon Sep 17 00:00:00 2001 From: Vemula Venkatesh Date: Mon, 23 Sep 2024 07:34:49 +0100 Subject: [PATCH 1/4] feat(idpool): idpool feature for generating id's Signed-off-by: Vemula Venkatesh --- pkg/LinuxGeneralModule/lgm.go | 64 +++++++------- pkg/utils/idpool.go | 160 ++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 30 deletions(-) create mode 100644 pkg/utils/idpool.go diff --git a/pkg/LinuxGeneralModule/lgm.go b/pkg/LinuxGeneralModule/lgm.go index 5140bd05..97a91cd7 100644 --- a/pkg/LinuxGeneralModule/lgm.go +++ b/pkg/LinuxGeneralModule/lgm.go @@ -31,12 +31,6 @@ import ( // ModulelgmHandler enmpty interface type ModulelgmHandler struct{} -// RoutingTableMax max value of routing table -const RoutingTableMax = 4000 - -// RoutingTableMin min value of routing table -const RoutingTableMin = 1000 - // lgmComp string constant const lgmComp string = "lgm" @@ -46,10 +40,11 @@ const brStr string = "br-" // vxlanStr string constant const vxlanStr string = "vxlan-" -// GenerateRouteTable range specification, note that min <= max -func GenerateRouteTable() uint32 { - return uint32(rand.Intn(RoutingTableMax-RoutingTableMin+1) + RoutingTableMin) //nolint:gosec -} +// routingTableMax max value of routing table +const routingTableMax = 4000 + +// routingTableMin min value of routing table +const routingTableMin = 1000 // run runs the commands func run(cmd []string, flag bool) (string, int) { @@ -350,6 +345,9 @@ var ctx context.Context // nlink variable wrapper var nlink utils.Netlink +// RouteTableGen table id generate variable +var RouteTableGen utils.IDPool + // Initialize initializes the config, logger and subscribers func Initialize() { eb := eventbus.EBus @@ -363,7 +361,8 @@ func Initialize() { brTenant = "br-tenant" ipMtu = config.GlobalConfig.LinuxFrr.IPMtu ctx = context.Background() - nlink = utils.NewNetlinkWrapperWithArgs(config.GlobalConfig.Tracer) + RouteTableGen = utils.IDPoolInit("RTtable", routingTableMin, routingTableMax) + nlink = utils.NewNetlinkWrapperWithArgs(false) // Set up the static configuration parts _, err := nlink.LinkByName(ctx, brTenant) if err != nil { @@ -401,8 +400,8 @@ func setUpTenantBridge() { } } -// routingTableBusy checks if the route is in filterred list -func routingTableBusy(table uint32) (bool, error) { +// routingtableBusy checks if the route is in filterred list +func routingtableBusy(table uint32) (bool, error) { routeList, err := nlink.RouteListFiltered(ctx, netlink.FAMILY_V4, &netlink.Route{Table: int(table)}, netlink.RT_FILTER_TABLE) if err != nil { return false, err @@ -454,6 +453,7 @@ func setUpBridge(lb *infradb.LogicalBridge) bool { //nolint:funlen,gocognit func setUpVrf(vrf *infradb.Vrf) (string, bool) { IPMtu := fmt.Sprintf("%+v", ipMtu) + var addKey int if path.Base(vrf.Name) == "GRD" { vrf.Metadata.RoutingTable = make([]*uint32, 2) vrf.Metadata.RoutingTable[0] = new(uint32) @@ -464,19 +464,23 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { } vrf.Metadata.RoutingTable = make([]*uint32, 1) vrf.Metadata.RoutingTable[0] = new(uint32) - var routingTable uint32 + var routingtable uint32 + name := vrf.Name for { - routingTable = GenerateRouteTable() - isBusy, err := routingTableBusy(routingTable) + routingtable, _ = RouteTableGen.GetID(name, 0) + log.Printf("LGM assigned id %+v for vrf name %s\n", routingtable, vrf.Name) + isbusy, err := routingtableBusy(routingtable) if err != nil { - log.Printf("LGM : Error occurred when checking if routing table %d is busy: %+v\n", routingTable, err) + log.Printf("LGM : Error occurred when checking if routing table %d is busy: %+v\n", routingtable, err) return "", false } - if !isBusy { - log.Printf("LGM: Routing Table %d is not busy\n", routingTable) + if !isbusy { + log.Printf("LGM: Routing Table %d is not busy\n", routingtable) break } - log.Printf("LGM: Routing Table %d is busy\n", routingTable) + log.Printf("LGM: Routing Table %d is busy\n", routingtable) + addKey++ + name = fmt.Sprintf("%s%d", name, addKey) } var vtip string if !reflect.ValueOf(vrf.Spec.VtepIP).IsZero() { @@ -489,19 +493,19 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { return "", false } } - log.Printf("setUpVrf: %s %d\n", vtip, routingTable) + log.Printf("setUpVrf: %s %d\n", vtip, routingtable) // Create the vrf interface for the specified routing table and add loopback address linkAdderr := nlink.LinkAdd(ctx, &netlink.Vrf{ LinkAttrs: netlink.LinkAttrs{Name: path.Base(vrf.Name)}, - Table: routingTable, + Table: routingtable, }) if linkAdderr != nil { - log.Printf("LGM: Error in Adding vrf link table %d\n", routingTable) + log.Printf("LGM: Error in Adding vrf link table %d\n", routingtable) return "", false } - log.Printf("LGM: vrf link %s Added with table id %d\n", vrf.Name, routingTable) + log.Printf("LGM: vrf link %s Added with table id %d\n", vrf.Name, routingtable) link, linkErr := nlink.LinkByName(ctx, path.Base(vrf.Name)) if linkErr != nil { @@ -536,7 +540,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { Src1 := net.IPv4(0, 0, 0, 0) route := netlink.Route{ - Table: int(routingTable), + Table: int(routingtable), Type: unix.RTN_THROW, Protocol: 255, Priority: 9999, @@ -548,7 +552,7 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { return "", false } - log.Printf("LGM : Added route throw default table %d proto opi_evpn_br metric 9999\n", routingTable) + log.Printf("LGM : Added route throw default table %d proto opi_evpn_br metric 9999\n", routingtable) // Disable reverse-path filtering to accept ingress traffic punted by the pipeline // disable_rp_filter("rep-"+vrf.Name) // Configuration specific for VRFs associated with L3 EVPN @@ -638,8 +642,8 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { return "", false } } - details := fmt.Sprintf("{\"routingTable\":\"%d\"}", routingTable) - *vrf.Metadata.RoutingTable[0] = routingTable + details := fmt.Sprintf("{\"routingtable\":\"%d\"}", routingtable) + *vrf.Metadata.RoutingTable[0] = routingtable return details, true } @@ -775,7 +779,7 @@ func tearDownVrf(vrf *infradb.Vrf) bool { if path.Base(vrf.Name) == "GRD" { return true } - routingTable := *vrf.Metadata.RoutingTable[0] + routingtable := *vrf.Metadata.RoutingTable[0] // Delete the Linux networking artefacts in reverse order if !reflect.ValueOf(vrf.Spec.Vni).IsZero() { linkVxlan, linkErr := nlink.LinkByName(ctx, vxlanStr+path.Base(vrf.Name)) @@ -802,7 +806,7 @@ func tearDownVrf(vrf *infradb.Vrf) bool { } log.Printf("LGM : Delete br-%s\n", vrf.Name) } - routeTable := fmt.Sprintf("%+v", routingTable) + routeTable := fmt.Sprintf("%+v", routingtable) flusherr := nlink.RouteFlushTable(ctx, routeTable) if flusherr != nil { log.Printf("LGM: Error in flush table %+v\n", routeTable) diff --git a/pkg/utils/idpool.go b/pkg/utils/idpool.go new file mode 100644 index 00000000..77f95f02 --- /dev/null +++ b/pkg/utils/idpool.go @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. +// Copyright (C) 2023 Nordix Foundation. + +// Package linuxgeneralmodule is the main package of the application + +package utils + +import ( + "fmt" + "log" + "reflect" +) + +// IDPool structure +/* Helper class for uniquely assigning IDs from a specified integer set (e.g. a +# range) to keys. IDs are assigned (or read) with GetID(key) and returned back +# into the pool with ReleaseID(key). The IDPool remembers a once-assigned ID +# for keys so that the same ID is assigned for a key. Only when the pool runs +# out of unassigned keys, it will recycle released ids and assign them to new +# keys. +# Optionally, the IDPool supports reference tracking for key/ID pairs. Clients +# can provide a unique reference when fetching and releasing an ID for a key +# to support multiple independent clients. +# The pool will only release the ID for the key, when the last client has the +# released the ID with its reference. When a reference is specified in GetID() +# and ReleaseID() the IDPool returns the current number of reference for the +# ID so that a caller knows when an ID was newly assigned (ref_count 1) or +# finally released (ref_count 0). +*/ +type IDPool struct { + name string // Name of pool + unusedIDs []uint32 // Yet unused IDs in pool Available ids + idsInUse map[interface{}]uint32 // Mapping key: id for currently assigned ids + idsForReuse map[interface{}]uint32 // Mapping key: id for previously assigned ids + refs map[uint32][]interface{} + size int // Size of the pool +} + +// IDPoolInit initialize mod ptr pool +func IDPoolInit(name string, min uint32, max uint32) IDPool { + var pool IDPool + pool.name = name + var index int + pool.unusedIDs = make([]uint32, (max-min)+1) + if min > 0 { + for value := max; value >= min; value-- { + pool.unusedIDs[index] = value + index++ + } + } else { + return IDPool{} + } + pool.size = len(pool.unusedIDs) + pool.idsInUse = make(map[interface{}]uint32) + pool.idsForReuse = make(map[interface{}]uint32) + pool.refs = make(map[uint32][]interface{}) + return pool +} + +// GetPoolStatus get status of a pool +func (ip *IDPool) GetPoolStatus() string { + str := fmt.Sprintf("name=%s\n Inuse=%+v\n Refs=%+v\n Forreuse=%+v\n Unused=%+v\n", ip.name, ip.idsInUse, ip.refs, ip.idsForReuse, ip.unusedIDs) + return str +} + +func (ip *IDPool) assignid(key interface{}) uint32 { + // Check if there was an id assigned for that key earlier + var id uint32 + ok := ip.idsForReuse[key] + if ok != 0 { + // Re-use the old id + delete(ip.idsForReuse, key) + } else { + if len(ip.unusedIDs) != 0 { + // Pick an unused id + id = ip.unusedIDs[len(ip.unusedIDs)-1] + ip.unusedIDs = ip.unusedIDs[0 : len(ip.unusedIDs)-1] + } else { + if len(ip.idsForReuse) != 0 { + // Pick one of the ids earlier used for another key + for oldKey := range ip.idsForReuse { + delete(ip.idsForReuse, oldKey) + break + } + } else { + log.Printf("IDPool: Failed to allocate id for %+v. No free ids in pool.", key) + return 0 + } + } + } + // Store the assigned id, if any + if id != 0 { + ip.idsInUse[key] = id + } + return id +} + +// GetID get the mod ptr id from pool +func (ip *IDPool) GetID(key interface{}, ref interface{}) (uint32, uint32) { + var id uint32 + ok := ip.idsInUse[key] + if ok == 0 { + id = ip.assignid(key) + if id == 0 { + return 0, 0 + } + } + id = ok + if ref != nil { + log.Printf("IDPool: GetID Assigning key : %+v , id %+v for ref %v", id, key, ref) + if reflect.ValueOf(ip.refs[id]).IsZero() { + ip.refs[id] = make([]interface{}, 0) + } + ip.refs[id] = append(ip.refs[id], ref) + return id, uint32(len(ip.refs[id])) + } + log.Printf("IDPool: GetID Assigning id %v for key %v and ref %v", id, key, ref) + return id, uint32(0) +} + +func deleteRef(refSet []interface{}, ref interface{}) []interface{} { + var i uint32 + for index, value := range refSet { + if value == ref { + i = uint32(index) + break + } + } + return append(refSet[:i], refSet[i+1:]...) +} + +// ReleaseID get the reference id +func (ip *IDPool) ReleaseID(key interface{}, ref interface{}) (uint32, uint32) { + log.Printf("IDPool:ReleaseID Releasing id for key %v", key) + id := ip.idsInUse[key] + if ref == nil { + log.Printf("No id to release for key %v", key) + return 0, 0 + } + refSet := ip.refs[id] + if !reflect.ValueOf(refSet).IsZero() && !reflect.ValueOf(ref).IsZero() { + refSet = deleteRef(refSet, ref) + } + if refSet != nil { + log.Printf("IDPool:ReleaseID Id %v has been released", id) + delete(ip.idsInUse, key) + if refSet != nil { + delete(ip.refs, id) + } + // Store released id for future reassignment + ip.idsForReuse[key] = id + } else { + log.Printf("IDPool:ReleaseID Keep id:%+v remaining references %+v", id, len(refSet)) + } + if ref != nil { + return id, uint32(len(refSet)) + } + return id, uint32(0) +} From 3a9ec4ff66fe07ddb137991c0538af7d4a862b94 Mon Sep 17 00:00:00 2001 From: Vemula Venkatesh Date: Tue, 29 Oct 2024 14:38:01 +0000 Subject: [PATCH 2/4] feat(idpool): fixed routing table id busy error handling Signed-off-by: Vemula Venkatesh --- pkg/LinuxGeneralModule/lgm.go | 25 +++++++++---------------- pkg/utils/idpool.go | 8 ++++---- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/pkg/LinuxGeneralModule/lgm.go b/pkg/LinuxGeneralModule/lgm.go index 97a91cd7..871202f9 100644 --- a/pkg/LinuxGeneralModule/lgm.go +++ b/pkg/LinuxGeneralModule/lgm.go @@ -453,7 +453,6 @@ func setUpBridge(lb *infradb.LogicalBridge) bool { //nolint:funlen,gocognit func setUpVrf(vrf *infradb.Vrf) (string, bool) { IPMtu := fmt.Sprintf("%+v", ipMtu) - var addKey int if path.Base(vrf.Name) == "GRD" { vrf.Metadata.RoutingTable = make([]*uint32, 2) vrf.Metadata.RoutingTable[0] = new(uint32) @@ -466,21 +465,15 @@ func setUpVrf(vrf *infradb.Vrf) (string, bool) { vrf.Metadata.RoutingTable[0] = new(uint32) var routingtable uint32 name := vrf.Name - for { - routingtable, _ = RouteTableGen.GetID(name, 0) - log.Printf("LGM assigned id %+v for vrf name %s\n", routingtable, vrf.Name) - isbusy, err := routingtableBusy(routingtable) - if err != nil { - log.Printf("LGM : Error occurred when checking if routing table %d is busy: %+v\n", routingtable, err) - return "", false - } - if !isbusy { - log.Printf("LGM: Routing Table %d is not busy\n", routingtable) - break - } - log.Printf("LGM: Routing Table %d is busy\n", routingtable) - addKey++ - name = fmt.Sprintf("%s%d", name, addKey) + routingtable, _ = RouteTableGen.GetID(name, 0) + log.Printf("LGM assigned id %+v for vrf name %s\n", routingtable, vrf.Name) + isbusy, err := routingtableBusy(routingtable) + if err != nil { + log.Printf("LGM : Error occurred when checking if routing table %d is busy: %+v\n", routingtable, err) + return "", false + } + if !isbusy { + log.Printf("LGM: Routing Table %d is not busy\n", routingtable) } var vtip string if !reflect.ValueOf(vrf.Spec.VtepIP).IsZero() { diff --git a/pkg/utils/idpool.go b/pkg/utils/idpool.go index 77f95f02..511437ac 100644 --- a/pkg/utils/idpool.go +++ b/pkg/utils/idpool.go @@ -2,8 +2,7 @@ // Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries. // Copyright (C) 2023 Nordix Foundation. -// Package linuxgeneralmodule is the main package of the application - +// Package utils has some utility functions and interfaces package utils import ( @@ -133,11 +132,12 @@ func deleteRef(refSet []interface{}, ref interface{}) []interface{} { // ReleaseID get the reference id func (ip *IDPool) ReleaseID(key interface{}, ref interface{}) (uint32, uint32) { log.Printf("IDPool:ReleaseID Releasing id for key %v", key) - id := ip.idsInUse[key] - if ref == nil { + ok := ip.idsInUse[key] + if ok == 0 { log.Printf("No id to release for key %v", key) return 0, 0 } + id := ok refSet := ip.refs[id] if !reflect.ValueOf(refSet).IsZero() && !reflect.ValueOf(ref).IsZero() { refSet = deleteRef(refSet, ref) From a5b97636238ddd84865892528a3d62aff56478b7 Mon Sep 17 00:00:00 2001 From: Vemula Venkatesh Date: Tue, 29 Oct 2024 15:10:30 +0000 Subject: [PATCH 3/4] feat(idpool): fixed routing table id busy error handling and reference type changed to list(python) equivalent Signed-off-by: Vemula Venkatesh --- pkg/LinuxGeneralModule/lgm.go | 4 ++++ pkg/utils/idpool.go | 35 +++++++++++------------------------ 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/pkg/LinuxGeneralModule/lgm.go b/pkg/LinuxGeneralModule/lgm.go index 871202f9..b03fad64 100644 --- a/pkg/LinuxGeneralModule/lgm.go +++ b/pkg/LinuxGeneralModule/lgm.go @@ -362,6 +362,10 @@ func Initialize() { ipMtu = config.GlobalConfig.LinuxFrr.IPMtu ctx = context.Background() RouteTableGen = utils.IDPoolInit("RTtable", routingTableMin, routingTableMax) + if reflect.DeepEqual(RouteTableGen, utils.IDPool{}) { + log.Printf("LGM: Failed in the assigning id \n") + return + } nlink = utils.NewNetlinkWrapperWithArgs(false) // Set up the static configuration parts _, err := nlink.LinkByName(ctx, brTenant) diff --git a/pkg/utils/idpool.go b/pkg/utils/idpool.go index 511437ac..97f6aaa4 100644 --- a/pkg/utils/idpool.go +++ b/pkg/utils/idpool.go @@ -32,7 +32,7 @@ type IDPool struct { unusedIDs []uint32 // Yet unused IDs in pool Available ids idsInUse map[interface{}]uint32 // Mapping key: id for currently assigned ids idsForReuse map[interface{}]uint32 // Mapping key: id for previously assigned ids - refs map[uint32][]interface{} + refs map[uint32]map[interface{}]bool size int // Size of the pool } @@ -53,13 +53,13 @@ func IDPoolInit(name string, min uint32, max uint32) IDPool { pool.size = len(pool.unusedIDs) pool.idsInUse = make(map[interface{}]uint32) pool.idsForReuse = make(map[interface{}]uint32) - pool.refs = make(map[uint32][]interface{}) + pool.refs = make(map[uint32]map[interface{}]bool) return pool } // GetPoolStatus get status of a pool func (ip *IDPool) GetPoolStatus() string { - str := fmt.Sprintf("name=%s\n Inuse=%+v\n Refs=%+v\n Forreuse=%+v\n Unused=%+v\n", ip.name, ip.idsInUse, ip.refs, ip.idsForReuse, ip.unusedIDs) + str := fmt.Sprintf("name=%s\n Inuse=%+v\n Refs=%+v\n Forreuse=%+v\n Unused=%+v\n ", ip.name, ip.idsInUse, ip.refs, ip.idsForReuse, ip.unusedIDs) return str } @@ -104,31 +104,21 @@ func (ip *IDPool) GetID(key interface{}, ref interface{}) (uint32, uint32) { if id == 0 { return 0, 0 } + } else { + id = ok } - id = ok if ref != nil { log.Printf("IDPool: GetID Assigning key : %+v , id %+v for ref %v", id, key, ref) if reflect.ValueOf(ip.refs[id]).IsZero() { - ip.refs[id] = make([]interface{}, 0) + ip.refs[id] = make(map[interface{}]bool, 0) } - ip.refs[id] = append(ip.refs[id], ref) + ip.refs[id][ref] = true return id, uint32(len(ip.refs[id])) } log.Printf("IDPool: GetID Assigning id %v for key %v and ref %v", id, key, ref) return id, uint32(0) } -func deleteRef(refSet []interface{}, ref interface{}) []interface{} { - var i uint32 - for index, value := range refSet { - if value == ref { - i = uint32(index) - break - } - } - return append(refSet[:i], refSet[i+1:]...) -} - // ReleaseID get the reference id func (ip *IDPool) ReleaseID(key interface{}, ref interface{}) (uint32, uint32) { log.Printf("IDPool:ReleaseID Releasing id for key %v", key) @@ -140,16 +130,13 @@ func (ip *IDPool) ReleaseID(key interface{}, ref interface{}) (uint32, uint32) { id := ok refSet := ip.refs[id] if !reflect.ValueOf(refSet).IsZero() && !reflect.ValueOf(ref).IsZero() { - refSet = deleteRef(refSet, ref) + delete(refSet, ref) } - if refSet != nil { - log.Printf("IDPool:ReleaseID Id %v has been released", id) + if len(refSet) == 0 { delete(ip.idsInUse, key) - if refSet != nil { - delete(ip.refs, id) - } - // Store released id for future reassignment + delete(ip.refs, id) ip.idsForReuse[key] = id + log.Printf("IDPool:ReleaseID Id %v has been released", id) } else { log.Printf("IDPool:ReleaseID Keep id:%+v remaining references %+v", id, len(refSet)) } From 64597cfda4769ae09d1c94efe34b1851129b160a Mon Sep 17 00:00:00 2001 From: Vemula Venkatesh Date: Tue, 10 Dec 2024 14:12:48 +0000 Subject: [PATCH 4/4] feat(idpool): fixed review comments Signed-off-by: Vemula Venkatesh --- pkg/LinuxGeneralModule/lgm.go | 4 ++-- pkg/utils/idpool.go | 36 ++++++++++++++++------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/pkg/LinuxGeneralModule/lgm.go b/pkg/LinuxGeneralModule/lgm.go index b03fad64..28a6aed8 100644 --- a/pkg/LinuxGeneralModule/lgm.go +++ b/pkg/LinuxGeneralModule/lgm.go @@ -351,6 +351,7 @@ var RouteTableGen utils.IDPool // Initialize initializes the config, logger and subscribers func Initialize() { eb := eventbus.EBus + var ok bool for _, subscriberConfig := range config.GlobalConfig.Subscribers { if subscriberConfig.Name == lgmComp { for _, eventType := range subscriberConfig.Events { @@ -361,8 +362,7 @@ func Initialize() { brTenant = "br-tenant" ipMtu = config.GlobalConfig.LinuxFrr.IPMtu ctx = context.Background() - RouteTableGen = utils.IDPoolInit("RTtable", routingTableMin, routingTableMax) - if reflect.DeepEqual(RouteTableGen, utils.IDPool{}) { + if RouteTableGen, ok = utils.IDPoolInit("RTtable", routingTableMin, routingTableMax); !ok { log.Printf("LGM: Failed in the assigning id \n") return } diff --git a/pkg/utils/idpool.go b/pkg/utils/idpool.go index 97f6aaa4..7e5edb10 100644 --- a/pkg/utils/idpool.go +++ b/pkg/utils/idpool.go @@ -37,24 +37,24 @@ type IDPool struct { } // IDPoolInit initialize mod ptr pool -func IDPoolInit(name string, min uint32, max uint32) IDPool { +func IDPoolInit(name string, min uint32, max uint32) (IDPool, bool) { + if max < min { + log.Printf("IDPool: Failed to Init pool for %s\n", name) + return IDPool{}, false + } var pool IDPool pool.name = name var index int pool.unusedIDs = make([]uint32, (max-min)+1) - if min > 0 { - for value := max; value >= min; value-- { - pool.unusedIDs[index] = value - index++ - } - } else { - return IDPool{} + for value := max; value >= min; value-- { + pool.unusedIDs[index] = value + index++ } pool.size = len(pool.unusedIDs) pool.idsInUse = make(map[interface{}]uint32) pool.idsForReuse = make(map[interface{}]uint32) pool.refs = make(map[uint32]map[interface{}]bool) - return pool + return pool, true } // GetPoolStatus get status of a pool @@ -66,8 +66,7 @@ func (ip *IDPool) GetPoolStatus() string { func (ip *IDPool) assignid(key interface{}) uint32 { // Check if there was an id assigned for that key earlier var id uint32 - ok := ip.idsForReuse[key] - if ok != 0 { + if _, ok := ip.idsForReuse[key]; ok { // Re-use the old id delete(ip.idsForReuse, key) } else { @@ -97,15 +96,12 @@ func (ip *IDPool) assignid(key interface{}) uint32 { // GetID get the mod ptr id from pool func (ip *IDPool) GetID(key interface{}, ref interface{}) (uint32, uint32) { + var ok bool var id uint32 - ok := ip.idsInUse[key] - if ok == 0 { - id = ip.assignid(key) - if id == 0 { + if id, ok = ip.idsInUse[key]; !ok { + if id = ip.assignid(key); id == 0 { return 0, 0 } - } else { - id = ok } if ref != nil { log.Printf("IDPool: GetID Assigning key : %+v , id %+v for ref %v", id, key, ref) @@ -121,13 +117,13 @@ func (ip *IDPool) GetID(key interface{}, ref interface{}) (uint32, uint32) { // ReleaseID get the reference id func (ip *IDPool) ReleaseID(key interface{}, ref interface{}) (uint32, uint32) { + var ok bool + var id uint32 log.Printf("IDPool:ReleaseID Releasing id for key %v", key) - ok := ip.idsInUse[key] - if ok == 0 { + if id, ok = ip.idsInUse[key]; !ok { log.Printf("No id to release for key %v", key) return 0, 0 } - id := ok refSet := ip.refs[id] if !reflect.ValueOf(refSet).IsZero() && !reflect.ValueOf(ref).IsZero() { delete(refSet, ref)