Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: item.go

Issue 1410743011: Fix race in item too. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/gkvlite.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698