Chromium Code Reviews| 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 |