mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-26 21:00:30 +00:00
vendor: add google.golang.org/appengine/memcache
This commit is contained in:
parent
c063196348
commit
a1aebcca7f
1562
vendor/google.golang.org/appengine/internal/memcache/memcache_service.pb.go
generated
vendored
Normal file
1562
vendor/google.golang.org/appengine/internal/memcache/memcache_service.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
165
vendor/google.golang.org/appengine/internal/memcache/memcache_service.proto
generated
vendored
Normal file
165
vendor/google.golang.org/appengine/internal/memcache/memcache_service.proto
generated
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
syntax = "proto2";
|
||||
option go_package = "memcache";
|
||||
|
||||
package appengine;
|
||||
|
||||
message MemcacheServiceError {
|
||||
enum ErrorCode {
|
||||
OK = 0;
|
||||
UNSPECIFIED_ERROR = 1;
|
||||
NAMESPACE_NOT_SET = 2;
|
||||
PERMISSION_DENIED = 3;
|
||||
INVALID_VALUE = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message AppOverride {
|
||||
required string app_id = 1;
|
||||
|
||||
optional int32 num_memcacheg_backends = 2 [deprecated=true];
|
||||
optional bool ignore_shardlock = 3 [deprecated=true];
|
||||
optional string memcache_pool_hint = 4 [deprecated=true];
|
||||
optional bytes memcache_sharding_strategy = 5 [deprecated=true];
|
||||
}
|
||||
|
||||
message MemcacheGetRequest {
|
||||
repeated bytes key = 1;
|
||||
optional string name_space = 2 [default = ""];
|
||||
optional bool for_cas = 4;
|
||||
optional AppOverride override = 5;
|
||||
}
|
||||
|
||||
message MemcacheGetResponse {
|
||||
repeated group Item = 1 {
|
||||
required bytes key = 2;
|
||||
required bytes value = 3;
|
||||
optional fixed32 flags = 4;
|
||||
optional fixed64 cas_id = 5;
|
||||
optional int32 expires_in_seconds = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message MemcacheSetRequest {
|
||||
enum SetPolicy {
|
||||
SET = 1;
|
||||
ADD = 2;
|
||||
REPLACE = 3;
|
||||
CAS = 4;
|
||||
}
|
||||
repeated group Item = 1 {
|
||||
required bytes key = 2;
|
||||
required bytes value = 3;
|
||||
|
||||
optional fixed32 flags = 4;
|
||||
optional SetPolicy set_policy = 5 [default = SET];
|
||||
optional fixed32 expiration_time = 6 [default = 0];
|
||||
|
||||
optional fixed64 cas_id = 8;
|
||||
optional bool for_cas = 9;
|
||||
}
|
||||
optional string name_space = 7 [default = ""];
|
||||
optional AppOverride override = 10;
|
||||
}
|
||||
|
||||
message MemcacheSetResponse {
|
||||
enum SetStatusCode {
|
||||
STORED = 1;
|
||||
NOT_STORED = 2;
|
||||
ERROR = 3;
|
||||
EXISTS = 4;
|
||||
}
|
||||
repeated SetStatusCode set_status = 1;
|
||||
}
|
||||
|
||||
message MemcacheDeleteRequest {
|
||||
repeated group Item = 1 {
|
||||
required bytes key = 2;
|
||||
optional fixed32 delete_time = 3 [default = 0];
|
||||
}
|
||||
optional string name_space = 4 [default = ""];
|
||||
optional AppOverride override = 5;
|
||||
}
|
||||
|
||||
message MemcacheDeleteResponse {
|
||||
enum DeleteStatusCode {
|
||||
DELETED = 1;
|
||||
NOT_FOUND = 2;
|
||||
}
|
||||
repeated DeleteStatusCode delete_status = 1;
|
||||
}
|
||||
|
||||
message MemcacheIncrementRequest {
|
||||
enum Direction {
|
||||
INCREMENT = 1;
|
||||
DECREMENT = 2;
|
||||
}
|
||||
required bytes key = 1;
|
||||
optional string name_space = 4 [default = ""];
|
||||
|
||||
optional uint64 delta = 2 [default = 1];
|
||||
optional Direction direction = 3 [default = INCREMENT];
|
||||
|
||||
optional uint64 initial_value = 5;
|
||||
optional fixed32 initial_flags = 6;
|
||||
optional AppOverride override = 7;
|
||||
}
|
||||
|
||||
message MemcacheIncrementResponse {
|
||||
enum IncrementStatusCode {
|
||||
OK = 1;
|
||||
NOT_CHANGED = 2;
|
||||
ERROR = 3;
|
||||
}
|
||||
|
||||
optional uint64 new_value = 1;
|
||||
optional IncrementStatusCode increment_status = 2;
|
||||
}
|
||||
|
||||
message MemcacheBatchIncrementRequest {
|
||||
optional string name_space = 1 [default = ""];
|
||||
repeated MemcacheIncrementRequest item = 2;
|
||||
optional AppOverride override = 3;
|
||||
}
|
||||
|
||||
message MemcacheBatchIncrementResponse {
|
||||
repeated MemcacheIncrementResponse item = 1;
|
||||
}
|
||||
|
||||
message MemcacheFlushRequest {
|
||||
optional AppOverride override = 1;
|
||||
}
|
||||
|
||||
message MemcacheFlushResponse {
|
||||
}
|
||||
|
||||
message MemcacheStatsRequest {
|
||||
optional AppOverride override = 1;
|
||||
}
|
||||
|
||||
message MergedNamespaceStats {
|
||||
required uint64 hits = 1;
|
||||
required uint64 misses = 2;
|
||||
required uint64 byte_hits = 3;
|
||||
|
||||
required uint64 items = 4;
|
||||
required uint64 bytes = 5;
|
||||
|
||||
required fixed32 oldest_item_age = 6;
|
||||
}
|
||||
|
||||
message MemcacheStatsResponse {
|
||||
optional MergedNamespaceStats stats = 1;
|
||||
}
|
||||
|
||||
message MemcacheGrabTailRequest {
|
||||
required int32 item_count = 1;
|
||||
optional string name_space = 2 [default = ""];
|
||||
optional AppOverride override = 3;
|
||||
}
|
||||
|
||||
message MemcacheGrabTailResponse {
|
||||
repeated group Item = 1 {
|
||||
required bytes value = 2;
|
||||
optional fixed32 flags = 3;
|
||||
}
|
||||
}
|
526
vendor/google.golang.org/appengine/memcache/memcache.go
generated
vendored
Normal file
526
vendor/google.golang.org/appengine/memcache/memcache.go
generated
vendored
Normal file
@ -0,0 +1,526 @@
|
||||
// Copyright 2011 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package memcache provides a client for App Engine's distributed in-memory
|
||||
// key-value store for small chunks of arbitrary data.
|
||||
//
|
||||
// The fundamental operations get and set items, keyed by a string.
|
||||
//
|
||||
// item0, err := memcache.Get(c, "key")
|
||||
// if err != nil && err != memcache.ErrCacheMiss {
|
||||
// return err
|
||||
// }
|
||||
// if err == nil {
|
||||
// fmt.Fprintf(w, "memcache hit: Key=%q Val=[% x]\n", item0.Key, item0.Value)
|
||||
// } else {
|
||||
// fmt.Fprintf(w, "memcache miss\n")
|
||||
// }
|
||||
//
|
||||
// and
|
||||
//
|
||||
// item1 := &memcache.Item{
|
||||
// Key: "foo",
|
||||
// Value: []byte("bar"),
|
||||
// }
|
||||
// if err := memcache.Set(c, item1); err != nil {
|
||||
// return err
|
||||
// }
|
||||
package memcache // import "google.golang.org/appengine/memcache"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"google.golang.org/appengine"
|
||||
"google.golang.org/appengine/internal"
|
||||
pb "google.golang.org/appengine/internal/memcache"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCacheMiss means that an operation failed
|
||||
// because the item wasn't present.
|
||||
ErrCacheMiss = errors.New("memcache: cache miss")
|
||||
// ErrCASConflict means that a CompareAndSwap call failed due to the
|
||||
// cached value being modified between the Get and the CompareAndSwap.
|
||||
// If the cached value was simply evicted rather than replaced,
|
||||
// ErrNotStored will be returned instead.
|
||||
ErrCASConflict = errors.New("memcache: compare-and-swap conflict")
|
||||
// ErrNoStats means that no statistics were available.
|
||||
ErrNoStats = errors.New("memcache: no statistics available")
|
||||
// ErrNotStored means that a conditional write operation (i.e. Add or
|
||||
// CompareAndSwap) failed because the condition was not satisfied.
|
||||
ErrNotStored = errors.New("memcache: item not stored")
|
||||
// ErrServerError means that a server error occurred.
|
||||
ErrServerError = errors.New("memcache: server error")
|
||||
)
|
||||
|
||||
// Item is the unit of memcache gets and sets.
|
||||
type Item struct {
|
||||
// Key is the Item's key (250 bytes maximum).
|
||||
Key string
|
||||
// Value is the Item's value.
|
||||
Value []byte
|
||||
// Object is the Item's value for use with a Codec.
|
||||
Object interface{}
|
||||
// Flags are server-opaque flags whose semantics are entirely up to the
|
||||
// App Engine app.
|
||||
Flags uint32
|
||||
// Expiration is the maximum duration that the item will stay
|
||||
// in the cache.
|
||||
// The zero value means the Item has no expiration time.
|
||||
// Subsecond precision is ignored.
|
||||
// This is not set when getting items.
|
||||
Expiration time.Duration
|
||||
// casID is a client-opaque value used for compare-and-swap operations.
|
||||
// Zero means that compare-and-swap is not used.
|
||||
casID uint64
|
||||
}
|
||||
|
||||
const (
|
||||
secondsIn30Years = 60 * 60 * 24 * 365 * 30 // from memcache server code
|
||||
thirtyYears = time.Duration(secondsIn30Years) * time.Second
|
||||
)
|
||||
|
||||
// protoToItem converts a protocol buffer item to a Go struct.
|
||||
func protoToItem(p *pb.MemcacheGetResponse_Item) *Item {
|
||||
return &Item{
|
||||
Key: string(p.Key),
|
||||
Value: p.Value,
|
||||
Flags: p.GetFlags(),
|
||||
casID: p.GetCasId(),
|
||||
}
|
||||
}
|
||||
|
||||
// If err is an appengine.MultiError, return its first element. Otherwise, return err.
|
||||
func singleError(err error) error {
|
||||
if me, ok := err.(appengine.MultiError); ok {
|
||||
return me[0]
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Get gets the item for the given key. ErrCacheMiss is returned for a memcache
|
||||
// cache miss. The key must be at most 250 bytes in length.
|
||||
func Get(c context.Context, key string) (*Item, error) {
|
||||
m, err := GetMulti(c, []string{key})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := m[key]; !ok {
|
||||
return nil, ErrCacheMiss
|
||||
}
|
||||
return m[key], nil
|
||||
}
|
||||
|
||||
// GetMulti is a batch version of Get. The returned map from keys to items may
|
||||
// have fewer elements than the input slice, due to memcache cache misses.
|
||||
// Each key must be at most 250 bytes in length.
|
||||
func GetMulti(c context.Context, key []string) (map[string]*Item, error) {
|
||||
if len(key) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
keyAsBytes := make([][]byte, len(key))
|
||||
for i, k := range key {
|
||||
keyAsBytes[i] = []byte(k)
|
||||
}
|
||||
req := &pb.MemcacheGetRequest{
|
||||
Key: keyAsBytes,
|
||||
ForCas: proto.Bool(true),
|
||||
}
|
||||
res := &pb.MemcacheGetResponse{}
|
||||
if err := internal.Call(c, "memcache", "Get", req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[string]*Item, len(res.Item))
|
||||
for _, p := range res.Item {
|
||||
t := protoToItem(p)
|
||||
m[t.Key] = t
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Delete deletes the item for the given key.
|
||||
// ErrCacheMiss is returned if the specified item can not be found.
|
||||
// The key must be at most 250 bytes in length.
|
||||
func Delete(c context.Context, key string) error {
|
||||
return singleError(DeleteMulti(c, []string{key}))
|
||||
}
|
||||
|
||||
// DeleteMulti is a batch version of Delete.
|
||||
// If any keys cannot be found, an appengine.MultiError is returned.
|
||||
// Each key must be at most 250 bytes in length.
|
||||
func DeleteMulti(c context.Context, key []string) error {
|
||||
if len(key) == 0 {
|
||||
return nil
|
||||
}
|
||||
req := &pb.MemcacheDeleteRequest{
|
||||
Item: make([]*pb.MemcacheDeleteRequest_Item, len(key)),
|
||||
}
|
||||
for i, k := range key {
|
||||
req.Item[i] = &pb.MemcacheDeleteRequest_Item{Key: []byte(k)}
|
||||
}
|
||||
res := &pb.MemcacheDeleteResponse{}
|
||||
if err := internal.Call(c, "memcache", "Delete", req, res); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(res.DeleteStatus) != len(key) {
|
||||
return ErrServerError
|
||||
}
|
||||
me, any := make(appengine.MultiError, len(key)), false
|
||||
for i, s := range res.DeleteStatus {
|
||||
switch s {
|
||||
case pb.MemcacheDeleteResponse_DELETED:
|
||||
// OK
|
||||
case pb.MemcacheDeleteResponse_NOT_FOUND:
|
||||
me[i] = ErrCacheMiss
|
||||
any = true
|
||||
default:
|
||||
me[i] = ErrServerError
|
||||
any = true
|
||||
}
|
||||
}
|
||||
if any {
|
||||
return me
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Increment atomically increments the decimal value in the given key
|
||||
// by delta and returns the new value. The value must fit in a uint64.
|
||||
// Overflow wraps around, and underflow is capped to zero. The
|
||||
// provided delta may be negative. If the key doesn't exist in
|
||||
// memcache, the provided initial value is used to atomically
|
||||
// populate it before the delta is applied.
|
||||
// The key must be at most 250 bytes in length.
|
||||
func Increment(c context.Context, key string, delta int64, initialValue uint64) (newValue uint64, err error) {
|
||||
return incr(c, key, delta, &initialValue)
|
||||
}
|
||||
|
||||
// IncrementExisting works like Increment but assumes that the key
|
||||
// already exists in memcache and doesn't take an initial value.
|
||||
// IncrementExisting can save work if calculating the initial value is
|
||||
// expensive.
|
||||
// An error is returned if the specified item can not be found.
|
||||
func IncrementExisting(c context.Context, key string, delta int64) (newValue uint64, err error) {
|
||||
return incr(c, key, delta, nil)
|
||||
}
|
||||
|
||||
func incr(c context.Context, key string, delta int64, initialValue *uint64) (newValue uint64, err error) {
|
||||
req := &pb.MemcacheIncrementRequest{
|
||||
Key: []byte(key),
|
||||
InitialValue: initialValue,
|
||||
}
|
||||
if delta >= 0 {
|
||||
req.Delta = proto.Uint64(uint64(delta))
|
||||
} else {
|
||||
req.Delta = proto.Uint64(uint64(-delta))
|
||||
req.Direction = pb.MemcacheIncrementRequest_DECREMENT.Enum()
|
||||
}
|
||||
res := &pb.MemcacheIncrementResponse{}
|
||||
err = internal.Call(c, "memcache", "Increment", req, res)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if res.NewValue == nil {
|
||||
return 0, ErrCacheMiss
|
||||
}
|
||||
return *res.NewValue, nil
|
||||
}
|
||||
|
||||
// set sets the given items using the given conflict resolution policy.
|
||||
// appengine.MultiError may be returned.
|
||||
func set(c context.Context, item []*Item, value [][]byte, policy pb.MemcacheSetRequest_SetPolicy) error {
|
||||
if len(item) == 0 {
|
||||
return nil
|
||||
}
|
||||
req := &pb.MemcacheSetRequest{
|
||||
Item: make([]*pb.MemcacheSetRequest_Item, len(item)),
|
||||
}
|
||||
for i, t := range item {
|
||||
p := &pb.MemcacheSetRequest_Item{
|
||||
Key: []byte(t.Key),
|
||||
}
|
||||
if value == nil {
|
||||
p.Value = t.Value
|
||||
} else {
|
||||
p.Value = value[i]
|
||||
}
|
||||
if t.Flags != 0 {
|
||||
p.Flags = proto.Uint32(t.Flags)
|
||||
}
|
||||
if t.Expiration != 0 {
|
||||
// In the .proto file, MemcacheSetRequest_Item uses a fixed32 (i.e. unsigned)
|
||||
// for expiration time, while MemcacheGetRequest_Item uses int32 (i.e. signed).
|
||||
// Throughout this .go file, we use int32.
|
||||
// Also, in the proto, the expiration value is either a duration (in seconds)
|
||||
// or an absolute Unix timestamp (in seconds), depending on whether the
|
||||
// value is less than or greater than or equal to 30 years, respectively.
|
||||
if t.Expiration < time.Second {
|
||||
// Because an Expiration of 0 means no expiration, we take
|
||||
// care here to translate an item with an expiration
|
||||
// Duration between 0-1 seconds as immediately expiring
|
||||
// (saying it expired a few seconds ago), rather than
|
||||
// rounding it down to 0 and making it live forever.
|
||||
p.ExpirationTime = proto.Uint32(uint32(time.Now().Unix()) - 5)
|
||||
} else if t.Expiration >= thirtyYears {
|
||||
p.ExpirationTime = proto.Uint32(uint32(time.Now().Unix()) + uint32(t.Expiration/time.Second))
|
||||
} else {
|
||||
p.ExpirationTime = proto.Uint32(uint32(t.Expiration / time.Second))
|
||||
}
|
||||
}
|
||||
if t.casID != 0 {
|
||||
p.CasId = proto.Uint64(t.casID)
|
||||
p.ForCas = proto.Bool(true)
|
||||
}
|
||||
p.SetPolicy = policy.Enum()
|
||||
req.Item[i] = p
|
||||
}
|
||||
res := &pb.MemcacheSetResponse{}
|
||||
if err := internal.Call(c, "memcache", "Set", req, res); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(res.SetStatus) != len(item) {
|
||||
return ErrServerError
|
||||
}
|
||||
me, any := make(appengine.MultiError, len(item)), false
|
||||
for i, st := range res.SetStatus {
|
||||
var err error
|
||||
switch st {
|
||||
case pb.MemcacheSetResponse_STORED:
|
||||
// OK
|
||||
case pb.MemcacheSetResponse_NOT_STORED:
|
||||
err = ErrNotStored
|
||||
case pb.MemcacheSetResponse_EXISTS:
|
||||
err = ErrCASConflict
|
||||
default:
|
||||
err = ErrServerError
|
||||
}
|
||||
if err != nil {
|
||||
me[i] = err
|
||||
any = true
|
||||
}
|
||||
}
|
||||
if any {
|
||||
return me
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set writes the given item, unconditionally.
|
||||
func Set(c context.Context, item *Item) error {
|
||||
return singleError(set(c, []*Item{item}, nil, pb.MemcacheSetRequest_SET))
|
||||
}
|
||||
|
||||
// SetMulti is a batch version of Set.
|
||||
// appengine.MultiError may be returned.
|
||||
func SetMulti(c context.Context, item []*Item) error {
|
||||
return set(c, item, nil, pb.MemcacheSetRequest_SET)
|
||||
}
|
||||
|
||||
// Add writes the given item, if no value already exists for its key.
|
||||
// ErrNotStored is returned if that condition is not met.
|
||||
func Add(c context.Context, item *Item) error {
|
||||
return singleError(set(c, []*Item{item}, nil, pb.MemcacheSetRequest_ADD))
|
||||
}
|
||||
|
||||
// AddMulti is a batch version of Add.
|
||||
// appengine.MultiError may be returned.
|
||||
func AddMulti(c context.Context, item []*Item) error {
|
||||
return set(c, item, nil, pb.MemcacheSetRequest_ADD)
|
||||
}
|
||||
|
||||
// CompareAndSwap writes the given item that was previously returned by Get,
|
||||
// if the value was neither modified or evicted between the Get and the
|
||||
// CompareAndSwap calls. The item's Key should not change between calls but
|
||||
// all other item fields may differ.
|
||||
// ErrCASConflict is returned if the value was modified in between the calls.
|
||||
// ErrNotStored is returned if the value was evicted in between the calls.
|
||||
func CompareAndSwap(c context.Context, item *Item) error {
|
||||
return singleError(set(c, []*Item{item}, nil, pb.MemcacheSetRequest_CAS))
|
||||
}
|
||||
|
||||
// CompareAndSwapMulti is a batch version of CompareAndSwap.
|
||||
// appengine.MultiError may be returned.
|
||||
func CompareAndSwapMulti(c context.Context, item []*Item) error {
|
||||
return set(c, item, nil, pb.MemcacheSetRequest_CAS)
|
||||
}
|
||||
|
||||
// Codec represents a symmetric pair of functions that implement a codec.
|
||||
// Items stored into or retrieved from memcache using a Codec have their
|
||||
// values marshaled or unmarshaled.
|
||||
//
|
||||
// All the methods provided for Codec behave analogously to the package level
|
||||
// function with same name.
|
||||
type Codec struct {
|
||||
Marshal func(interface{}) ([]byte, error)
|
||||
Unmarshal func([]byte, interface{}) error
|
||||
}
|
||||
|
||||
// Get gets the item for the given key and decodes the obtained value into v.
|
||||
// ErrCacheMiss is returned for a memcache cache miss.
|
||||
// The key must be at most 250 bytes in length.
|
||||
func (cd Codec) Get(c context.Context, key string, v interface{}) (*Item, error) {
|
||||
i, err := Get(c, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cd.Unmarshal(i.Value, v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (cd Codec) set(c context.Context, items []*Item, policy pb.MemcacheSetRequest_SetPolicy) error {
|
||||
var vs [][]byte
|
||||
var me appengine.MultiError
|
||||
for i, item := range items {
|
||||
v, err := cd.Marshal(item.Object)
|
||||
if err != nil {
|
||||
if me == nil {
|
||||
me = make(appengine.MultiError, len(items))
|
||||
}
|
||||
me[i] = err
|
||||
continue
|
||||
}
|
||||
if me == nil {
|
||||
vs = append(vs, v)
|
||||
}
|
||||
}
|
||||
if me != nil {
|
||||
return me
|
||||
}
|
||||
|
||||
return set(c, items, vs, policy)
|
||||
}
|
||||
|
||||
// Set writes the given item, unconditionally.
|
||||
func (cd Codec) Set(c context.Context, item *Item) error {
|
||||
return singleError(cd.set(c, []*Item{item}, pb.MemcacheSetRequest_SET))
|
||||
}
|
||||
|
||||
// SetMulti is a batch version of Set.
|
||||
// appengine.MultiError may be returned.
|
||||
func (cd Codec) SetMulti(c context.Context, items []*Item) error {
|
||||
return cd.set(c, items, pb.MemcacheSetRequest_SET)
|
||||
}
|
||||
|
||||
// Add writes the given item, if no value already exists for its key.
|
||||
// ErrNotStored is returned if that condition is not met.
|
||||
func (cd Codec) Add(c context.Context, item *Item) error {
|
||||
return singleError(cd.set(c, []*Item{item}, pb.MemcacheSetRequest_ADD))
|
||||
}
|
||||
|
||||
// AddMulti is a batch version of Add.
|
||||
// appengine.MultiError may be returned.
|
||||
func (cd Codec) AddMulti(c context.Context, items []*Item) error {
|
||||
return cd.set(c, items, pb.MemcacheSetRequest_ADD)
|
||||
}
|
||||
|
||||
// CompareAndSwap writes the given item that was previously returned by Get,
|
||||
// if the value was neither modified or evicted between the Get and the
|
||||
// CompareAndSwap calls. The item's Key should not change between calls but
|
||||
// all other item fields may differ.
|
||||
// ErrCASConflict is returned if the value was modified in between the calls.
|
||||
// ErrNotStored is returned if the value was evicted in between the calls.
|
||||
func (cd Codec) CompareAndSwap(c context.Context, item *Item) error {
|
||||
return singleError(cd.set(c, []*Item{item}, pb.MemcacheSetRequest_CAS))
|
||||
}
|
||||
|
||||
// CompareAndSwapMulti is a batch version of CompareAndSwap.
|
||||
// appengine.MultiError may be returned.
|
||||
func (cd Codec) CompareAndSwapMulti(c context.Context, items []*Item) error {
|
||||
return cd.set(c, items, pb.MemcacheSetRequest_CAS)
|
||||
}
|
||||
|
||||
var (
|
||||
// Gob is a Codec that uses the gob package.
|
||||
Gob = Codec{gobMarshal, gobUnmarshal}
|
||||
// JSON is a Codec that uses the json package.
|
||||
JSON = Codec{json.Marshal, json.Unmarshal}
|
||||
)
|
||||
|
||||
func gobMarshal(v interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := gob.NewEncoder(&buf).Encode(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func gobUnmarshal(data []byte, v interface{}) error {
|
||||
return gob.NewDecoder(bytes.NewBuffer(data)).Decode(v)
|
||||
}
|
||||
|
||||
// Statistics represents a set of statistics about the memcache cache.
|
||||
// This may include items that have expired but have not yet been removed from the cache.
|
||||
type Statistics struct {
|
||||
Hits uint64 // Counter of cache hits
|
||||
Misses uint64 // Counter of cache misses
|
||||
ByteHits uint64 // Counter of bytes transferred for gets
|
||||
|
||||
Items uint64 // Items currently in the cache
|
||||
Bytes uint64 // Size of all items currently in the cache
|
||||
|
||||
Oldest int64 // Age of access of the oldest item, in seconds
|
||||
}
|
||||
|
||||
// Stats retrieves the current memcache statistics.
|
||||
func Stats(c context.Context) (*Statistics, error) {
|
||||
req := &pb.MemcacheStatsRequest{}
|
||||
res := &pb.MemcacheStatsResponse{}
|
||||
if err := internal.Call(c, "memcache", "Stats", req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.Stats == nil {
|
||||
return nil, ErrNoStats
|
||||
}
|
||||
return &Statistics{
|
||||
Hits: *res.Stats.Hits,
|
||||
Misses: *res.Stats.Misses,
|
||||
ByteHits: *res.Stats.ByteHits,
|
||||
Items: *res.Stats.Items,
|
||||
Bytes: *res.Stats.Bytes,
|
||||
Oldest: int64(*res.Stats.OldestItemAge),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Flush flushes all items from memcache.
|
||||
func Flush(c context.Context) error {
|
||||
req := &pb.MemcacheFlushRequest{}
|
||||
res := &pb.MemcacheFlushResponse{}
|
||||
return internal.Call(c, "memcache", "FlushAll", req, res)
|
||||
}
|
||||
|
||||
func namespaceMod(m proto.Message, namespace string) {
|
||||
switch m := m.(type) {
|
||||
case *pb.MemcacheDeleteRequest:
|
||||
if m.NameSpace == nil {
|
||||
m.NameSpace = &namespace
|
||||
}
|
||||
case *pb.MemcacheGetRequest:
|
||||
if m.NameSpace == nil {
|
||||
m.NameSpace = &namespace
|
||||
}
|
||||
case *pb.MemcacheIncrementRequest:
|
||||
if m.NameSpace == nil {
|
||||
m.NameSpace = &namespace
|
||||
}
|
||||
case *pb.MemcacheSetRequest:
|
||||
if m.NameSpace == nil {
|
||||
m.NameSpace = &namespace
|
||||
}
|
||||
// MemcacheFlushRequest, MemcacheStatsRequest do not apply namespace.
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
internal.RegisterErrorCodeMap("memcache", pb.MemcacheServiceError_ErrorCode_name)
|
||||
internal.NamespaceMods["memcache"] = namespaceMod
|
||||
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -416,12 +416,14 @@ google.golang.org/appengine/internal/base
|
||||
google.golang.org/appengine/internal/datastore
|
||||
google.golang.org/appengine/internal/log
|
||||
google.golang.org/appengine/internal/mail
|
||||
google.golang.org/appengine/internal/memcache
|
||||
google.golang.org/appengine/internal/modules
|
||||
google.golang.org/appengine/internal/remote_api
|
||||
google.golang.org/appengine/internal/urlfetch
|
||||
google.golang.org/appengine/internal/user
|
||||
google.golang.org/appengine/log
|
||||
google.golang.org/appengine/mail
|
||||
google.golang.org/appengine/memcache
|
||||
google.golang.org/appengine/urlfetch
|
||||
google.golang.org/appengine/user
|
||||
# google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5
|
||||
|
Loading…
Reference in New Issue
Block a user