1
0
mirror of https://github.com/netsampler/goflow2.git synced 2024-05-06 15:54:52 +00:00

decoders: improve BasicTemplateSystem (#233)

* Use write lock when removing template

Since template removal modifies the template set map, it should be done
while holding a write lock, instead of a read lock.

* Optimize BasicTemplateSystem

The BasicTemplateSystem that comes with the library uses a 3-level map
to hold template information to avoid templateId and obsDomainId
collision between multiple protocols and hosts. However, the same can be
done by using a single map with a 64-bit key consisting of version,
templateId and obsDomainId.

This greatly simplifies the code and reduces the number of map lookups
from 3 to 1 per call to GetTemplate.

Co-authored-by: Matheus Castanho <matheus.castanho@dcc.ufmg.br>
This commit is contained in:
Louis
2023-11-04 16:04:36 -07:00
committed by GitHub
parent a0660824f0
commit 00c77d7605

View File

@ -9,7 +9,11 @@ var (
ErrorTemplateNotFound = fmt.Errorf("Error template not found")
)
type FlowBaseTemplateSet map[uint16]map[uint32]map[uint16]interface{}
type FlowBaseTemplateSet map[uint64]interface{}
func templateKey(version uint16, obsDomainId uint32, templateId uint16) uint64 {
return (uint64(version) << 48) | (uint64(obsDomainId) << 16) | uint64(templateId)
}
// Store interface that allows storing, removing and retrieving template data
type NetFlowTemplateSystem interface {
@ -18,7 +22,7 @@ type NetFlowTemplateSystem interface {
AddTemplate(version uint16, obsDomainId uint32, templateId uint16, template interface{}) error
}
func (ts *BasicTemplateSystem) GetTemplates() map[uint16]map[uint32]map[uint16]interface{} {
func (ts *BasicTemplateSystem) GetTemplates() FlowBaseTemplateSet {
ts.templateslock.RLock()
tmp := ts.templates
ts.templateslock.RUnlock()
@ -28,14 +32,7 @@ func (ts *BasicTemplateSystem) GetTemplates() map[uint16]map[uint32]map[uint16]i
func (ts *BasicTemplateSystem) AddTemplate(version uint16, obsDomainId uint32, templateId uint16, template interface{}) error {
ts.templateslock.Lock()
defer ts.templateslock.Unlock()
_, exists := ts.templates[version]
if !exists {
ts.templates[version] = make(map[uint32]map[uint16]interface{})
}
_, exists = ts.templates[version][obsDomainId]
if !exists {
ts.templates[version][obsDomainId] = make(map[uint16]interface{})
}
/*var templateId uint16
switch templateIdConv := template.(type) {
case IPFIXOptionsTemplateRecord:
@ -45,42 +42,30 @@ func (ts *BasicTemplateSystem) AddTemplate(version uint16, obsDomainId uint32, t
case TemplateRecord:
templateId = templateIdConv.TemplateId
}*/
ts.templates[version][obsDomainId][templateId] = template
key := templateKey(version, obsDomainId, templateId)
ts.templates[key] = template
return nil
}
func (ts *BasicTemplateSystem) GetTemplate(version uint16, obsDomainId uint32, templateId uint16) (interface{}, error) {
ts.templateslock.RLock()
defer ts.templateslock.RUnlock()
if templatesVersion, ok := ts.templates[version]; ok {
if templatesObsDom, ok := templatesVersion[obsDomainId]; ok {
if template, ok := templatesObsDom[templateId]; ok {
key := templateKey(version, obsDomainId, templateId)
if template, ok := ts.templates[key]; ok {
return template, nil
}
}
}
return nil, ErrorTemplateNotFound
}
func (ts *BasicTemplateSystem) RemoveTemplate(version uint16, obsDomainId uint32, templateId uint16) (interface{}, error) {
ts.templateslock.RLock()
defer ts.templateslock.RUnlock()
if templatesVersion, ok := ts.templates[version]; ok {
if templatesObsDom, ok := templatesVersion[obsDomainId]; ok {
if template, ok := templatesObsDom[templateId]; ok {
delete(templatesObsDom, templateId)
if len(templatesObsDom) == 0 {
delete(templatesVersion, obsDomainId)
if len(templatesVersion) == 0 {
delete(ts.templates, version)
}
}
ts.templateslock.Lock()
defer ts.templateslock.Unlock()
key := templateKey(version, obsDomainId, templateId)
if template, ok := ts.templates[key]; ok {
delete(ts.templates, key)
return template, nil
}
}
}
return nil, ErrorTemplateNotFound
}