示例#1
0
// CAS does an atomic compare-and-swap on a counter.
func (Example) CAS(c context.Context, r *CASReq) (err error) {
	success := false
	c = prod.Use(c)
	err = rdsS.Get(c).RunInTransaction(func(c context.Context) error {
		rds := rdsS.Get(c)
		key := rds.NewKey("Counter", r.Name, 0, nil)
		ctr := &Counter{}
		pls := rdsS.GetPLS(ctr)
		if err := rds.Get(key, pls); err != nil {
			return err
		}
		if ctr.Val == r.OldVal {
			success = true
			ctr.Val = r.NewVal
			_, err := rds.Put(key, pls)
			return err
		}
		success = false
		return nil
	}, nil)
	if err == nil && !success {
		err = endpoints.ConflictError
	}
	return
}
示例#2
0
func TestGetEntityGroupVersion(t *testing.T) {
	t.Parallel()

	Convey("GetEntityGroupVersion", t, func() {
		c := memory.Use(context.Background())
		c, fb := featureBreaker.FilterRDS(c, errors.New("INTERNAL_ERROR"))
		rds := rawdatastore.Get(c)

		aKey, err := rds.Put(rds.NewKey("A", "", 0, nil), rawdatastore.PropertyMap{
			"Val": {rawdatastore.MkProperty(10)},
		})
		So(err, ShouldBeNil)

		v, err := GetEntityGroupVersion(c, aKey)
		So(err, ShouldBeNil)
		So(v, ShouldEqual, 1)

		So(rds.Delete(aKey), ShouldBeNil)

		v, err = GetEntityGroupVersion(c, rds.NewKey("madeUp", "thing", 0, aKey))
		So(err, ShouldBeNil)
		So(v, ShouldEqual, 2)

		v, err = GetEntityGroupVersion(c, rds.NewKey("madeUp", "thing", 0, nil))
		So(err, ShouldBeNil)
		So(v, ShouldEqual, 0)

		fb.BreakFeatures(nil, "Get")

		v, err = GetEntityGroupVersion(c, aKey)
		So(err.Error(), ShouldContainSubstring, "INTERNAL_ERROR")
	})
}
示例#3
0
// Add adds a value to the current counter, and returns the old+new values. It
// may cause a counter to come into existance.
func (Example) Add(c context.Context, r *AddReq) (rsp *AddRsp, err error) {
	rsp = &AddRsp{}

	c = prod.Use(c)
	err = rdsS.Get(c).RunInTransaction(func(c context.Context) error {
		rds := rdsS.Get(c)
		ctr := &Counter{}
		pls := rdsS.GetPLS(ctr)
		key := rds.NewKey("Counter", r.Name, 0, nil)
		if err := rds.Get(key, pls); err != nil && err != rdsS.ErrNoSuchEntity {
			return err
		}
		rsp.Prev = ctr.Val
		ctr.Val += r.Delta
		rsp.Cur = ctr.Val
		_, err := rds.Put(key, pls)
		return err
	}, nil)
	return
}
// CurrentValue gets the current value of a counter (duh)
func (Example) CurrentValue(c context.Context, r *CurrentValueReq) (rsp *CurrentValueRsp, err error) {
	c = prod.Use(c)
	rds := rdsS.Get(c)

	key := rds.NewKey("Counter", r.Name, 0, nil)
	ctr := &Counter{}
	if err = rds.Get(key, rdsS.GetPLS(ctr)); err != nil {
		return
	}

	rsp = &CurrentValueRsp{ctr.Val}
	return
}
示例#5
0
// GetEntityGroupVersion returns the entity group version for the entity group
// containing root. If the entity group doesn't exist, this function will return
// zero and a nil error.
func GetEntityGroupVersion(c context.Context, root rdsS.Key) (int64, error) {
	for root.Parent() != nil {
		root = root.Parent()
	}
	rds := rdsS.Get(c)
	egm := &EntityGroupMeta{}
	err := rds.Get(rds.NewKey("__entity_group__", "", 1, root), rdsS.GetPLS(egm))
	ret := egm.Version
	if err == rdsS.ErrNoSuchEntity {
		// this is OK for callers. The version of the entity group is effectively 0
		// in this case.
		err = nil
	}
	return ret, err
}
示例#6
0
// List returns a list of all the counters. Note that it's very poorly
// implemented! It's completely unpaged. I don't care :).
func (Example) List(c context.Context) (rsp *ListRsp, err error) {
	rds := rawdatastore.Get(prod.Use(c))
	rsp = &ListRsp{}
	dst := []rawdatastore.PropertyMap{}
	_, err = rds.GetAll(rds.NewQuery("Counter"), &dst)
	if err != nil {
		return
	}
	rsp.Counters = make([]Counter, len(dst))
	for i, m := range dst {
		if err = rawdatastore.GetPLS(rsp.Counters[i]).Load(m); err != nil {
			return
		}
	}
	return
}