// Increment increments the named counter. func Increment(c appengine.Context, name string) error { // Get counter config. var cfg counterConfig ckey := datastore.NewKey(c, configKind, name, 0, nil) err := datastore.RunInTransaction(c, func(c appengine.Context) error { err := datastore.Get(c, ckey, &cfg) if err == datastore.ErrNoSuchEntity { cfg.Shards = defaultShards _, err = datastore.Put(c, ckey, &cfg) } return err }, nil) if err != nil { return err } err = datastore.RunInTransaction(c, func(c appengine.Context) error { shardName := fmt.Sprintf("%v%d", name, rand.Intn(cfg.Shards)) key := datastore.NewKey(c, shardKind, shardName, 0, nil) var s shard err := datastore.Get(c, key, &s) // A missing entity and a present entity will both work. if err != nil && err != datastore.ErrNoSuchEntity { return err } s.Count++ s.Name = name _, err = datastore.Put(c, key, &s) return err }, nil) if err != nil { return err } //memcache.Increment(c, memcacheKey(name), 1, 0) return nil }
// Increment increments the named counter. func Increment(c appengine.Context, valName string) error { // Get counter config. wNumShards := dsu.WrapInt{} dsu.McacheGet(c, mCKNumShards(valName), &wNumShards) if wNumShards.I < 1 { ckey := datastore.NewKey(c, dsKindNumShards, mCKNumShards(valName), 0, nil) errTx := datastore.RunInTransaction(c, func(c appengine.Context) error { err := datastore.Get(c, ckey, &wNumShards) if err == datastore.ErrNoSuchEntity { wNumShards.I = defaultNumShards _, err = datastore.Put(c, ckey, &wNumShards) } return err }, nil) if errTx != nil { return errTx } dsu.McacheSet(c, mCKNumShards(valName), dsu.WrapInt{wNumShards.I}) } // pick random counter and increment it errTx := datastore.RunInTransaction(c, func(c appengine.Context) error { shardId := rand.Intn(wNumShards.I) dsKey := datastore.NewKey(c, dsKindShard, dSKSingleShard(valName, shardId), 0, nil) var sd WrapShardData err := datastore.Get(c, dsKey, &sd) // A missing entity and a present entity will both work. if err != nil && err != datastore.ErrNoSuchEntity { return err } sd.Name = valName sd.ShardId = shardId sd.I++ _, err = datastore.Put(c, dsKey, &sd) c.Infof("ds put %v %v", dsKey, sd) return err }, nil) if errTx != nil { return errTx } memcache.Increment(c, mCKValue(valName), 1, 0) // collect number of updates // per valName per instance in memory // for every interval of 10 minutes // // a batch job checks if the number of shards should be increased or decreased // and truncates this map updateSamplingFrequency[valName+util.TimeMarker()[:len("2006-01-02 15:0")]] += 1 return nil }
// commitHandler retrieves commit data or records a new commit. // // For GET requests it returns a Commit value for the specified // packagePath and hash. // // For POST requests it reads a JSON-encoded Commit value from the request // body and creates a new Commit entity. It also updates the "tip" Tag for // each new commit at tip. // // This handler is used by a gobuilder process in -commit mode. func commitHandler(r *http.Request) (interface{}, error) { c := appengine.NewContext(r) com := new(Commit) if r.Method == "GET" { com.PackagePath = r.FormValue("packagePath") com.Hash = r.FormValue("hash") if err := datastore.Get(c, com.Key(c), com); err != nil { return nil, fmt.Errorf("getting Commit: %v", err) } return com, nil } if r.Method != "POST" { return nil, errBadMethod(r.Method) } // POST request defer r.Body.Close() if err := json.NewDecoder(r.Body).Decode(com); err != nil { return nil, fmt.Errorf("decoding Body: %v", err) } if len(com.Desc) > maxDatastoreStringLen { com.Desc = com.Desc[:maxDatastoreStringLen] } if err := com.Valid(); err != nil { return nil, fmt.Errorf("validating Commit: %v", err) } defer cache.Tick(c) tx := func(c appengine.Context) error { return addCommit(c, com) } return nil, datastore.RunInTransaction(c, tx, nil) }
// method to import from JSON read with the file reader func importFile(c *context, file io.Reader) { // run in a transaction so that each datastore write doesn't redo the index, // rather all the indecies get updated at once when we're done datastore.RunInTransaction(c.c, func(tc appengine.Context) error { // decode the data decoder := json.NewDecoder(file) data := backup{} err := decoder.Decode(&data) check(err) // setup a worker to do the work worker := &importer{ context: *c, jsonData: data, fixUpKeys: make(map[string]*datastore.Key), allTags: make(map[string]map[string]bool), newTags: make([]interface{}, 0, 100), newTagKeys: make([]*datastore.Key, 0, 100), dirtyCacheEntries: make([]string, 0, 1000), } worker.c = tc // kick off the import worker.doImport() return nil }, nil) }
func SetPlayerName(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) seasonName := r.FormValue("SeasonName") seasonYear := r.FormValue("SeasonYear") playerId := r.FormValue("PlayerId") newPlayerName := r.FormValue("NewPlayerName") c.Infof("Replaceing '%v' with '%v' for season '%v' '%v'", playerId, newPlayerName, seasonName, seasonYear) var season *model.Season if seasonName == "" || seasonYear == "" { c.Infof("Lookup season") tmpSeason := api.GetActiveSeasonWithContext(c) season = &tmpSeason } else { season = api.LoadSeasonByNameYear(c, seasonName, seasonYear) } players := season.GetPlayers(c) targetIndex := playerIndex(players, playerId) replacePlayer := players[targetIndex] replacePlayer.Name = newPlayerName season.Schedule = []byte(strings.Replace(string(season.Schedule), playerId, newPlayerName, -1)) season.Conferences = []byte(strings.Replace(string(season.Conferences), playerId, newPlayerName, -1)) pkey := model.PlayerKey(c, season.Name, season.Year, newPlayerName) season.Players[targetIndex] = pkey err := datastore.RunInTransaction(c, func(c appengine.Context) error { model.SavePlayer(c, season, replacePlayer) err := model.SaveSeason(c, *season) return err }, nil) if err != nil { panic(err) } }
// Transactions in phase FINISHED will cause the price to be credited on the seller's // account, and the fee to be deducted. // All other phases will lead to price and fee being reimbursed to the buyer. // Returns ErrTransactionTooYoung if the transaction has not passed its timout at the // time of the call. // Returns ErrTransactionAlreadyRetired if the transaction has already been retired at // the time of the call. func RetireTransaction(c appengine.Context, key *datastore.Key) error { f := func(c appengine.Context) error { now := time.Now() dao := NewGaeAccountingDao(c, true) var tx Transaction if err := datastore.Get(c, key, txCodec{&tx}); err != nil { return err } if err := tx.Retire(dao, key.Encode(), now); err == ErrTooYoung { return ErrTransactionTooYoung } else if err == ErrAlreadyRetired { return ErrTransactionAlreadyRetired } else if err != nil { return err } if _, err := datastore.Put(c, key, txCodec{&tx}); err != nil { return err } return dao.Flush() } return datastore.RunInTransaction(c, f, &datastore.TransactionOptions{XG: true}) }
// This will reimburse the bid's price and fee to the buyer. func RetireBid(c appengine.Context, key *datastore.Key) error { f := func(c appengine.Context) error { now := time.Now() dao := NewGaeAccountingDao(c, true) var bid Bid if err := datastore.Get(c, key, bidCodec{&bid}); err != nil { return err } if bid.State == Matched { c.Infof("Not retiring matched bid %v", key) return nil } if err := bid.Retire(dao, key.Encode(), now); err != nil { return err } if _, err := datastore.Put(c, key, bidCodec{&bid}); err != nil { return err } return dao.Flush() } if err := datastore.RunInTransaction(c, f, &datastore.TransactionOptions{XG: true}); err != nil { return err } return nil }
// RefreshFeed fetches and updates a feed from the remote source, // stores it's info and articles in the datastore, and removes old articles // (those not retrieved on the latest fetch). func (f *FeedInfo) refresh(c appengine.Context) error { fnew, articles, fetchErr := f.readSource(c) err := datastore.RunInTransaction(c, func(c appengine.Context) error { var stored FeedInfo key := datastore.NewKey(c, feedKind, f.Url, 0, nil) err := fixMissingFieldError(datastore.Get(c, key, &stored)) if err != nil && err != datastore.ErrNoSuchEntity { return err } if fetchErr != nil { *f = stored f.LastFetch = time.Now() } else { *f = fnew } f.Refs = stored.Refs _, err = datastore.Put(c, key, f) return err }, nil) if fetchErr != nil { return fetchErr } if err != nil { return err } return f.updateArticles(c, articles) }
func sit(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) u := user.Current(c) id := r.FormValue("id") g, err := poker.LoadGame(id, r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } err = datastore.RunInTransaction(c, func(c appengine.Context) error { name := r.FormValue("name") if name == "" { return errors.New("Please choose a name") } return g.Sit(u.Email, name) }, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if err = g.Save(r); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } err = broadcastState(c, g) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } }
func addAtom(c appengine.Context, url string) error { feedRoot := datastore.NewKey(c, "feedRoot", "feedRoot", 0, nil) fk := datastore.NewKey(c, "feed", url, 0, feedRoot) err := datastore.RunInTransaction(c, func(c appengine.Context) error { done, err := exists(c, fk) if err != nil { return err } if !done { f, err := fetchAtom(c, url) if err != nil { return err } _, err = datastore.Put(c, fk, f) if err != nil { return err } err = f.update(c, fk) if err != nil { return err } return nil } return nil }, nil) if err != nil { return err } return subscribe(c, fk, true) }
// TODO(dlluncor): Merge this with ChangeGame as they are the same except for the key // and the type of the changeEntityFunc, and the defaultLounge() thing. // Utility function for reading from and updating a game before then // doing further processing. func ChangeLounge(c appengine.Context, loungeId string, clf changeLoungeFunc) *MyLounge { // Store all tables as part of the game state and send // a "startTimer" response. loungeKey := loungeId l := defaultLounge() err := datastore.RunInTransaction(c, func(c appengine.Context) error { k := datastore.NewKey(c, "WrLounge", loungeKey, 0, nil) if err := datastore.Get(c, k, l); err != nil { return err } // Perform special logic here to manipulate game. shouldRunUpdate := clf(l) if !shouldRunUpdate { // Sometimes we don't need to update the database so don't. return nil } if _, err := datastore.Put(c, k, l); err != nil { return err } return nil }, nil) if err != nil { c.Errorf("Err in db transaction %v", err) } return l }
func createLounge(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) queryMap := r.URL.Query() loungeName := queryMap.Get("l") gamesStr := queryMap.Get("g") games := strings.Split(gamesStr, ",") l := defaultLounge() l.Name = loungeName l.Games = games addLoungeNameDb(c, loungeName) // Create the lounges. err := datastore.RunInTransaction(c, func(c appengine.Context) error { k := datastore.NewKey(c, "WrLounge", loungeName, 0, nil) if _, err := datastore.Put(c, k, l); err != nil { return err } return nil }, nil) if err != nil { fmt.Fprintf(w, "Error creating a lounge: %v", err) } else { fmt.Fprintf(w, "Success in creating lounge: %v with games: %s", loungeName, games) } // Create the games as well. lang := queryMap.Get("lang") for _, tableKey := range games { g := defaultGame() g.Language = lang createGame(c, tableKey, g) } }
func tx(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) // start tx OMIT key := datastore.NewKey(c, "Book", "book1", 0, nil) // HL if err := datastore.RunInTransaction(c, func(c appengine.Context) error { // HL var book Book if err := datastore.Get(c, key, &book); err != nil { // HL return err } book.Price += 200 if _, err := datastore.Put(c, key, &book); err != nil { // HL return err } return nil }, nil); err != nil { // HL http.Error(w, err.Error(), http.StatusInternalServerError) return } // end tx OMIT w.Write([]byte("success")) }
// Claim attempts to uniquely associate the user and email. func (e *ClaimedEmail) Claim(c appengine.Context) error { err := datastore.RunInTransaction(c, func(c appengine.Context) error { key := e.key(c) old := &ClaimedEmail{} lookupErr := datastore.Get(c, key, old) switch { case lookupErr == nil: return ErrEmailAlreadyClaimed case lookupErr == datastore.ErrNoSuchEntity: // Didn't find old claim: all is well. break default: return lookupErr } if _, storeErr := datastore.Put(c, key, e); storeErr != nil { return storeErr } return nil }, nil) if err != nil { return err } return nil }
// RewriteID transactionally rewrites the Account under the // correct (i.e., obfuscated) key. func (a *Account) RewriteID(c appengine.Context, u *user.User) error { var err error a.ID, err = ID(u) if err != nil { return fmt.Errorf("couldn't create ID for %v", u) } var txnErr error for i := 0; i < 10; i++ { txnErr = datastore.RunInTransaction(c, func(c appengine.Context) error { if err := a.Put(c); err != nil { return err } oldKey := datastore.NewKey(c, "UserAccount", u.ID, 0, nil) if err := datastore.Delete(c, oldKey); err != nil { return err } return nil }, &datastore.TransactionOptions{XG: true}) if txnErr != datastore.ErrConcurrentTransaction { break } } if txnErr != nil { return txnErr } return nil }
func updateSubscriberCount(c appengine.Context, feedURL string, delta int) error { err := datastore.RunInTransaction(c, func(c appengine.Context) error { shardName := fmt.Sprintf("%s#%d", feedURL, rand.Intn(subscriberCountShards)) key := datastore.NewKey(c, "SubscriberCountShard", shardName, 0, nil) var shard subscriberCountShard if err := datastore.Get(c, key, &shard); err == datastore.ErrNoSuchEntity { shard.Feed = datastore.NewKey(c, "Feed", feedURL, 0, nil) } else if err != nil { return err } shard.SubscriberCount += delta _, err := datastore.Put(c, key, &shard) return err }, nil) if err != nil { return err } return nil }
func getOrCreateAccount(c appengine.Context, user *user.User) (*KindiAccount, error) { var account KindiAccount _, err := memcache.JSON.Get(c, user.ID, &account) if err != nil && err != memcache.ErrCacheMiss { return nil, err } if err == memcache.ErrCacheMiss { key := datastore.NewKey(c, "KindiAccount", user.ID, 0, nil) return &account, datastore.RunInTransaction(c, func(c appengine.Context) error { err := datastore.Get(c, key, &account) if err != nil && err != datastore.ErrNoSuchEntity { return err } if err == datastore.ErrNoSuchEntity { account.Email = user.Email account.KindiCoins = 0 _, err = datastore.Put(c, key, &account) if err != nil { return err } } memcacheItem := new(memcache.Item) memcacheItem.Key = user.ID memcacheItem.Object = account return memcache.JSON.Set(c, memcacheItem) }, nil) } return &account, nil }
// Transaction executes f in a transaction. // If an error occurs, Transaction returns it but also logs it using ctxt.Errorf. // All transactions are marked as "cross-group" (there is no harm in doing so). func Transaction(ctxt appengine.Context, f func(ctxt appengine.Context) error) error { err := datastore.RunInTransaction(ctxt, f, &datastore.TransactionOptions{XG: true}) if err != nil { ctxt.Errorf("transaction failed: %v", err) } return err }
func Create(c appengine.Context, inputData string) (id string, err error) { id, err = generateRandStr(64) if err != nil { return } // Create our job's state object. state := &State{ ID: id, Status: StatusNew, InputData: inputData, } // Save the state object and schedule processing of the job. err = datastore.RunInTransaction(c, func(c appengine.Context) error { // Save the new job. datastore.Put(c, state.GetKey(c), state) // Schedule processing. processJobDelay.Call(c, id) return nil }, nil) if err != nil { state = nil } return }
func (s *Story) Get(c appengine.Context) error { // Construct the query once q := datastore.NewQuery("Property") q.Ancestor(s.key) return datastore.RunInTransaction(c, func(tx appengine.Context) error { if err := datastore.Get(tx, s.key, s); err != nil { return err } props := []*Property{} keys, err := q.GetAll(tx, &props) if err != nil { return err } s.Meta = make(map[string]*Property) for i, prop := range props { prop.key = keys[i] s.Meta[prop.Name] = prop } return nil }, nil) }
// Marks a bid as placed. This is purely informational for the user. func PlaceBid(c appengine.Context, bidId string) error { var key *datastore.Key if k, err := datastore.DecodeKey(bidId); err != nil { return err } else { key = k } f := func(c appengine.Context) error { var bid Bid if err := datastore.Get(c, key, bidCodec{&bid}); err != nil { return err } if bid.State != InQueue { c.Infof("Not placing bid %v : State=%v", key, bid.State) return nil } bid.State = Placed if _, err := datastore.Put(c, key, bidCodec{&bid}); err != nil { return err } return nil } return datastore.RunInTransaction(c, f, nil) }
func updateTag(c appengine.Context, page Page) error { for _, v := range page.Tags { key := datastore.NewKey(c, "Tag", v, 0, nil) err := datastore.RunInTransaction(c, func(c appengine.Context) error { var tag Tag err := datastore.Get(c, key, &tag) if nil != err && datastore.ErrNoSuchEntity != err { c.Errorf("%v", err) return err } // not exist, create /* if datastore.ErrNoSuchEntity == err { newTag.Title = append(newTag.Title, page.Title) } */ // exist tag.Name = v tag.Titles = append(tag.Titles, page.Title) _, err = datastore.Put(c, key, &tag) if nil != err { c.Errorf("%v", err) return err } return nil }, nil) if nil != err { c.Errorf("%v", err) return err } } return nil }
func updateAll(typeName string, makeFn func() interface{}, updateFn func(value interface{}) bool, c *Context) error { q := datastore.NewQuery(typeName).KeysOnly() keys, err := q.GetAll(c.Aec(), nil) CheckError(err) for _, key := range keys { err := datastore.RunInTransaction(c.Aec(), func(aec appengine.Context) error { value := makeFn() if err := datastore.Get(aec, key, value); err != nil { return err } if updateFn(value) { if _, err := datastore.Put(aec, key, value); err != nil { return err } } return nil }, nil) if err != nil { return err } } return nil }
func updateImage(c appengine.Context, img Image) error { key := datastore.NewKey(c, "Image", img.Name, 0, nil) err := datastore.RunInTransaction(c, func(c appengine.Context) error { newimg := Image{} err := datastore.Get(c, key, &newimg) if nil != err && datastore.ErrNoSuchEntity != err { c.Errorf("%v", err) return err } if datastore.ErrNoSuchEntity != err { err = blobstore.Delete(c, newimg.BlobKey) if nil != err { c.Errorf("%v", err) return err } } _, err = datastore.Put(c, key, &img) if nil != err { c.Errorf("%v", err) return err } return nil }, nil) if nil != err { c.Errorf("%v", err) return err } return nil }
// CreateFromPerson Creates a User from a Person object func CreateFromPerson(c appengine.Context, p *person.Person) (u *User, err error) { if err = validatePerson(p); err != nil { return } // Transaction Action err = datastore.RunInTransaction(c, func(c appengine.Context) error { // Get the email e, err := email.Get(c, p.Email) // An error that is not an ErrNoSuchEntity indicates an an internal error // and it should be returned. if err != nil && err != dserrors.ErrNoSuchEntity { return err } // Lack of an error indicates that the email existing in the ds. if err == nil { return ErrEmailInUse } // Create a new User u = New() u.Person = p u.Email = p.Email if err = u.Put(c); err != nil { return err } // Update the Email with UserID. e.UserID = u.Key.StringID() return e.Put(c) // XG transation }, &datastore.TransactionOptions{XG: true}) return u, err }
// 勉強会の追加 func (group *Group) Add(c appengine.Context) os.Error { count := new(Counter) countKey := datastore.NewKey(c, "Counter", "mycounter", 0, nil) countErr := datastore.RunInTransaction(c, func(c appengine.Context) os.Error { err := datastore.Get(c, countKey, count) if err != nil && err != datastore.ErrNoSuchEntity { return err } count.GroupCount++ _, err = datastore.Put(c, countKey, count) return err }, nil) if countErr != nil { return countErr } group.Id = count.GroupCount group.CreateDate = datastore.SecondsToTime(time.Seconds()) key := datastore.NewKey(c, "Group", "", int64(group.Id), nil) _, err := datastore.Put(c, key, group) return err }
func (is *indexStorage) CommitBatch(bm sorted.BatchMutation) error { type mutationser interface { Mutations() []sorted.Mutation } var muts []sorted.Mutation if m, ok := bm.(mutationser); ok { muts = m.Mutations() } else { panic("unexpected type") } tryFunc := func(c appengine.Context) error { for _, m := range muts { dk := is.key(c, m.Key()) if m.IsDelete() { if err := datastore.Delete(c, dk); err != nil { return err } } else { // A put. ent := &indexRowEnt{ Value: []byte(m.Value()), } if _, err := datastore.Put(c, dk, ent); err != nil { return err } } } return nil } c := ctxPool.Get() defer c.Return() return datastore.RunInTransaction(c, tryFunc, crossGroupTransaction) }
func checkNonce(c appengine.Context, nonce string) error { now := time.Now() if len(nonce) < 24 || len(nonce) > 32 { return errInvalidNonce } key := NonceKey(c, nonce) return datastore.RunInTransaction(c, func(c appengine.Context) error { var dbNonce Nonce if err := datastore.Get(c, key, &dbNonce); err != nil { return errInvalidNonce } if !dbNonce.Expires.After(now) { return errInvalidNonce } if err := datastore.Delete(c, key); err != nil { return err } return nil }, nil) }
// perfResultHandler records a becnhmarking result. func perfResultHandler(r *http.Request) (interface{}, error) { defer r.Body.Close() if r.Method != "POST" { return nil, errBadMethod(r.Method) } req := new(PerfRequest) if err := json.NewDecoder(r.Body).Decode(req); err != nil { return nil, fmt.Errorf("decoding Body: %v", err) } c := contextForRequest(r) defer cache.Tick(c) // store the text files if supplied for i, a := range req.Artifacts { hash, err := PutLog(c, a.Body) if err != nil { return nil, fmt.Errorf("putting Log: %v", err) } req.Artifacts[i].Body = hash } tx := func(c appengine.Context) error { return addPerfResult(c, r, req) } return nil, datastore.RunInTransaction(c, tx, nil) }
func (article Article) updateLikeCount(c appengine.Context, delta int) error { err := datastore.RunInTransaction(c, func(c appengine.Context) error { shardName := fmt.Sprintf("%s#%d", article.Entry.StringID(), rand.Intn(likeCountShards)) key := datastore.NewKey(c, "LikeCountShard", shardName, 0, nil) var shard likeCountShard if err := datastore.Get(c, key, &shard); err == datastore.ErrNoSuchEntity { shard.Entry = article.Entry } else if err != nil { return err } shard.LikeCount += delta _, err := datastore.Put(c, key, &shard) return err }, nil) if err != nil { return err } return nil }