| OLD | NEW |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 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 cloud | 5 package cloud |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "reflect" | 9 "reflect" |
| 10 "strings" | 10 "strings" |
| 11 "time" | 11 "time" |
| 12 | 12 |
| 13 "github.com/luci/luci-go/common/errors" | 13 "github.com/luci/luci-go/common/errors" |
| 14 | 14 |
| 15 ds "github.com/luci/gae/service/datastore" | 15 ds "github.com/luci/gae/service/datastore" |
| 16 "github.com/luci/gae/service/info" | |
| 17 | 16 |
| 18 "cloud.google.com/go/datastore" | 17 "cloud.google.com/go/datastore" |
| 18 "google.golang.org/api/iterator" |
| 19 | 19 |
| 20 "golang.org/x/net/context" | 20 "golang.org/x/net/context" |
| 21 ) | 21 ) |
| 22 | 22 |
| 23 type cloudDatastore struct { | 23 type cloudDatastore struct { |
| 24 client *datastore.Client | 24 client *datastore.Client |
| 25 } | 25 } |
| 26 | 26 |
| 27 func (cds *cloudDatastore) use(c context.Context) context.Context { | 27 func (cds *cloudDatastore) use(c context.Context) context.Context { |
| 28 return ds.SetRawFactory(c, func(ic context.Context) ds.RawInterface { | 28 return ds.SetRawFactory(c, func(ic context.Context) ds.RawInterface { |
| 29 if ns := info.GetNamespace(ic); ns != "" { | |
| 30 ic = datastore.WithNamespace(ic, ns) | |
| 31 } | |
| 32 | |
| 33 return &boundDatastore{ | 29 return &boundDatastore{ |
| 34 Context: ic, | 30 Context: ic, |
| 35 cloudDatastore: cds, | 31 cloudDatastore: cds, |
| 36 transaction: datastoreTransaction(ic), | 32 transaction: datastoreTransaction(ic), |
| 37 kc: ds.GetKeyContext(ic), | 33 kc: ds.GetKeyContext(ic), |
| 38 } | 34 } |
| 39 }) | 35 }) |
| 40 } | 36 } |
| 41 | 37 |
| 42 // boundDatastore is a bound instance of the cloudDatastore installed in the | 38 // boundDatastore is a bound instance of the cloudDatastore installed in the |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 return it.Cursor() | 100 return it.Cursor() |
| 105 } | 101 } |
| 106 | 102 |
| 107 for { | 103 for { |
| 108 var npls *nativePropertyLoadSaver | 104 var npls *nativePropertyLoadSaver |
| 109 if !q.KeysOnly() { | 105 if !q.KeysOnly() { |
| 110 npls = bds.mkNPLS(nil) | 106 npls = bds.mkNPLS(nil) |
| 111 } | 107 } |
| 112 nativeKey, err := it.Next(npls) | 108 nativeKey, err := it.Next(npls) |
| 113 if err != nil { | 109 if err != nil { |
| 114 » » » if err == datastore.Done { | 110 » » » if err == iterator.Done { |
| 115 return nil | 111 return nil |
| 116 } | 112 } |
| 117 return normalizeError(err) | 113 return normalizeError(err) |
| 118 } | 114 } |
| 119 | 115 |
| 120 var pmap ds.PropertyMap | 116 var pmap ds.PropertyMap |
| 121 if npls != nil { | 117 if npls != nil { |
| 122 pmap = npls.pmap | 118 pmap = npls.pmap |
| 123 } | 119 } |
| 124 if err := cb(bds.nativeKeysToGAE(nativeKey)[0], pmap, cursorFn);
err != nil { | 120 if err := cb(bds.nativeKeysToGAE(nativeKey)[0], pmap, cursorFn);
err != nil { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 | 254 |
| 259 func (bds *boundDatastore) CurrentTransaction() ds.Transaction { return bds.tran
saction } | 255 func (bds *boundDatastore) CurrentTransaction() ds.Transaction { return bds.tran
saction } |
| 260 | 256 |
| 261 func (bds *boundDatastore) GetTestable() ds.Testable { return nil } | 257 func (bds *boundDatastore) GetTestable() ds.Testable { return nil } |
| 262 | 258 |
| 263 func (bds *boundDatastore) prepareNativeQuery(fq *ds.FinalizedQuery) *datastore.
Query { | 259 func (bds *boundDatastore) prepareNativeQuery(fq *ds.FinalizedQuery) *datastore.
Query { |
| 264 nq := datastore.NewQuery(fq.Kind()) | 260 nq := datastore.NewQuery(fq.Kind()) |
| 265 if bds.transaction != nil { | 261 if bds.transaction != nil { |
| 266 nq = nq.Transaction(bds.transaction) | 262 nq = nq.Transaction(bds.transaction) |
| 267 } | 263 } |
| 264 if ns := bds.kc.Namespace; ns != "" { |
| 265 nq = nq.Namespace(ns) |
| 266 } |
| 268 | 267 |
| 269 // nativeFilter translates a filter field. If the translation fails, we'
ll | 268 // nativeFilter translates a filter field. If the translation fails, we'
ll |
| 270 // pass the result through to the underlying datastore and allow it to | 269 // pass the result through to the underlying datastore and allow it to |
| 271 // reject it. | 270 // reject it. |
| 272 nativeFilter := func(prop ds.Property) interface{} { | 271 nativeFilter := func(prop ds.Property) interface{} { |
| 273 if np, err := bds.gaePropertyToNative("", prop); err == nil { | 272 if np, err := bds.gaePropertyToNative("", prop); err == nil { |
| 274 return np.Value | 273 return np.Value |
| 275 } | 274 } |
| 276 return prop.Value() | 275 return prop.Value() |
| 277 } | 276 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 return | 450 return |
| 452 } | 451 } |
| 453 | 452 |
| 454 func (bds *boundDatastore) gaeKeysToNative(keys ...*ds.Key) []*datastore.Key { | 453 func (bds *boundDatastore) gaeKeysToNative(keys ...*ds.Key) []*datastore.Key { |
| 455 nativeKeys := make([]*datastore.Key, len(keys)) | 454 nativeKeys := make([]*datastore.Key, len(keys)) |
| 456 for i, key := range keys { | 455 for i, key := range keys { |
| 457 _, _, toks := key.Split() | 456 _, _, toks := key.Split() |
| 458 | 457 |
| 459 var nativeKey *datastore.Key | 458 var nativeKey *datastore.Key |
| 460 for _, tok := range toks { | 459 for _, tok := range toks { |
| 461 » » » nativeKey = datastore.NewKey(bds, tok.Kind, tok.StringID
, tok.IntID, nativeKey) | 460 » » » nativeKey = &datastore.Key{ |
| 461 » » » » Kind: tok.Kind, |
| 462 » » » » ID: tok.IntID, |
| 463 » » » » Name: tok.StringID, |
| 464 » » » » Parent: nativeKey, |
| 465 » » » » Namespace: key.Namespace(), |
| 466 » » » } |
| 462 } | 467 } |
| 463 nativeKeys[i] = nativeKey | 468 nativeKeys[i] = nativeKey |
| 464 } | 469 } |
| 465 return nativeKeys | 470 return nativeKeys |
| 466 } | 471 } |
| 467 | 472 |
| 468 func (bds *boundDatastore) nativeKeysToGAE(nativeKeys ...*datastore.Key) []*ds.K
ey { | 473 func (bds *boundDatastore) nativeKeysToGAE(nativeKeys ...*datastore.Key) []*ds.K
ey { |
| 469 keys := make([]*ds.Key, len(nativeKeys)) | 474 keys := make([]*ds.Key, len(nativeKeys)) |
| 470 toks := make([]ds.KeyTok, 1) | 475 toks := make([]ds.KeyTok, 1) |
| 471 | 476 |
| 472 kc := bds.kc | 477 kc := bds.kc |
| 473 for i, nativeKey := range nativeKeys { | 478 for i, nativeKey := range nativeKeys { |
| 474 toks = toks[:0] | 479 toks = toks[:0] |
| 475 cur := nativeKey | 480 cur := nativeKey |
| 476 for { | 481 for { |
| 477 » » » toks = append(toks, ds.KeyTok{Kind: cur.Kind(), IntID: c
ur.ID(), StringID: cur.Name()}) | 482 » » » toks = append(toks, ds.KeyTok{Kind: cur.Kind, IntID: cur
.ID, StringID: cur.Name}) |
| 478 » » » cur = cur.Parent() | 483 » » » cur = cur.Parent |
| 479 if cur == nil { | 484 if cur == nil { |
| 480 break | 485 break |
| 481 } | 486 } |
| 482 } | 487 } |
| 483 | 488 |
| 484 // Reverse "toks" so we have ancestor-to-child lineage. | 489 // Reverse "toks" so we have ancestor-to-child lineage. |
| 485 for i := 0; i < len(toks)/2; i++ { | 490 for i := 0; i < len(toks)/2; i++ { |
| 486 ri := len(toks) - i - 1 | 491 ri := len(toks) - i - 1 |
| 487 toks[i], toks[ri] = toks[ri], toks[i] | 492 toks[i], toks[ri] = toks[ri], toks[i] |
| 488 } | 493 } |
| 489 » » kc.Namespace = nativeKey.Namespace() | 494 » » kc.Namespace = nativeKey.Namespace |
| 490 keys[i] = kc.NewKeyToks(toks) | 495 keys[i] = kc.NewKeyToks(toks) |
| 491 } | 496 } |
| 492 return keys | 497 return keys |
| 493 } | 498 } |
| 494 | 499 |
| 495 // nativePropertyLoadSaver is a ds.PropertyMap which implements | 500 // nativePropertyLoadSaver is a ds.PropertyMap which implements |
| 496 // datastore.PropertyLoadSaver. | 501 // datastore.PropertyLoadSaver. |
| 497 // | 502 // |
| 498 // It naturally converts between native and GAE properties and values. | 503 // It naturally converts between native and GAE properties and values. |
| 499 type nativePropertyLoadSaver struct { | 504 type nativePropertyLoadSaver struct { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 case datastore.ErrNoSuchEntity: | 578 case datastore.ErrNoSuchEntity: |
| 574 return ds.ErrNoSuchEntity | 579 return ds.ErrNoSuchEntity |
| 575 case datastore.ErrConcurrentTransaction: | 580 case datastore.ErrConcurrentTransaction: |
| 576 return ds.ErrConcurrentTransaction | 581 return ds.ErrConcurrentTransaction |
| 577 case datastore.ErrInvalidKey: | 582 case datastore.ErrInvalidKey: |
| 578 return ds.ErrInvalidKey | 583 return ds.ErrInvalidKey |
| 579 default: | 584 default: |
| 580 return err | 585 return err |
| 581 } | 586 } |
| 582 } | 587 } |
| OLD | NEW |