| Index: go/src/infra/gae/libs/wrapper/memory/memcache.go
|
| diff --git a/go/src/infra/gae/libs/wrapper/memory/memcache.go b/go/src/infra/gae/libs/wrapper/memory/memcache.go
|
| deleted file mode 100644
|
| index 2b48ca9c5842e256051a45f082791df216fad8b6..0000000000000000000000000000000000000000
|
| --- a/go/src/infra/gae/libs/wrapper/memory/memcache.go
|
| +++ /dev/null
|
| @@ -1,196 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package memory
|
| -
|
| -import (
|
| - "infra/gae/libs/wrapper"
|
| - "infra/gae/libs/wrapper/gae/commonErrors"
|
| - "infra/gae/libs/wrapper/unsafe"
|
| - "infra/libs/clock"
|
| - "sync"
|
| - "time"
|
| -
|
| - "golang.org/x/net/context"
|
| -
|
| - "appengine/memcache"
|
| -)
|
| -
|
| -type memcacheData struct {
|
| - wrapper.BrokenFeatures
|
| -
|
| - lock sync.Mutex
|
| - items map[string]*unsafe.Item
|
| - casID uint64
|
| -}
|
| -
|
| -// memcacheImpl binds the current connection's memcache data to an
|
| -// implementation of {wrapper.Memcache, wrapper.Testable}.
|
| -type memcacheImpl struct {
|
| - wrapper.Memcache
|
| -
|
| - data *memcacheData
|
| - ctx context.Context
|
| -}
|
| -
|
| -var (
|
| - _ = wrapper.Memcache((*memcacheImpl)(nil))
|
| - _ = wrapper.Testable((*memcacheImpl)(nil))
|
| -)
|
| -
|
| -// useMC adds a wrapper.Memcache implementation to context, accessible
|
| -// by wrapper.GetMC(c)
|
| -func useMC(c context.Context) context.Context {
|
| - lck := sync.Mutex{}
|
| - mcdMap := map[string]*memcacheData{}
|
| -
|
| - return wrapper.SetMCFactory(c, func(ic context.Context) wrapper.Memcache {
|
| - lck.Lock()
|
| - defer lck.Unlock()
|
| -
|
| - ns := curGID(ic).namespace
|
| - mcd, ok := mcdMap[ns]
|
| - if !ok {
|
| - mcd = &memcacheData{
|
| - BrokenFeatures: wrapper.BrokenFeatures{
|
| - DefaultError: commonErrors.ErrServerErrorMC},
|
| - items: map[string]*unsafe.Item{}}
|
| - mcdMap[ns] = mcd
|
| - }
|
| -
|
| - return &memcacheImpl{
|
| - wrapper.DummyMC(),
|
| - mcd,
|
| - ic,
|
| - }
|
| - })
|
| -}
|
| -
|
| -func (m *memcacheImpl) mkItemLocked(i *memcache.Item) *unsafe.Item {
|
| - m.data.casID++
|
| - var exp time.Duration
|
| - if i.Expiration != 0 {
|
| - exp = time.Duration(clock.Now(m.ctx).Add(i.Expiration).UnixNano())
|
| - }
|
| - newItem := unsafe.Item{
|
| - Key: i.Key,
|
| - Value: make([]byte, len(i.Value)),
|
| - Flags: i.Flags,
|
| - Expiration: exp,
|
| - CasID: m.data.casID,
|
| - }
|
| - copy(newItem.Value, i.Value)
|
| - return &newItem
|
| -}
|
| -
|
| -func copyBack(i *unsafe.Item) *memcache.Item {
|
| - ret := &memcache.Item{
|
| - Key: i.Key,
|
| - Value: make([]byte, len(i.Value)),
|
| - Flags: i.Flags,
|
| - }
|
| - copy(ret.Value, i.Value)
|
| - unsafe.MCSetCasID(ret, i.CasID)
|
| -
|
| - return ret
|
| -}
|
| -
|
| -func (m *memcacheImpl) retrieve(key string) (*unsafe.Item, bool) {
|
| - ret, ok := m.data.items[key]
|
| - if ok && ret.Expiration != 0 && ret.Expiration < time.Duration(clock.Now(m.ctx).UnixNano()) {
|
| - ret = nil
|
| - ok = false
|
| - delete(m.data.items, key)
|
| - }
|
| - return ret, ok
|
| -}
|
| -
|
| -func (m *memcacheImpl) BreakFeatures(err error, features ...string) {
|
| - m.data.BreakFeatures(err, features...)
|
| -}
|
| -
|
| -func (m *memcacheImpl) UnbreakFeatures(features ...string) {
|
| - m.data.UnbreakFeatures(features...)
|
| -}
|
| -
|
| -// Add implements context.MCSingleReadWriter.Add.
|
| -func (m *memcacheImpl) Add(i *memcache.Item) error {
|
| - if err := m.data.IsBroken(); err != nil {
|
| - return err
|
| - }
|
| -
|
| - m.data.lock.Lock()
|
| - defer m.data.lock.Unlock()
|
| -
|
| - if _, ok := m.retrieve(i.Key); !ok {
|
| - m.data.items[i.Key] = m.mkItemLocked(i)
|
| - return nil
|
| - }
|
| - return memcache.ErrNotStored
|
| -}
|
| -
|
| -// CompareAndSwap implements context.MCSingleReadWriter.CompareAndSwap.
|
| -func (m *memcacheImpl) CompareAndSwap(item *memcache.Item) error {
|
| - if err := m.data.IsBroken(); err != nil {
|
| - return err
|
| - }
|
| -
|
| - m.data.lock.Lock()
|
| - defer m.data.lock.Unlock()
|
| -
|
| - if cur, ok := m.retrieve(item.Key); ok {
|
| - if cur.CasID == unsafe.MCGetCasID(item) {
|
| - m.data.items[item.Key] = m.mkItemLocked(item)
|
| - } else {
|
| - return memcache.ErrCASConflict
|
| - }
|
| - } else {
|
| - return memcache.ErrNotStored
|
| - }
|
| - return nil
|
| -}
|
| -
|
| -// Set implements context.MCSingleReadWriter.Set.
|
| -func (m *memcacheImpl) Set(i *memcache.Item) error {
|
| - if err := m.data.IsBroken(); err != nil {
|
| - return err
|
| - }
|
| -
|
| - m.data.lock.Lock()
|
| - defer m.data.lock.Unlock()
|
| -
|
| - m.data.items[i.Key] = m.mkItemLocked(i)
|
| - return nil
|
| -}
|
| -
|
| -// Get implements context.MCSingleReadWriter.Get.
|
| -func (m *memcacheImpl) Get(key string) (*memcache.Item, error) {
|
| - if err := m.data.IsBroken(); err != nil {
|
| - return nil, err
|
| - }
|
| -
|
| - m.data.lock.Lock()
|
| - defer m.data.lock.Unlock()
|
| -
|
| - if val, ok := m.retrieve(key); ok {
|
| - return copyBack(val), nil
|
| - }
|
| - return nil, memcache.ErrCacheMiss
|
| -}
|
| -
|
| -// Delete implements context.MCSingleReadWriter.Delete.
|
| -func (m *memcacheImpl) Delete(key string) error {
|
| - if err := m.data.IsBroken(); err != nil {
|
| - return err
|
| - }
|
| -
|
| - m.data.lock.Lock()
|
| - defer m.data.lock.Unlock()
|
| -
|
| - if _, ok := m.retrieve(key); ok {
|
| - delete(m.data.items, key)
|
| - return nil
|
| - }
|
| - return memcache.ErrCacheMiss
|
| -}
|
|
|