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 }
// 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 }
// 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 }
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 }
// 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 }
// 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 }
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 }
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 } }
func get(c appengine.Context, key *datastore.Key) (p *Perm, err error) { p = &Perm{} err = ds.Get(c, key, p) return }
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) } }