Example #1
0
/*
LockedBy will return whether this KeyLock is actually locked in the database and who holds it now.
*/
func (self *KeyLock) LockedBy(c GAEContext) (isLocked bool, lockedBy key.Key, err error) {
	existingLock := &KeyLock{Id: self.Id}
	if err = gae.GetById(c, existingLock); err != nil {
		if _, ok := err.(gae.ErrNoSuchEntity); ok {
			err = nil
			return
		} else {
			return
		}
	}
	isLocked = true
	lockedBy = existingLock.Entity
	return
}
Example #2
0
/*
Unlock will unlock this KeyLock and make its Id (and the value it is based on) available for other locks.
*/
func (self *KeyLock) Unlock(c GAEContext) (err error) {
	snapshot := *self
	return c.Transaction(func(c GAEContext) (err error) {
		*self = snapshot
		existingLock := &KeyLock{Id: self.Id}
		if err = gae.GetById(c, existingLock); err != nil {
			return
		}
		if existingLock.Entity != self.Entity {
			err = errors.Errorf("%+v doesn't own %v", self, self.Entity)
			return
		}
		err = gae.Del(c, existingLock)
		return
	}, false)
}
Example #3
0
func testGet(c gaecontext.HTTPContext) {
	gae.DelAll(c, &Ts{})
	k, err := key.For(&Ts{}, "", 0, "")
	if err != nil {
		panic(err)
	}
	t := &Ts{
		Id:   k,
		Name: "the t",
		Age:  12,
	}
	if err := gae.Put(c, t); err != nil {
		panic(err)
	}
	wantedProcesses := []string{"BeforeCreate", "BeforeSave", "AfterCreate", "AfterSave"}
	if !reflect.DeepEqual(t.Processes, wantedProcesses) {
		panic("wrong processes!")
	}
	if t.Id.IntID() == 0 {
		panic("shouldn't be zero")
	}
	t2 := &Ts{Id: t.Id}
	if err := gae.GetById(c, t2); err != nil {
		panic(err)
	}
	if !t.Equal(t2) {
		panic("1 should be equal")
	}
	wantedProcesses = []string{"BeforeCreate", "BeforeSave", "AfterLoad"}
	if !reflect.DeepEqual(t2.Processes, wantedProcesses) {
		panic(fmt.Sprintf("wrong processes! wanted %+v but got %+v", wantedProcesses, t2.Processes))
	}
	t2.Age = 13
	if err := gae.Put(c, t2); err != nil {
		panic(err)
	}
	wantedProcesses = append(wantedProcesses, "BeforeUpdate", "BeforeSave", "AfterUpdate", "AfterSave")
	if !reflect.DeepEqual(t2.Processes, wantedProcesses) {
		panic("wrong processes!")
	}
	if err := gae.Del(c, t2); err != nil {
		panic(err)
	}
	if !reflect.DeepEqual(t2.Processes, wantedProcesses) {
		panic(fmt.Errorf("got %+v, wanted %+v", t2.Processes, wantedProcesses))
	}
}
Example #4
0
/*
Lock will try to lock this KeyLock and make its Id (and the value it is based on) unavailable for other locks.
*/
func (self *KeyLock) Lock(c GAEContext) error {
	snapshot := *self
	return c.Transaction(func(c GAEContext) (err error) {
		*self = snapshot
		existingLock := &KeyLock{Id: self.Id}
		err = gae.GetById(c, existingLock)
		if _, ok := err.(gae.ErrNoSuchEntity); ok {
			err = nil
		} else if err == nil {
			err = ErrLockTaken{
				Key:    self.Id,
				Entity: existingLock.Entity,
				Stack:  utils.Stack(),
			}
		}
		if err != nil {
			return
		}
		err = gae.Put(c, self)
		return
	}, false)
}
Example #5
0
func testMemcacheMulti(c gaecontext.HTTPContext) {
	doTest1 := func(c gaecontext.HTTPContext) (ts1, ts2 *MemMulTS) {
		gae.DelAll(c, &MemMulTS{})
		var err error
		ts1 = &MemMulTS{}
		if ts1.Id, err = key.For(ts1, "", 0, ""); err != nil {
			panic(err)
		}
		ts2 = &MemMulTS{}
		if ts2.Id, err = key.For(ts2, "", 0, ""); err != nil {
			panic(err)
		}
		if err := gae.Put(c, ts1); err != nil {
			panic(err)
		}
		if err := gae.Put(c, ts2); err != nil {
			panic(err)
		}
		return
	}
	doTest2 := func(c gaecontext.HTTPContext, ts1, ts2 *MemMulTS) {
		load1 := &MemMulTS{}
		load2 := &MemMulTS{}
		load3 := &MemMulTS{}
		fakeId, err := key.New("MemMulTS", "hehu", 0, "")
		if err != nil {
			return
		}
		fgen := func(id key.Key) func() (result interface{}, err error) {
			return func() (result interface{}, err error) {
				ts := &MemMulTS{
					Id: id,
				}
				if err = gae.GetById(c, ts); err != nil {
					if _, ok := err.(gae.ErrNoSuchEntity); ok {
						err = nil
						return
					}
					return
				}
				result = ts
				return
			}
		}
		if err := memcache.MemoizeMulti(c, []string{
			ts1.Id.Encode(),
			ts2.Id.Encode(),
			fakeId.Encode(),
		}, []interface{}{
			load1,
			load2,
			load3,
		}, []func() (interface{}, error){
			fgen(ts1.Id),
			fgen(ts2.Id),
			fgen(fakeId),
		}); err != nil {
			if err[0] != nil || err[1] != nil || err[2] != memcache.ErrCacheMiss {
				for _, serr := range err {
					c.Infof("Error: %v", serr)
				}
				panic(err)
			}
		}
		if load1.Id != ts1.Id {
			panic(fmt.Errorf("wrong id, wanted %v but got %v", ts1.Id, load1.Id))
		}
		if load2.Id != ts2.Id {
			panic("wrong id")
		}
		if load3.Id != "" {
			panic("wrong id")
		}

		load1 = &MemMulTS{}
		load2 = &MemMulTS{}
		load3 = &MemMulTS{}
		if err := memcache.MemoizeMulti(c, []string{
			ts1.Id.Encode(),
			ts2.Id.Encode(),
			fakeId.Encode(),
		}, []interface{}{
			load1,
			load2,
			load3,
		}, []func() (interface{}, error){
			fgen(ts1.Id),
			fgen(ts2.Id),
			fgen(fakeId),
		}); err != nil {
			if err[0] != nil || err[1] != nil || err[2] != memcache.ErrCacheMiss {
				panic(err)
			}
		}
		if load1.Id != ts1.Id {
			panic(fmt.Errorf("wrong id, wanted %v but got %v", ts1.Id, load1.Id))
		}
		if load2.Id != ts2.Id {
			panic("wrong id")
		}
		if load3.Id != "" {
			panic("wrong id")
		}
	}
	ts1, ts2 := doTest1(c)
	doTest2(c, ts1, ts2)
	ts1, ts2 = doTest1(c)
	c.Transaction(func(c gaecontext.HTTPContext) (err error) {
		doTest2(c, ts1, ts2)
		return
	}, true)
}
Example #6
0
func testMemcacheDeletion(c gaecontext.HTTPContext) {
	t1 := &Ts{}
	parentKey, err := key.For(t1, "parent", 0, "")
	if err != nil {
		panic(err)
	}
	t1.Id, err = key.For(t1, "", 0, parentKey)
	if err != nil {
		panic(err)
	}
	t1.Name = "hej"
	if err := gae.Put(c, t1); err != nil {
		panic(err)
	}
	t2 := &Ts{Id: t1.Id}
	if err := gae.GetById(c, t2); err != nil {
		panic(err)
	}
	if t2.Name != "hej" {
		panic("wrong name")
	}

	time.Sleep(time.Second)
	found := []Ts{}
	if err := findTsByName(c, &found, "hej"); err != nil {
		panic(err)
	}
	if len(found) != 1 {
		panic("wrong len")
	}
	if found[0].Name != "hej" {
		panic("wrong name")
	}
	found = []Ts{}
	if err := findTsByAncestorAndName(c, &found, parentKey, "hej"); err != nil {
		panic(err)
	}
	if len(found) != 1 {
		panic("wrong len")
	}
	if found[0].Name != "hej" {
		panic("wrong name")
	}

	t1.Name = "hehu"
	if err := gae.Put(c, t1); err != nil {
		panic(err)
	}

	time.Sleep(time.Second)
	found = []Ts{}
	if err := findTsByName(c, &found, "hej"); err != nil {
		panic(err)
	}
	if len(found) != 0 {
		panic("wrong len")
	}
	found = []Ts{}
	if err := findTsByAncestorAndName(c, &found, parentKey, "hej"); err != nil {
		panic(err)
	}
	if len(found) != 0 {
		panic("wrong len")
	}
	found = []Ts{}
	if err := findTsByName(c, &found, "hehu"); err != nil {
		panic(err)
	}
	if len(found) != 1 {
		panic("wrong len")
	}
	if found[0].Name != "hehu" {
		panic("wrong name")
	}
	found = []Ts{}
	if err := findTsByAncestorAndName(c, &found, parentKey, "hehu"); err != nil {
		panic(err)
	}
	if len(found) != 1 {
		panic("wrong len")
	}
	if found[0].Name != "hehu" {
		panic("wrong name")
	}

	if err := c.Transaction(func(c gaecontext.HTTPContext) (err error) {
		t1.Name = "blapp"
		err = gae.Put(c, t1)
		return
	}, false); err != nil {
		panic(err)
	}

	time.Sleep(time.Second)
	found = []Ts{}
	if err := findTsByName(c, &found, "hehu"); err != nil {
		panic(err)
	}
	if len(found) != 0 {
		panic("wrong len")
	}
	found = []Ts{}
	if err := findTsByAncestorAndName(c, &found, parentKey, "hehu"); err != nil {
		panic(err)
	}
	if len(found) != 0 {
		panic("wrong len")
	}
	found = []Ts{}
	if err := findTsByName(c, &found, "blapp"); err != nil {
		panic(err)
	}
	if len(found) != 1 {
		panic("wrong len")
	}
	if found[0].Name != "blapp" {
		panic("wrong name")
	}
	found = []Ts{}
	if err := findTsByAncestorAndName(c, &found, parentKey, "blapp"); err != nil {
		panic(err)
	}
	if len(found) != 1 {
		panic("wrong len")
	}
	if found[0].Name != "blapp" {
		panic("wrong name")
	}

}