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

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

Issue 1269113005: A transparent cache for datastore, backed by memcache. (Closed) Base URL: https://github.com/luci/gae.git@add_meta
Patch Set: some minor comments 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 "sync"
9
10 "github.com/luci/gae/service/datastore"
11 "github.com/luci/gae/service/memcache"
12 log "github.com/luci/luci-go/common/logging"
13 )
14
15 type dsTxnState struct {
16 sync.Mutex
17
18 toLock []memcache.Item
19 toDelete map[string]struct{}
20 }
21
22 // reset sets the transaction state back to its 0 state. This is used so that
23 // when a transaction retries the function, we don't accidentally leak state
24 // from one function to the next.
25 func (s *dsTxnState) reset() {
26 s.Lock()
27 defer s.Unlock()
28 // reduce capacity back to 0, but keep the allocated array. If the trans action
29 // body retries, it'll probably end up re-allocating the same amount of space
30 // anyway.
31 s.toLock = s.toLock[:0]
32 s.toDelete = make(map[string]struct{}, len(s.toDelete))
33 }
34
35 // apply is called right before the trasnaction is about to commit. It's job
36 // is to lock all the to-be-changed memcache keys.
37 func (s *dsTxnState) apply(sc *supportContext) error {
38 s.Lock()
39 defer s.Unlock()
40
41 // this is a hard failure. No mutation can occur if we're unable to set
42 // locks out. See "DANGER ZONE" in the docs.
43 err := sc.mc.SetMulti(s.toLock)
44 if err != nil {
45 (log.Fields{log.ErrorKey: err}).Errorf(
46 sc.c, "dscache: HARD FAILURE: dsTxnState.apply(): mc.Set Multi")
47 }
48 return err
49 }
50
51 // release is called right after a successful transaction completion. It's job
52 // is to clear out all the locks, if possible (but if not, no worries,
53 // they'll expire soon).
54 func (s *dsTxnState) release(sc *supportContext) {
55 s.Lock()
56 defer s.Unlock()
57
58 delKeys := make([]string, 0, len(s.toDelete))
59 for k := range s.toDelete {
60 delKeys = append(delKeys, k)
61 }
62
63 err := sc.mc.DeleteMulti(delKeys)
64 if err != nil {
65 (log.Fields{log.ErrorKey: err}).Warningf(
66 sc.c, "dscache: txn.release: memcache.DeleteMulti")
67 }
68 }
69
70 func (s *dsTxnState) add(sc *supportContext, keys []datastore.Key) {
71 lockItems, lockKeys := sc.mkAllLockItems(keys)
72 if lockItems == nil {
73 return
74 }
75
76 s.Lock()
77 defer s.Unlock()
78
79 for i, li := range lockItems {
80 k := lockKeys[i]
81 if _, ok := s.toDelete[k]; !ok {
82 s.toLock = append(s.toLock, li)
83 s.toDelete[k] = struct{}{}
84 }
85 }
86 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698