| OLD | NEW |
| 1 package gkvlite | 1 package gkvlite |
| 2 | 2 |
| 3 import ( | 3 import ( |
| 4 "encoding/binary" | 4 "encoding/binary" |
| 5 "errors" | 5 "errors" |
| 6 "fmt" | 6 "fmt" |
| 7 "sync" | 7 "sync" |
| 8 "sync/atomic" | 8 "sync/atomic" |
| 9 ) | 9 ) |
| 10 | 10 |
| 11 // A persistable item. | 11 // A persistable item. |
| 12 type Item struct { | 12 type Item struct { |
| 13 Transient interface{} // For any ephemeral data. | 13 Transient interface{} // For any ephemeral data. |
| 14 Key, Val []byte // Val may be nil if not fetched into memory yet. | 14 Key, Val []byte // Val may be nil if not fetched into memory yet. |
| 15 Priority int32 // Use rand.Int31() for probabilistic balancing. | 15 Priority int32 // Use rand.Int31() for probabilistic balancing. |
| 16 } | 16 } |
| 17 | 17 |
| 18 var itemLocGL = sync.RWMutex{} |
| 19 |
| 18 // A persistable item and its persistence location. | 20 // A persistable item and its persistence location. |
| 19 type itemLoc struct { | 21 type itemLoc struct { |
| 20 m sync.Mutex | |
| 21 | |
| 22 loc *ploc // can be nil if item is dirty (not yet persisted). | 22 loc *ploc // can be nil if item is dirty (not yet persisted). |
| 23 item *Item // can be nil if item is not fetched into memory yet. | 23 item *Item // can be nil if item is not fetched into memory yet. |
| 24 } | 24 } |
| 25 | 25 |
| 26 var empty_itemLoc = &itemLoc{} | 26 var empty_itemLoc = &itemLoc{} |
| 27 | 27 |
| 28 // Number of Key bytes plus number of Val bytes. | 28 // Number of Key bytes plus number of Val bytes. |
| 29 func (i *Item) NumBytes(c *Collection) int { | 29 func (i *Item) NumBytes(c *Collection) int { |
| 30 return len(i.Key) + i.NumValBytes(c) | 30 return len(i.Key) + i.NumValBytes(c) |
| 31 } | 31 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 42 func (i *Item) Copy() *Item { | 42 func (i *Item) Copy() *Item { |
| 43 return &Item{ | 43 return &Item{ |
| 44 Key: i.Key, | 44 Key: i.Key, |
| 45 Val: i.Val, | 45 Val: i.Val, |
| 46 Priority: i.Priority, | 46 Priority: i.Priority, |
| 47 Transient: i.Transient, | 47 Transient: i.Transient, |
| 48 } | 48 } |
| 49 } | 49 } |
| 50 | 50 |
| 51 func (i *itemLoc) Loc() *ploc { | 51 func (i *itemLoc) Loc() *ploc { |
| 52 » i.m.Lock() | 52 » itemLocGL.RLock() |
| 53 » defer i.m.Unlock() | 53 » defer itemLocGL.RUnlock() |
| 54 return i.loc | 54 return i.loc |
| 55 } | 55 } |
| 56 | 56 |
| 57 func (i *itemLoc) setLoc(n *ploc) { | 57 func (i *itemLoc) setLoc(n *ploc) { |
| 58 » i.m.Lock() | 58 » itemLocGL.Lock() |
| 59 » defer i.m.Unlock() | 59 » defer itemLocGL.Unlock() |
| 60 i.loc = n | 60 i.loc = n |
| 61 } | 61 } |
| 62 | 62 |
| 63 func (i *itemLoc) Item() *Item { | 63 func (i *itemLoc) Item() *Item { |
| 64 » i.m.Lock() | 64 » itemLocGL.RLock() |
| 65 » defer i.m.Unlock() | 65 » defer itemLocGL.RUnlock() |
| 66 return i.item | 66 return i.item |
| 67 } | 67 } |
| 68 | 68 |
| 69 func (i *itemLoc) casItem(o, n *Item) bool { | 69 func (i *itemLoc) casItem(o, n *Item) bool { |
| 70 » i.m.Lock() | 70 » itemLocGL.Lock() |
| 71 » defer i.m.Unlock() | 71 » defer itemLocGL.Unlock() |
| 72 if i.item == o { | 72 if i.item == o { |
| 73 i.item = n | 73 i.item = n |
| 74 return true | 74 return true |
| 75 } | 75 } |
| 76 return false | 76 return false |
| 77 } | 77 } |
| 78 | 78 |
| 79 func (i *itemLoc) Copy(src *itemLoc) { | 79 func (i *itemLoc) Copy(src *itemLoc) { |
| 80 if src == nil { | 80 if src == nil { |
| 81 i.Copy(empty_itemLoc) | 81 i.Copy(empty_itemLoc) |
| 82 return | 82 return |
| 83 } | 83 } |
| 84 newloc := src.Loc() | |
| 85 newitem := src.Item() | |
| 86 | 84 |
| 87 » i.m.Lock() | 85 » itemLocGL.Lock() |
| 88 » defer i.m.Unlock() | 86 » defer itemLocGL.Unlock() |
| 89 » i.loc = newloc | 87 » // NOTE: This trick only works because of the global lock. No reason to
lock |
| 90 » i.item = newitem | 88 » // src independently of i. |
| 89 » i.loc = src.loc |
| 90 » i.item = src.item |
| 91 } | 91 } |
| 92 | 92 |
| 93 const itemLoc_hdrLength int = 4 + 4 + 4 + 4 | 93 const itemLoc_hdrLength int = 4 + 4 + 4 + 4 |
| 94 | 94 |
| 95 func (i *itemLoc) write(c *Collection) (err error) { | 95 func (i *itemLoc) write(c *Collection) (err error) { |
| 96 if i.Loc().isEmpty() { | 96 if i.Loc().isEmpty() { |
| 97 iItem := i.Item() | 97 iItem := i.Item() |
| 98 if iItem == nil { | 98 if iItem == nil { |
| 99 return errors.New("itemLoc.write with nil item") | 99 return errors.New("itemLoc.write with nil item") |
| 100 } | 100 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 loc := iloc.Loc() | 212 loc := iloc.Loc() |
| 213 if loc.isEmpty() { | 213 if loc.isEmpty() { |
| 214 i := iloc.Item() | 214 i := iloc.Item() |
| 215 if i == nil { | 215 if i == nil { |
| 216 return 0 | 216 return 0 |
| 217 } | 217 } |
| 218 return i.NumBytes(c) | 218 return i.NumBytes(c) |
| 219 } | 219 } |
| 220 return int(loc.Length) - itemLoc_hdrLength | 220 return int(loc.Length) - itemLoc_hdrLength |
| 221 } | 221 } |
| OLD | NEW |