func (qs *QuotaStorage) Peek(ctx context.Context, names []string) (map[string]int64, error) {
	now := timeSource.Now()
	tokens := make(map[string]int64)
	err := qs.forNames(ctx, names, emitInfinite, func(s concurrency.STM, name string, cfg *storagepb.Config) error {
		var err error
		var t int64
		if cfg == nil {
			t = int64(quota.MaxTokens)
		} else {
			t, err = modBucket(s, cfg, now, 0  )
		}
		tokens[name] = t
		return err
	})
	return tokens, err
}
Peek returns a map of quota name to tokens for the named quotas.
Unknown or disabled quotas are considered infinite and returned as having quota.MaxTokens tokens,
therefore all requested names are guaranteed to be in the resulting map
package storage
import (
	"context"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"
	"github.com/golang/glog"
	"github.com/google/trillian/quota"
	"github.com/google/trillian/quota/etcd/storagepb"
	"github.com/google/trillian/util/clock"
	"go.etcd.io/etcd/client/v3/concurrency"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/proto"
	clientv3 "go.etcd.io/etcd/client/v3"
)
const (
	configsKey = "quotas/configs"
)
var (
	timeSource = clock.System
	globalPattern *regexp.Regexp
	treesPattern  *regexp.Regexp
	usersPattern  *regexp.Regexp
)
func init() {
	var err error
	globalPattern, err = regexp.Compile("^quotas/global/(read|write)/config$")
	if err != nil {
		glog.Fatalf("bad global pattern: %v", err)
	}
	treesPattern, err = regexp.Compile(`^quotas/trees/\d+/(read|write)/config$`)
	if err != nil {
		glog.Fatalf("bad trees pattern: %v", err)
	}
	usersPattern, err = regexp.Compile("^quotas/users/[^/]+/(read|write)/config$")
	if err != nil {
		glog.Fatalf("bad users pattern: %v", err)
	}
}
func IsNameValid(name string) bool {
	switch {
	case globalPattern.MatchString(name):
		return true
	case usersPattern.MatchString(name):
		return true
	case treesPattern.MatchString(name):
		id := strings.Split(name, "/")[2]
		_, err := strconv.ParseInt(id, 10, 64)
		return err == nil
	}
	return false
}
type QuotaStorage struct {
	Client *clientv3.Client
}
func (qs *QuotaStorage) UpdateConfigs(ctx context.Context, reset bool, update func(*storagepb.Configs)) (*storagepb.Configs, error) {
	if update == nil {
		return nil, status.Error(codes.Internal, "update function required")
	}
	var updated *storagepb.Configs
	_, err := concurrency.NewSTMSerializable(ctx, qs.Client, func(s concurrency.STM) error {
		previous, err := getConfigs(s)
		if err != nil {
			return err
		}
		updated, err = getConfigs(s)
		if err != nil {
			return err
		}
		if !proto.Equal(previous, updated) {
			return status.Error(codes.Internal, "verification failed: previous quota config != updated")
		}
		update(updated)
		if err := validate(updated); err != nil {
			return err
		}
		if !proto.Equal(previous, updated) {
			pb, err := proto.Marshal(updated)
			if err != nil {
				return err
			}
			s.Put(configsKey, string(pb))
		}
		now := timeSource.Now()
		for _, cfg := range updated.Configs {
			key := bucketKey(cfg)
			var prev *storagepb.Config
			for _, p := range previous.Configs {
				if cfg.Name == p.Name {
					prev = p
					break
				}
			}
			switch {
			case prev == nil || prev.State == storagepb.Config_DISABLED || reset:  
				bucket := &storagepb.Bucket{
					Tokens:                        cfg.MaxTokens,
					LastReplenishMillisSinceEpoch: now.UnixNano() / 1e6,
				}
				pb, err := proto.Marshal(bucket)
				if err != nil {
					return err
				}
				s.Put(key, string(pb))
			case cfg.MaxTokens < prev.MaxTokens:  
				if _, err := modBucket(s, cfg, now, 0  ); err != nil {
					return err
				}
			}
		}
		return nil
	})
	return updated, err
}
func validate(cfgs *storagepb.Configs) error {
	names := make(map[string]bool)
	for i, cfg := range cfgs.Configs {
		switch n := cfg.Name; {
		case n == "":
			return status.Errorf(codes.InvalidArgument, "config name is required (Configs[%v].Name is empty)", i)
		case !IsNameValid(cfg.Name):
			return status.Errorf(codes.InvalidArgument, "config name malformed (Configs[%v].Name = %q)", i, n)
		}
		if s := cfg.State; s == storagepb.Config_UNKNOWN_CONFIG_STATE {
			return status.Errorf(codes.InvalidArgument, "config state invalid (Configs[%v].State = %s)", i, s)
		}
		if t := cfg.MaxTokens; t <= 0 {
			return status.Errorf(codes.InvalidArgument, "config max tokens must be > 0 (Configs[%v].MaxTokens = %v)", i, t)
		}
		switch s := cfg.ReplenishmentStrategy.(type) {
		case *storagepb.Config_SequencingBased:
			if usersPattern.MatchString(cfg.Name) {
				return status.Errorf(codes.InvalidArgument, "user quotas cannot use sequencing-based replenishment (Configs[%v].ReplenishmentStrategy)", i)
			}
			if strings.HasSuffix(cfg.Name, "/read/config") {
				return status.Errorf(codes.InvalidArgument, "read quotas cannot use sequencing-based replenishment (Configs[%v].ReplenishmentStrategy)", i)
			}
		case *storagepb.Config_TimeBased:
			if t := s.TimeBased.TokensToReplenish; t <= 0 {
				return status.Errorf(codes.InvalidArgument, "time based tokens must be > 0 (Configs[%v].TimeBased.TokensToReplenish = %v)", i, t)
			}
			if r := s.TimeBased.ReplenishIntervalSeconds; r <= 0 {
				return status.Errorf(codes.InvalidArgument, "time based replenish interval must be > 0 (Configs[%v].TimeBased.ReplenishIntervalSeconds = %v)", i, r)
			}
		default:
			return status.Errorf(codes.InvalidArgument, "unsupported replenishment strategy (Configs[%v].ReplenishmentStrategy = %T)", i, s)
		}
		if names[cfg.Name] {
			return status.Errorf(codes.InvalidArgument, "duplicate config name found at Configs[%v].Name", i)
		}
		names[cfg.Name] = true
	}
	return nil
}
func (qs *QuotaStorage) Configs(ctx context.Context) (*storagepb.Configs, error) {
	var cfgs *storagepb.Configs
	_, err := concurrency.NewSTMSerializable(ctx, qs.Client, func(s concurrency.STM) error {
		var err error
		cfgs, err = getConfigs(s)
		return err
	})
	return cfgs, err
}
func (qs *QuotaStorage) Get(ctx context.Context, names []string, tokens int64) error {
	if tokens < 0 {
		return fmt.Errorf("invalid number of tokens: %v", tokens)
	}
	return qs.mod(ctx, names, -tokens)
}
func (qs *QuotaStorage) mod(ctx context.Context, names []string, add int64) error {
	now := timeSource.Now()
	return qs.forNames(ctx, names, defaultMode, func(s concurrency.STM, name string, cfg *storagepb.Config) error {
		_, err := modBucket(s, cfg, now, add)
		return err
	})
}