// Increment increments the named counter. func Increment(c context.Context, valName string) error { // Get counter config. shardsTotal := dsu.WrapInt{} dsu.McacheGet(c, mcKeyShardsTotal(valName), &shardsTotal) if shardsTotal.I < 1 { ckey := datastore.NewKey(c, dsKindNumShards, mcKeyShardsTotal(valName), 0, nil) errTx := datastore.RunInTransaction(c, func(c context.Context) error { err := datastore.Get(c, ckey, &shardsTotal) if err == datastore.ErrNoSuchEntity { shardsTotal.I = defaultNumShards _, err = datastore.Put(c, ckey, &shardsTotal) } return err }, nil) if errTx != nil { return errTx } dsu.McacheSet(c, mcKeyShardsTotal(valName), dsu.WrapInt{shardsTotal.I}) } // pick random counter and increment it errTx := datastore.RunInTransaction(c, func(c context.Context) error { shardId := rand.Intn(shardsTotal.I) dsKey := datastore.NewKey(c, dsKindShard, keySingleShard(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) if ll > 2 { aelog.Infof(c, "ds put %v %v", dsKey, sd) } return err }, nil) if errTx != nil { return errTx } memcache.Increment(c, mcKey(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 }
// AdjustShards increases the number of shards for the named counter to n. // It will never decrease the number of shards. func AdjustShards(c context.Context, valName string, n int) error { ckey := datastore.NewKey(c, dsKindNumShards, valName, 0, nil) return datastore.RunInTransaction(c, func(c context.Context) error { shardsTotal := dsu.WrapInt{} mod := false err := datastore.Get(c, ckey, &shardsTotal) if err == datastore.ErrNoSuchEntity { shardsTotal.I = n mod = true } else if err != nil { return err } if shardsTotal.I < n { shardsTotal.I = n mod = true } if mod { _, err = datastore.Put(c, ckey, &shardsTotal) } return err }, nil) }
// AdjustShards increases the number of shards for the named counter to n. // It will never decrease the number of shards. func AdjustShards(c appengine.Context, valName string, n int) error { ckey := datastore.NewKey(c, dsKindNumShards, valName, 0, nil) return datastore.RunInTransaction(c, func(c appengine.Context) error { wNumShards := dsu.WrapInt{} mod := false err := datastore.Get(c, ckey, &wNumShards) if err == datastore.ErrNoSuchEntity { wNumShards.I = defaultNumShards mod = true } else if err != nil { return err } if wNumShards.I < n { wNumShards.I = n mod = true } if mod { _, err = datastore.Put(c, ckey, &wNumShards) } return err }, nil) }