OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package memory | 5 package memory |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "sync" | 9 "sync" |
10 | 10 |
| 11 "github.com/luci/gae/service/datastore" |
11 "github.com/luci/gae/service/datastore/serialize" | 12 "github.com/luci/gae/service/datastore/serialize" |
12 "github.com/luci/gkvlite" | 13 "github.com/luci/gkvlite" |
13 ) | 14 ) |
14 | 15 |
15 type iterDefinition struct { | 16 type iterDefinition struct { |
16 // The collection to iterate over | 17 // The collection to iterate over |
17 c *memCollection | 18 c *memCollection |
18 | 19 |
19 // The prefix to always assert for every row. A nil prefix matches every
row. | 20 // The prefix to always assert for every row. A nil prefix matches every
row. |
20 prefix []byte | 21 prefix []byte |
21 | 22 |
22 // prefixLen is the number of prefix bytes that the caller cares about.
It | 23 // prefixLen is the number of prefix bytes that the caller cares about.
It |
23 // may be <= len(prefix). When doing a multiIterator, this number will b
e used | 24 // may be <= len(prefix). When doing a multiIterator, this number will b
e used |
24 // to determine the amount of suffix to transfer accross iterators. This
is | 25 // to determine the amount of suffix to transfer accross iterators. This
is |
25 // used specifically when using builtin indexes to service ancestor quer
ies. | 26 // used specifically when using builtin indexes to service ancestor quer
ies. |
26 // The builtin index represents the ancestor key with prefix bytes, but
in a | 27 // The builtin index represents the ancestor key with prefix bytes, but
in a |
27 // multiIterator context, it wants the entire key to be included in the | 28 // multiIterator context, it wants the entire key to be included in the |
28 // suffix. | 29 // suffix. |
29 prefixLen int | 30 prefixLen int |
30 | 31 |
31 // The start cursor. It's appended to prefix to find the first row. | 32 // The start cursor. It's appended to prefix to find the first row. |
32 start []byte | 33 start []byte |
33 | 34 |
34 // The end cursor. It's appended to prefix to find the last row (which i
s not | 35 // The end cursor. It's appended to prefix to find the last row (which i
s not |
35 // included in the interation result). If this is nil, then there's no e
nd | 36 // included in the interation result). If this is nil, then there's no e
nd |
36 // except the natural end of the collection. | 37 // except the natural end of the collection. |
37 end []byte | 38 end []byte |
38 } | 39 } |
39 | 40 |
40 func multiIterate(defs []*iterDefinition, cb func(suffix []byte) bool) { | 41 func multiIterate(defs []*iterDefinition, cb func(suffix []byte) error) error { |
41 if len(defs) == 0 { | 42 if len(defs) == 0 { |
42 » » return | 43 » » return nil |
43 } | 44 } |
44 | 45 |
45 ts := make([]*iterator, len(defs)) | 46 ts := make([]*iterator, len(defs)) |
46 prefixLens := make([]int, len(defs)) | 47 prefixLens := make([]int, len(defs)) |
47 for i, def := range defs { | 48 for i, def := range defs { |
48 // bind i so that the defer below doesn't get goofed by the loop
variable | 49 // bind i so that the defer below doesn't get goofed by the loop
variable |
49 i := i | 50 i := i |
50 ts[i] = def.mkIter() | 51 ts[i] = def.mkIter() |
51 prefixLens[i] = def.prefixLen | 52 prefixLens[i] = def.prefixLen |
52 defer ts[i].stop() | 53 defer ts[i].stop() |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 // no point to restarting on the
0th index | 86 // no point to restarting on the
0th index |
86 restart = true | 87 restart = true |
87 } | 88 } |
88 } | 89 } |
89 }) | 90 }) |
90 if stop || restart { | 91 if stop || restart { |
91 break | 92 break |
92 } | 93 } |
93 } | 94 } |
94 if stop { | 95 if stop { |
95 » » » return | 96 » » » return nil |
96 } | 97 } |
97 if restart { | 98 if restart { |
98 continue | 99 continue |
99 } | 100 } |
100 | 101 |
101 » » if !cb(suffix) { | 102 » » if err := cb(suffix); err != nil { |
102 » » » return | 103 » » » if err == datastore.Stop { |
| 104 » » » » return nil |
| 105 » » » } |
| 106 » » » return err |
103 } | 107 } |
104 suffix = nil | 108 suffix = nil |
105 skip = -1 | 109 skip = -1 |
106 } | 110 } |
107 } | 111 } |
108 | 112 |
109 type cmd struct { | 113 type cmd struct { |
110 targ []byte | 114 targ []byte |
111 cb func(*gkvlite.Item) | 115 cb func(*gkvlite.Item) |
112 } | 116 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 t.ch <- &cmd{targ, func(i *gkvlite.Item) { | 211 t.ch <- &cmd{targ, func(i *gkvlite.Item) { |
208 defer close(waiter) | 212 defer close(waiter) |
209 | 213 |
210 if i == nil { | 214 if i == nil { |
211 t.stop() | 215 t.stop() |
212 } | 216 } |
213 cb(i) | 217 cb(i) |
214 }} | 218 }} |
215 <-waiter | 219 <-waiter |
216 } | 220 } |
OLD | NEW |