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 "errors" | 8 "errors" |
9 "fmt" | 9 "fmt" |
10 "io" | |
11 "io/ioutil" | |
12 "os" | |
13 "path/filepath" | |
14 "runtime" | |
10 | 15 |
11 "golang.org/x/net/context" | 16 "golang.org/x/net/context" |
12 | 17 |
18 "gopkg.in/yaml.v2" | |
19 | |
13 ds "github.com/luci/gae/service/datastore" | 20 ds "github.com/luci/gae/service/datastore" |
14 "github.com/luci/gae/service/info" | 21 "github.com/luci/gae/service/info" |
15 ) | 22 ) |
16 | 23 |
24 //////////////////////////////////// utility /////////////////////////////////// | |
25 | |
26 // fileExists returns true if the file f exists | |
27 func fileExists(f string) bool { | |
28 if _, err := os.Stat(f); os.IsNotExist(err) { | |
29 return false | |
30 } | |
31 return true | |
32 } | |
33 | |
17 //////////////////////////////////// public //////////////////////////////////// | 34 //////////////////////////////////// public //////////////////////////////////// |
18 | 35 |
19 // useRDS adds a gae.Datastore implementation to context, accessible | 36 // useRDS adds a gae.Datastore implementation to context, accessible |
20 // by gae.GetDS(c) | 37 // by gae.GetDS(c) |
21 func useRDS(c context.Context) context.Context { | 38 func useRDS(c context.Context) context.Context { |
22 return ds.SetRawFactory(c, func(ic context.Context, wantTxn bool) ds.Raw Interface { | 39 return ds.SetRawFactory(c, func(ic context.Context, wantTxn bool) ds.Raw Interface { |
23 ns := curGID(ic).namespace | 40 ns := curGID(ic).namespace |
24 maybeTxnCtx := cur(ic) | 41 maybeTxnCtx := cur(ic) |
25 | 42 |
26 needResetCtx := false | 43 needResetCtx := false |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 } | 175 } |
159 | 176 |
160 func (d *dsImpl) DisableSpecialEntities(enabled bool) { | 177 func (d *dsImpl) DisableSpecialEntities(enabled bool) { |
161 d.data.setDisableSpecialEntities(enabled) | 178 d.data.setDisableSpecialEntities(enabled) |
162 } | 179 } |
163 | 180 |
164 func (d *dsImpl) Testable() ds.Testable { | 181 func (d *dsImpl) Testable() ds.Testable { |
165 return d | 182 return d |
166 } | 183 } |
167 | 184 |
185 func (d *dsImpl) ParseIndexYAML(content io.Reader) []*ds.IndexDefinition { | |
186 var m map[string][]*ds.IndexDefinition | |
187 serialized, err := ioutil.ReadAll(content) | |
188 | |
189 if err != nil { | |
190 panic(fmt.Errorf("failed to parse index YAML: %v", content)) | |
191 } | |
192 | |
193 if err := yaml.Unmarshal(serialized, &m); err != nil { | |
194 panic(fmt.Errorf("failed to parse index YAML: %s", serialized)) | |
195 } | |
196 | |
197 if _, ok := m["indexes"]; !ok { | |
198 panic(fmt.Errorf("failed to parse index YAML: %s", serialized)) | |
199 } | |
200 | |
201 return m["indexes"] | |
202 } | |
203 | |
204 func (d *dsImpl) FindAndAddIndexYAML() { | |
205 // get path of current source file | |
206 _, f, _, _ := runtime.Caller(1) | |
207 dir, err := filepath.Abs(filepath.Dir(f)) | |
208 | |
209 if err != nil { | |
210 panic(fmt.Errorf("failed to find index YAML file")) | |
iannucci
2016/01/13 19:12:20
this error should be changed to be more meaningful
nishanths (utexas)
2016/01/14 21:12:56
Done. Also implemented "look until you find _test
| |
211 } | |
212 | |
213 for { | |
214 var filename string | |
215 | |
216 if fileExists(filepath.Join(dir, "index.yml")) { | |
dnj
2016/01/13 16:16:40
nit: Consider making this loop over a slice of can
iannucci
2016/01/13 19:12:20
Moreover, doing os.Open directly avoids an (admitt
nishanths (utexas)
2016/01/14 21:12:56
Thanks for the tip!
nishanths (utexas)
2016/01/14 21:12:56
Done.
| |
217 filename = filepath.Join(dir, "index.yml") | |
218 } else if fileExists(filepath.Join(dir, "index.yaml")) { | |
219 filename = filepath.Join(dir, "index.yaml") | |
220 } | |
221 | |
222 if filename != "" { | |
223 // found index file | |
224 // read contents | |
225 file, err := os.Open(filename) | |
226 | |
227 if err != nil { | |
228 panic(fmt.Errorf("failed to open index YAML file : %s", filename)) | |
229 } | |
230 | |
231 defer file.Close() | |
232 | |
233 // parse the bytes that were read | |
234 idxs := d.ParseIndexYAML(file) | |
235 d.AddIndexes(idxs...) | |
236 break | |
237 } | |
238 | |
239 // already at root of drive | |
240 if dir == "/" && filepath.Dir(dir) == "/" { | |
dnj
2016/01/13 16:16:40
This is not a cross-platform check, as on Windows
nishanths (utexas)
2016/01/14 21:12:56
Done.
| |
241 panic(fmt.Errorf("failed to find index YAML file")) | |
242 } | |
243 | |
244 // to parent directory | |
245 dir = filepath.Dir(dir) | |
246 } | |
247 } | |
248 | |
168 ////////////////////////////////// txnDsImpl /////////////////////////////////// | 249 ////////////////////////////////// txnDsImpl /////////////////////////////////// |
169 | 250 |
170 type txnDsImpl struct { | 251 type txnDsImpl struct { |
171 data *txnDataStoreData | 252 data *txnDataStoreData |
172 ns string | 253 ns string |
173 } | 254 } |
174 | 255 |
175 var _ ds.RawInterface = (*txnDsImpl)(nil) | 256 var _ ds.RawInterface = (*txnDsImpl)(nil) |
176 | 257 |
177 func (d *txnDsImpl) AllocateIDs(incomplete *ds.Key, n int) (int64, error) { | 258 func (d *txnDsImpl) AllocateIDs(incomplete *ds.Key, n int) (int64, error) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 return countQuery(fq, d.data.parent.aid, d.ns, true, d.data.snap, d.data .snap) | 299 return countQuery(fq, d.data.parent.aid, d.ns, true, d.data.snap, d.data .snap) |
219 } | 300 } |
220 | 301 |
221 func (*txnDsImpl) RunInTransaction(func(c context.Context) error, *ds.Transactio nOptions) error { | 302 func (*txnDsImpl) RunInTransaction(func(c context.Context) error, *ds.Transactio nOptions) error { |
222 return errors.New("datastore: nested transactions are not supported") | 303 return errors.New("datastore: nested transactions are not supported") |
223 } | 304 } |
224 | 305 |
225 func (*txnDsImpl) Testable() ds.Testable { | 306 func (*txnDsImpl) Testable() ds.Testable { |
226 return nil | 307 return nil |
227 } | 308 } |
OLD | NEW |