Example #1
0
File: email.go Project: gaego/user
func Get(c appengine.Context, address string) (*Email, error) {
	e := New()
	key := datastore.NewKey(c, "Email", strings.ToLower(address), 0, nil)
	err := ds.Get(c, key, e)
	e.Key = key
	return e, err
}
Example #2
0
// Get is a convience method for retrieveing an entity from the ds.
func Get(c appengine.Context, id string) (up *Profile, err error) {
	up = &Profile{}
	key := datastore.NewKey(c, "AuthProfile", id, 0, nil)
	err = ds.Get(c, key, up)
	up.Key = key
	up.Decode()
	return
}
Example #3
0
File: user.go Project: gaego/user
// Get is a convience method for retrieveing an entity foom the store.
func Get(c appengine.Context, id string) (u *User, err error) {
	u = &User{}
	key := datastore.NewKey(c, "User", id, 0, nil)
	err = ds.Get(c, key, u)
	u.Key = key
	u.Decode()
	return u, err
}
Example #4
0
File: token.go Project: gaego/user
func Get(c context.Context, token string) (e *Token, err error) {
	e = &Token{}
	k := datastore.NewKey(c, "UserToken", token, 0, nil)
	if err = ds.Get(c, k, e); err != nil {
		return nil, err
	}
	e.Key = k
	e.Token = k.StringID()
	return
}
Example #5
0
// Get retieves a Config using the string key. If Config is not found
// it returns ds/error.ErrNoSuchEntity.
func Get(c appengine.Context, key string) (cnfg *Config, err error) {

	cnfg = new(Config)
	cnfg.SetKey(c, key)
	err = ds.Get(c, cnfg.Key, cnfg)
	if err != nil {
		return
	}
	err = cnfg.decode()
	return
}
Example #6
0
// Current checks the requesting User's session to see if they have an
// account. If they do, the provided User struct is populated with the
// information that is saved in the datastore. If they don't an error is
// returned.
func Current(r *http.Request) (*User, error) {
	id, _ := CurrentUserID(r)

	if id != "" {
		c := context.NewContext(r)
		u := new(User)
		key := datastore.NewKey(c, "User", id, 0, nil)
		err := ds.Get(c, key, u)
		u.Key = key
		return u, err
	}
	return nil, ErrNoLoggedInUser
}
Example #7
0
func actualGetPeers(future *getPeersFuture) {
	defer close(future.errorChannel)
	defer close(future.resultChannel)

	future.ctx.Debugf("[GetPeers] Getting peer list (%s)", future.hash)
	var res []*Peer
	if _, err := memcache.Gob.Get(future.ctx, getHashKey(future.ctx, future.hash), &res); err == nil {
		if len(res) == 0 {
			future.ctx.Debugf("[GetPeers] Cached peer list is empty")

			future.ctx.Debugf("[GetPeers] Successfully retrieved peer list from memcache (empty)")
			return
		}

		future.ctx.Debugf("[GetPeers] Valid list exists in memcache")

		if len(future.include) > 0 {
			peerToInclude := new(Peer)
			if err := ds.Get(future.ctx, getPeerKey(future.ctx, future.hash, future.include), peerToInclude); err != nil {
				if err != dserrors.ErrNoSuchEntity {
					future.ctx.Errorf("[GetPeers] Failed to include peer: %s", err)
				} else {
					future.ctx.Debugf("[GetPeers] Failed to include peer because peer doesn't exist")
				}
			} else {
				res = append(res, peerToInclude)
			}
		}

		future.ctx.Debugf("[GetPeers] Filtering peers")
		peersFiltered := make([]*Peer, 0, len(res))

		currentTime := time.Now()
		foundInclude := false

		for _, peer := range res {
			if !peer.Expires.After(currentTime) {
				continue
			} else if peer.ID == future.include {
				if foundInclude {
					continue
				} else {
					foundInclude = true
				}
			}

			peer.Key = getPeerKey(future.ctx, future.hash, peer.ID)

			// We have to copy the peer to this because the "peer" variable from the loop will always be at the same address.
			peersFiltered = append(peersFiltered, peer)
		}

		// This looks so ugly. TODO: Clean this up
		var filteredLength int64 = int64(len(peersFiltered))
		if filteredLength <= future.numberWanted {
			future.ctx.Debugf("[GetPeers] Returning all %d filtered peers: request wants more than we have", filteredLength)

			for _, peer := range peersFiltered {
				future.resultChannel <- peer
			}
			return
		}

		giveNumber := int64(math.Min(float64(filteredLength), float64(future.numberWanted)))
		given := make(map[int64]bool)
		randomGen := rand.New(rand.NewSource(currentTime.UnixNano()))
		future.ctx.Debugf("[GetPeers] Returning %d/%d random filtered peers", giveNumber, filteredLength)
		var i int64
		for i = 1; i <= giveNumber; i++ {
			giveNumber := randomGen.Int63n(filteredLength - 1)
			if isGiven, ok := given[giveNumber]; !ok || !isGiven {
				future.resultChannel <- peersFiltered[giveNumber]
				given[giveNumber] = true
			} else {
				i--
			}
		}

		future.ctx.Debugf("[GetPeers] Successfully retrieved peer list from memcache")
		return
	} else if appengine.IsCapabilityDisabled(err) {
		future.ctx.Warningf("[GetPeers] Memcache capability disabled: %s", err)
	} else if err != memcache.ErrCacheMiss {
		future.ctx.Errorf("[GetPeers] Error retrieving cached peer list: %s", err)
		future.errorChannel <- err
		return
	}

	future.ctx.Debugf("[GetPeers] No valid list exists in memcache")

	peerQuery := datastore.NewQuery("Peer").Filter("Hash =", future.hash).Filter("Expires >", time.Now())

	future.ctx.Debugf("[GetPeers] Querying for non-expired peers")

	numPeers, err := peerQuery.Count(future.ctx)
	if err != nil {
		future.ctx.Warningf("[GetPeers] Failed to get count of peers: %s", err)
		numPeers = 0
	}

	peers := make([]*Peer, 0, numPeers)

	var count int64 = 0
	for iterator := peerQuery.Run(future.ctx); ; {
		var thisPeer Peer
		key, err := iterator.Next(&thisPeer)
		if err == datastore.Done {
			break
		} else if err != nil {
			future.ctx.Errorf("[GetPeers] Error retrieving peers from query: %s", err)
			future.errorChannel <- err
			return
		}

		thisPeer.Key = key

		peers = append(peers, &thisPeer)

		if count < future.numberWanted {
			future.resultChannel <- &thisPeer
			count++
		}
	}

	future.ctx.Debugf("[GetPeers] Retrieved %d peers", len(peers))

	memcacheItem := &memcache.Item{
		Key:    getHashKey(future.ctx, future.hash),
		Object: peers,
	}

	if err := memcache.Gob.Set(future.ctx, memcacheItem); err == nil {
		future.ctx.Debugf("[GetPeers] Stored peer list in memcache")
	} else if appengine.IsCapabilityDisabled(err) {
		future.ctx.Warningf("[GetPeers] Memcache capability disabled: %s", err)
	} else {
		future.ctx.Warningf("[GetPeers] Error storing peer list in memcache: %s", err)
	}

	future.ctx.Debugf("[GetPeers] Successfully retrieved peer list from datastore")

	return
}
Example #8
0
func actualInsertPeer(future *insertPeerFuture) {
	defer close(future.resultChannel)

	future.ctx.Debugf("[InsertPeer] Inserting peer: (hash: %s) (ID: %s) (IP: %s) (port: %d)", future.hash, future.peerID, future.ip, future.port)

	changed := false
	peer := new(Peer)

	err := datastore.RunInTransaction(future.ctx, func(tc appengine.Context) error {
		peerKey := getPeerKey(tc, future.hash, future.peerID)

		if err := ds.Get(tc, peerKey, peer); err == nil {
			future.ctx.Debugf("[InsertPeer] Peer already exists, updating...")

			if peer.IP != future.ip {
				peer.IP = future.ip
				changed = true
				future.ctx.Debugf("[InsertPeer] Peer's IP has changed")
			}

			if peer.Port != int32(future.port) {
				peer.Port = int32(future.port)
				changed = true
				future.ctx.Debugf("[InsertPeer] Peer's port has changed")
			}

			currentTime := time.Now()
			if !peer.Expires.After(currentTime) || peer.Expires.Sub(currentTime) <= PeerRefreshTime {
				peer.Expires = time.Now().Add(PeerExpireTime).Add(PeerExpireGrace)
				changed = true
				future.ctx.Debugf("[InsertPeer] Peer's expire time has changed")
			}

			if changed {
				future.ctx.Debugf("[InsertPeer] Putting peer...")
				_, err := ds.Put(tc, peerKey, peer)
				if err != nil {
					future.ctx.Errorf("[InsertPeer] Error when putting updated peer: %s", err)
				}
				return err
			} else {
				future.ctx.Debugf("[InsertPeer] No need to update peer.")
				return nil
			}
		} else if err != dserrors.ErrNoSuchEntity {
			peer = nil
			future.ctx.Errorf("[InsertPeer] Error when retrieving peer from datastore for update: %s", err)
			return err
		}

		future.ctx.Debugf("[InsertPeer] Peer doesn't exist, creating")

		peer = &Peer{
			Hash:    future.hash,
			ID:      future.peerID,
			IP:      future.ip,
			Port:    int32(future.port),
			Expires: time.Now().Add(PeerExpireTime).Add(PeerExpireGrace),
		}

		_, err := ds.Put(tc, peerKey, peer)
		if err != nil {
			future.ctx.Errorf("[InsertPeer] Error when putting new peer: %s", err)
		}
		return err
	}, nil)

	if err == nil && peer != nil {
		memcacheKey := getHashKey(future.ctx, future.hash)
		for updatesAttempted := 1; updatesAttempted <= 3; updatesAttempted++ {
			future.ctx.Debugf("[InsertPeer] Attempting cache update #%d", updatesAttempted)
			var peers []*Peer
			if peersItem, memcacheErr := memcache.Gob.Get(future.ctx, memcacheKey, &peers); memcacheErr == nil {
				exists := false
				for _, thisPeer := range peers {
					if thisPeer.ID == future.peerID {
						exists = true
						break
					}
				}

				if !exists {
					peers = append(peers, peer)

					peersItem.Object = peers

					memcacheErr := memcache.Gob.CompareAndSwap(future.ctx, peersItem)
					if memcacheErr == nil {
						future.ctx.Debugf("[InsertPeer] Added peer to cached peer list.")
						break
					} else if memcacheErr == memcache.ErrCASConflict {
						future.ctx.Debugf("[InsertPeer] Cached peer list conflicted during modification: %s", memcacheErr)
						continue
					} else if memcacheErr == memcache.ErrNotStored {
						future.ctx.Debugf("[InsertPeer] Cached peer list was deleted during modification: %s", memcacheErr)
						continue
					} else if appengine.IsCapabilityDisabled(memcacheErr) {
						future.ctx.Warningf("[InsertPeer] Memcache capability disabled when attempting to add peer to cached peer list")
						continue
					} else {
						future.ctx.Errorf("[InsertPeer] Error when attempting to set cached peer list using CAS: %s", memcacheErr)
						future.resultChannel <- memcacheErr
						return
					}
				} else {
					future.ctx.Debugf("[InsertPeer] Peer already exists in cached list.")
					break
				}
			} else if memcacheErr == memcache.ErrCacheMiss {
				future.ctx.Debugf("[InsertPeer] Peer list not cached. Creating...")

				peersItem := &memcache.Item{
					Key:    memcacheKey,
					Object: []*Peer{peer},
				}
				if memcacheErr := memcache.Gob.CompareAndSwap(future.ctx, peersItem); memcacheErr == nil {
					future.ctx.Debugf("[InsertPeer] Peer list created")
					break
				} else if memcacheErr == memcache.ErrCASConflict {
					future.ctx.Debugf("[InsertPeer] Cached peer list conflicted during creation: %s", memcacheErr)
					continue
				} else if memcacheErr == memcache.ErrNotStored {
					future.ctx.Debugf("[InsertPeer] Cached peer list was deleted during creation: %s", memcacheErr)
					continue
				} else if appengine.IsCapabilityDisabled(memcacheErr) {
					future.ctx.Warningf("[InsertPeer] Memcache capability disabled when attempting to add peer to create cached peer list")
					continue
				} else {
					future.ctx.Errorf("[InsertPeer] Error when creating peer list: %s", memcacheErr)
					future.resultChannel <- memcacheErr
					return
				}
			} else if appengine.IsCapabilityDisabled(memcacheErr) {
				future.ctx.Warningf("[InsertPeer] Memcache capability is disabled.")
				break
			} else {
				future.ctx.Errorf("[InsertPeer] Error when attempting to get cache list for insertion: %s", memcacheErr)
				future.resultChannel <- memcacheErr
				return
			}
		}

		future.ctx.Debugf("[InsertPeer] Successfully inserted peer")
	} else if err != nil {
		future.resultChannel <- err
	}
}
Example #9
0
File: acl.go Project: gaego/acl
func get(c appengine.Context, key *datastore.Key) (p *Perm, err error) {
	p = &Perm{}
	err = ds.Get(c, key, p)
	return
}
Example #10
0
func TestGet(t *testing.T) {
	c := context.NewContext(nil)
	defer tearDown()

	// Save it.

	u := New("Google", "http://plus.google.com")
	u.ID = "12345"
	u.Person = &person.Person{
		Name: &person.PersonName{
			GivenName:  "Barack",
			FamilyName: "Obama",
		},
	}
	key := newKey(c, "google", "12345")
	u.Key = key
	err := u.Put(c)
	if err != nil {
		t.Errorf(`err: %q, want nil`, err)
	}

	// Get it.

	u2 := &Profile{}
	id := "google|12345"
	key = datastore.NewKey(c, "AuthProfile", id, 0, nil)
	err = ds.Get(c, key, u2)
	if err != nil {
		t.Errorf(`err: %q, want nil`, err)
	}
	u2, err = Get(c, id)
	if err != nil {
		t.Errorf(`err: %v, want nil`, err)
	}
	if u2.ID != "12345" {
		t.Errorf(`u2.ID: %v, want "1"`, u2.ID)
	}
	if u2.Key.StringID() != "google|12345" {
		t.Errorf(`uKey.StringID(): %v, want "google|12345"`, u2.Key.StringID())
	}
	if x := u2.ProviderURL; x != "http://plus.google.com" {
		t.Errorf(`u2.ProviderURL: %v, want %s`, x, "http://plus.google.com")
	}
	if x := u2.Person.ID; x != "12345" {
		t.Errorf(`u2.Person.ID: %v, want %s`, x, "12345")
	}
	if x := u2.Person.Name.GivenName; x != "Barack" {
		t.Errorf(`u2.Person.Name.GivenName: %v, want %s`, x, "Barack")
	}
	if x := u2.Person.Provider.Name; x != "Google" {
		t.Errorf(`u2.Person.Provider.Name: %v, want %s`, x, "Google")
	}
	if x := u2.Person.Provider.URL; x != "http://plus.google.com" {
		t.Errorf(`u2.Person.Provider.URL: %v, want %s`, x, "http://plus.google.com")
	}
	if x := u2.Person.Kind; x != "google#person" {
		t.Errorf(`u2.Person.Kind: %v, want %s`, x, "google#person")
	}
	if u2.Person.Created != u2.Created.UnixNano()/1000000 {
		t.Errorf(`u2.Created: %v, want %v`, u2.Person.Created,
			u2.Created.UnixNano()/1000000)
	}
	if u2.Person.Updated != u2.Updated.UnixNano()/1000000 {
		t.Errorf(`u2.Updated: %v, want %v`, u2.Person.Updated,
			u2.Updated.UnixNano()/1000000)
	}
}