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

Side by Side Diff: impl/memory/gkvlite_utils.go

Issue 2498463003: Fix a bug where deletions weren't updating the raw Kind index. (Closed)
Patch Set: Fix Created 4 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
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package memory 5 package memory
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "runtime" 9 "runtime"
10 "sync" 10 "sync"
11 11
12 "github.com/luci/gae/service/datastore" 12 "github.com/luci/gae/service/datastore"
13 "github.com/luci/gkvlite" 13 "github.com/luci/gkvlite"
14 ) 14 )
15 15
16 func gkvCollide(o, n memCollection, f func(k, ov, nv []byte)) { 16 func gkvCollide(o, n memCollection, f func(k, ov, nv []byte)) {
17 if o != nil && !o.IsReadOnly() { 17 if o != nil && !o.IsReadOnly() {
18 panic("old collection is r/w") 18 panic("old collection is r/w")
19 } 19 }
20 if n != nil && !n.IsReadOnly() { 20 if n != nil && !n.IsReadOnly() {
21 panic("new collection is r/w") 21 panic("new collection is r/w")
22 } 22 }
23 23
24 // TODO(riannucci): reimplement in terms of *iterator. 24 // TODO(riannucci): reimplement in terms of *iterator.
25 oldItems, newItems := make(chan *gkvlite.Item), make(chan *gkvlite.Item) 25 oldItems, newItems := make(chan *gkvlite.Item), make(chan *gkvlite.Item)
26 walker := func(c memCollection, ch chan<- *gkvlite.Item, wg *sync.WaitGr oup) { 26 walker := func(c memCollection, ch chan<- *gkvlite.Item, wg *sync.WaitGr oup) {
27 defer close(ch) 27 defer close(ch)
28 defer wg.Done()
29 if c != nil { 28 if c != nil {
30 c.VisitItemsAscend(nil, true, func(i *gkvlite.Item) bool { 29 c.VisitItemsAscend(nil, true, func(i *gkvlite.Item) bool {
31 ch <- i 30 ch <- i
32 return true 31 return true
33 }) 32 })
34 } 33 }
35 } 34 }
36 35
37 wg := &sync.WaitGroup{} 36 wg := &sync.WaitGroup{}
iannucci 2016/11/12 00:05:47 del wg too?
38 wg.Add(2)
39 go walker(o, oldItems, wg) 37 go walker(o, oldItems, wg)
40 go walker(n, newItems, wg) 38 go walker(n, newItems, wg)
41 39
42 l, r := <-oldItems, <-newItems 40 l, r := <-oldItems, <-newItems
43 for { 41 for {
44 » » if l == nil && r == nil { 42 » » switch {
45 » » » break 43 » » case l == nil && r == nil:
46 » » } 44 » » » return
47 45
48 » » if l == nil { 46 » » case l == nil:
49 f(r.Key, nil, r.Val) 47 f(r.Key, nil, r.Val)
50 r = <-newItems 48 r = <-newItems
51 » » } else if r == nil { 49
50 » » case r == nil:
52 f(l.Key, l.Val, nil) 51 f(l.Key, l.Val, nil)
53 l = <-oldItems 52 l = <-oldItems
54 » » } else { 53
54 » » default:
55 switch bytes.Compare(l.Key, r.Key) { 55 switch bytes.Compare(l.Key, r.Key) {
56 case -1: // l < r 56 case -1: // l < r
57 f(l.Key, l.Val, nil) 57 f(l.Key, l.Val, nil)
58 l = <-oldItems 58 l = <-oldItems
59 case 0: // l == r 59 case 0: // l == r
60 f(l.Key, l.Val, r.Val) 60 f(l.Key, l.Val, r.Val)
61 l, r = <-oldItems, <-newItems 61 l, r = <-oldItems, <-newItems
62 case 1: // l > r 62 case 1: // l > r
63 f(r.Key, nil, r.Val) 63 f(r.Key, nil, r.Val)
64 r = <-newItems 64 r = <-newItems
65 } 65 }
66 } 66 }
67 } 67 }
68 wg.Wait()
69 } 68 }
70 69
71 // memStore is a gkvlite.Store which will panic for anything which might 70 // memStore is a gkvlite.Store which will panic for anything which might
72 // otherwise return an error. 71 // otherwise return an error.
73 // 72 //
74 // This is reasonable for in-memory Store objects, since the only errors that 73 // This is reasonable for in-memory Store objects, since the only errors that
75 // should occur happen with file IO on the underlying file (which of course 74 // should occur happen with file IO on the underlying file (which of course
76 // doesn't exist). 75 // doesn't exist).
77 type memStore interface { 76 type memStore interface {
78 datastore.TestingSnapshot 77 datastore.TestingSnapshot
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 } 191 }
193 err := mc.c.VisitItemsAscend(target, withValue, visitor) 192 err := mc.c.VisitItemsAscend(target, withValue, visitor)
194 memoryCorruption(err) 193 memoryCorruption(err)
195 } 194 }
196 195
197 func (mc *memCollectionImpl) GetTotals() (numItems, numBytes uint64) { 196 func (mc *memCollectionImpl) GetTotals() (numItems, numBytes uint64) {
198 numItems, numBytes, err := mc.c.GetTotals() 197 numItems, numBytes, err := mc.c.GetTotals()
199 memoryCorruption(err) 198 memoryCorruption(err)
200 return 199 return
201 } 200 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698