OLD | NEW |
| (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 dumbCounter | |
6 | |
7 import ( | |
8 "github.com/GoogleCloudPlatform/go-endpoints/endpoints" | |
9 dstore "github.com/luci/gae/service/datastore" | |
10 "golang.org/x/net/context" | |
11 ) | |
12 | |
13 // CASReq is the input for the CAS RPC | |
14 type CASReq struct { | |
15 Name string `endpoints:"required"` | |
16 | |
17 OldVal int64 `json:",string"` | |
18 NewVal int64 `json:",string"` | |
19 } | |
20 | |
21 // CAS does an atomic compare-and-swap on a counter. | |
22 func (e *Example) CAS(c context.Context, r *CASReq) (err error) { | |
23 c, err = e.Use(c, casMethodInfo) | |
24 if err != nil { | |
25 return | |
26 } | |
27 | |
28 success := false | |
29 err = dstore.Get(c).RunInTransaction(func(c context.Context) error { | |
30 ds := dstore.Get(c) | |
31 ctr := &Counter{Name: r.Name} | |
32 if err := ds.Get(ctr); err != nil { | |
33 return err | |
34 } | |
35 if ctr.Val == r.OldVal { | |
36 success = true | |
37 ctr.Val = r.NewVal | |
38 return ds.Put(ctr) | |
39 } | |
40 success = false | |
41 return nil | |
42 }, nil) | |
43 if err == nil && !success { | |
44 err = endpoints.ConflictError | |
45 } | |
46 return | |
47 } | |
48 | |
49 var casMethodInfo = &endpoints.MethodInfo{ | |
50 Path: "counter/{Name}/cas", | |
51 Desc: "Compare and swap a counter value", | |
52 } | |
OLD | NEW |