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

Side by Side Diff: filter/dscache/ds.go

Issue 1269113005: A transparent cache for datastore, backed by memcache. (Closed) Base URL: https://github.com/luci/gae.git@add_meta
Patch Set: add test for per-model expiration Created 5 years, 4 months 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
(Empty)
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
3 // found in the LICENSE file.
4
5 package dscache
6
7 import (
8 "time"
9
10 ds "github.com/luci/gae/service/datastore"
11 "github.com/luci/gae/service/memcache"
12 "golang.org/x/net/context"
13 )
14
15 type dsCache struct {
16 ds.RawInterface
17
18 *supportContext
19 }
20
21 var _ ds.RawInterface = (*dsCache)(nil)
22
23 func (d *dsCache) DeleteMulti(keys []ds.Key, cb ds.DeleteMultiCB) error {
24 return d.mutation(keys, func() error {
25 return d.RawInterface.DeleteMulti(keys, cb)
26 })
27 }
28
29 func (d *dsCache) PutMulti(keys []ds.Key, vals []ds.PropertyMap, cb ds.PutMultiC B) error {
30 return d.mutation(keys, func() error {
31 return d.RawInterface.PutMulti(keys, vals, cb)
32 })
33 }
34
35 func (d *dsCache) GetMulti(keys []ds.Key, metas ds.MultiMetaGetter, cb ds.GetMul tiCB) error {
36 lockItems, nonce := d.mkRandLockItems(keys, metas)
37 if len(lockItems) == 0 {
38 return d.RawInterface.GetMulti(keys, metas, cb)
39 }
40
41 if err := d.mc.AddMulti(lockItems); err != nil {
Vadim Sh. 2015/08/06 01:23:33 what happens if only one item is failed to lock? (
iannucci 2015/08/06 02:37:33 it's not atomic, but it doesn't matter. Either:
42 d.log.Errorf("dscache: mc.AddMulti: %s", err)
dnj 2015/08/05 18:32:17 (Debugf)
iannucci 2015/08/06 01:54:01 Did warn
43 }
44 if err := d.mc.GetMulti(lockItems); err != nil {
45 d.log.Errorf("dscache: mc.GetMulti: %s", err)
dnj 2015/08/05 18:32:17 (Debugf)
iannucci 2015/08/06 01:54:01 Did warn
46 }
47
48 p := makePlan(d.aid, d.ns, d.log, &facts{keys, metas, lockItems, nonce})
49
50 if !p.empty() {
dnj 2015/08/05 18:32:17 Invert: if p.empty() { return nil }
iannucci 2015/08/06 01:54:01 can't, this modifies p.decoded for the loop below
dnj 2015/08/07 16:30:06 Acknowledged.
51 toCas := []memcache.Item{}
dnj 2015/08/05 18:32:17 Might as well optimistically allocate capacity.
iannucci 2015/08/06 01:54:01 Eh... estimating the amount to allocate is hard en
dnj 2015/08/07 16:30:06 Acknowledged.
52 j := 0
53 err := d.RawInterface.GetMulti(p.toGet, p.toGetMeta, func(pm ds. PropertyMap, err error) {
54 i := p.idxMap[j]
55 toSave := p.toSave[j]
Vadim Sh. 2015/08/06 01:23:33 ah, I guess appending nils is by design. Looked we
Vadim Sh. 2015/08/06 01:23:33 nit: move j++ to this line. I forgot what "j" was
56
57 data := []byte(nil)
58
59 // 0 == do not save
60 // 1 == save
61 // 2 == lock until next put
62 saveState := 1
63 if err == nil {
64 p.decoded[i] = pm
65 if toSave != nil {
66 data = encodeItemValue(pm)
67 if len(data) > internalValueSizeLimit {
68 saveState = 2
Vadim Sh. 2015/08/06 01:23:33 heh... smart :)
iannucci 2015/08/06 02:37:33 managed to reduce this to just a boolean, but yeah
69 d.log.Warningf("dscache: encoded entity too big (%d/%d)!",
70 len(data), internalValue SizeLimit)
71 }
72 }
73 }
74
75 if err != nil {
dnj 2015/08/05 18:32:17 } else {
iannucci 2015/08/06 01:54:01 Done.
76 p.lme.Assign(i, err)
77 if err != ds.ErrNoSuchEntity {
78 saveState = 0
79 }
80 }
81
82 if saveState > 0 && toSave != nil {
83 if saveState == 1 { // save
84 expSecs := metas.GetMetaDefault(i, Cache ExpirationMeta, CacheTimeSeconds).(int64)
85 toSave.SetFlags(uint32(ItemHasData))
86 toSave.SetExpiration(time.Duration(expSe cs) * time.Second)
87 toSave.SetValue(data)
88 } else {
89 // Set a lock with an infinite timeout. No one else should try to
90 // serialize this item to memcache until something Put/Delete's it.
91 toSave.SetFlags(uint32(ItemHasLock))
92 toSave.SetExpiration(0)
93 toSave.SetValue(nonce)
94 }
95 toCas = append(toCas, toSave)
96 }
97
98 j++
99 })
100 if err != nil {
101 return err
102 }
103 if len(toCas) > 0 {
104 if err := d.mc.CompareAndSwapMulti(toCas); err != nil {
105 d.log.Errorf("dscache: CompareAndSwapMulti: %s", err)
106 }
107 }
108 }
109
110 for i, dec := range p.decoded {
111 cb(dec, p.lme.GetOne(i))
112 }
113
114 return nil
115 }
116
117 func (d *dsCache) RunInTransaction(f func(context.Context) error, opts *ds.Trans actionOptions) error {
118 txnState := dsTxnState{}
119 err := d.RawInterface.RunInTransaction(func(ctx context.Context) error {
120 txnState.Reset()
121 err := f(context.WithValue(ctx, dsTxnCacheKey, &txnState))
122 if err == nil {
123 txnState.Apply(d.supportContext)
124 }
125 return err
126 }, opts)
127 if err == nil {
128 txnState.Release(d.supportContext)
129 }
130 return err
131 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698