Browse Source

make CompactMap concurrent safe

pull/279/head
tnextday 10 years ago
parent
commit
2c6b98877d
  1. 22
      go/storage/compact_map.go

22
go/storage/compact_map.go

@ -1,6 +1,9 @@
package storage package storage
import "strconv"
import (
"strconv"
"sync"
)
type NeedleValue struct { type NeedleValue struct {
Key Key Key Key
@ -18,6 +21,8 @@ func (k Key) String() string {
return strconv.FormatUint(uint64(k), 10) return strconv.FormatUint(uint64(k), 10)
} }
//CompactSection is not concurrent safe,you should lock it when access in multi-thread
type CompactSection struct { type CompactSection struct {
values []NeedleValue values []NeedleValue
overflow map[Key]NeedleValue overflow map[Key]NeedleValue
@ -78,6 +83,7 @@ func (cs *CompactSection) Delete(key Key) uint32 {
} }
return ret return ret
} }
func (cs *CompactSection) Get(key Key) (*NeedleValue, bool) { func (cs *CompactSection) Get(key Key) (*NeedleValue, bool) {
if v, ok := cs.overflow[key]; ok { if v, ok := cs.overflow[key]; ok {
return &v, true return &v, true
@ -87,6 +93,7 @@ func (cs *CompactSection) Get(key Key) (*NeedleValue, bool) {
} }
return nil, false return nil, false
} }
func (cs *CompactSection) binarySearchValues(key Key) int { func (cs *CompactSection) binarySearchValues(key Key) int {
l, h := 0, cs.counter-1 l, h := 0, cs.counter-1
if h >= 0 && cs.values[h].Key < key { 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 //This map assumes mostly inserting increasing keys
//It is concurrent safe
type CompactMap struct { type CompactMap struct {
list []*CompactSection list []*CompactSection
lock sync.RWMutex
} }
func NewCompactMap() CompactMap { func NewCompactMap() CompactMap {
@ -118,6 +127,8 @@ func NewCompactMap() CompactMap {
} }
func (cm *CompactMap) Set(key Key, offset uint32, size uint32) uint32 { func (cm *CompactMap) Set(key Key, offset uint32, size uint32) uint32 {
cm.lock.Lock()
defer cm.lock.Unlock()
x := cm.binarySearchCompactSection(key) x := cm.binarySearchCompactSection(key)
if x < 0 { if x < 0 {
//println(x, "creating", len(cm.list), "section, starting", key) //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) return cm.list[x].Set(key, offset, size)
} }
func (cm *CompactMap) Delete(key Key) uint32 { func (cm *CompactMap) Delete(key Key) uint32 {
cm.lock.Lock()
defer cm.lock.Unlock()
x := cm.binarySearchCompactSection(key) x := cm.binarySearchCompactSection(key)
if x < 0 { if x < 0 {
return uint32(0) return uint32(0)
} }
return cm.list[x].Delete(key) return cm.list[x].Delete(key)
} }
func (cm *CompactMap) Get(key Key) (*NeedleValue, bool) { func (cm *CompactMap) Get(key Key) (*NeedleValue, bool) {
cm.lock.RLock()
defer cm.lock.RUnlock()
x := cm.binarySearchCompactSection(key) x := cm.binarySearchCompactSection(key)
if x < 0 { if x < 0 {
return nil, false 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 // 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 { func (cm *CompactMap) Visit(visit func(NeedleValue) error) error {
cm.lock.RLock()
defer cm.lock.RUnlock()
for _, cs := range cm.list { for _, cs := range cm.list {
for _, v := range cs.overflow { for _, v := range cs.overflow {
if err := visit(v); err != nil { if err := visit(v); err != nil {

Loading…
Cancel
Save