diff --git a/go/storage/compact_map.go b/go/storage/compact_map.go index ff3621910..93312b14d 100644 --- a/go/storage/compact_map.go +++ b/go/storage/compact_map.go @@ -1,6 +1,9 @@ package storage -import "strconv" +import ( + "strconv" + "sync" +) type NeedleValue struct { Key Key @@ -18,6 +21,8 @@ func (k Key) String() string { return strconv.FormatUint(uint64(k), 10) } + +//CompactSection is not concurrent safe,you should lock it when access in multi-thread type CompactSection struct { values []NeedleValue overflow map[Key]NeedleValue @@ -78,6 +83,7 @@ func (cs *CompactSection) Delete(key Key) uint32 { } return ret } + func (cs *CompactSection) Get(key Key) (*NeedleValue, bool) { if v, ok := cs.overflow[key]; ok { return &v, true @@ -87,6 +93,7 @@ func (cs *CompactSection) Get(key Key) (*NeedleValue, bool) { } return nil, false } + func (cs *CompactSection) binarySearchValues(key Key) int { l, h := 0, cs.counter-1 if h >= 0 && cs.values[h].Key < key { @@ -109,8 +116,10 @@ func (cs *CompactSection) binarySearchValues(key Key) int { } //This map assumes mostly inserting increasing keys +//It is concurrent safe type CompactMap struct { list []*CompactSection + lock sync.RWMutex } func NewCompactMap() CompactMap { @@ -118,6 +127,8 @@ func NewCompactMap() CompactMap { } func (cm *CompactMap) Set(key Key, offset uint32, size uint32) uint32 { + cm.lock.Lock() + defer cm.lock.Unlock() x := cm.binarySearchCompactSection(key) if x < 0 { //println(x, "creating", len(cm.list), "section, starting", key) @@ -135,14 +146,20 @@ func (cm *CompactMap) Set(key Key, offset uint32, size uint32) uint32 { } return cm.list[x].Set(key, offset, size) } + func (cm *CompactMap) Delete(key Key) uint32 { + cm.lock.Lock() + defer cm.lock.Unlock() x := cm.binarySearchCompactSection(key) if x < 0 { return uint32(0) } return cm.list[x].Delete(key) } + func (cm *CompactMap) Get(key Key) (*NeedleValue, bool) { + cm.lock.RLock() + defer cm.lock.RUnlock() x := cm.binarySearchCompactSection(key) if x < 0 { return nil, false @@ -176,7 +193,10 @@ func (cm *CompactMap) binarySearchCompactSection(key Key) int { } // Visit visits all entries or stop if any error when visiting +// You should NOT add or delete item in visit func func (cm *CompactMap) Visit(visit func(NeedleValue) error) error { + cm.lock.RLock() + defer cm.lock.RUnlock() for _, cs := range cm.list { for _, v := range cs.overflow { if err := visit(v); err != nil {