| Index: service/memcache/memcache.go
 | 
| diff --git a/service/memcache/memcache.go b/service/memcache/memcache.go
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..e9a1e40bd77ffc08e0440b43156c64ceb32af267
 | 
| --- /dev/null
 | 
| +++ b/service/memcache/memcache.go
 | 
| @@ -0,0 +1,106 @@
 | 
| +// 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 memcache
 | 
| +
 | 
| +import (
 | 
| +	"github.com/luci/luci-go/common/errors"
 | 
| +	"golang.org/x/net/context"
 | 
| +)
 | 
| +
 | 
| +type memcacheImpl struct{ RawInterface }
 | 
| +
 | 
| +var _ Interface = (*memcacheImpl)(nil)
 | 
| +
 | 
| +func (m *memcacheImpl) Add(item Item) error {
 | 
| +	return errors.SingleError(m.AddMulti([]Item{item}))
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) Set(item Item) error {
 | 
| +	return errors.SingleError(m.SetMulti([]Item{item}))
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) Get(item Item) error {
 | 
| +	return errors.SingleError(m.GetMulti([]Item{item}))
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) Delete(key string) error {
 | 
| +	return errors.SingleError(m.DeleteMulti([]string{key}))
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) CompareAndSwap(item Item) error {
 | 
| +	return errors.SingleError(m.CompareAndSwapMulti([]Item{item}))
 | 
| +}
 | 
| +
 | 
| +func multiCall(items []Item, inner func(items []Item, cb RawCB) error) error {
 | 
| +	lme := errors.LazyMultiError{Size: len(items)}
 | 
| +	i := 0
 | 
| +	err := inner(items, func(err error) {
 | 
| +		lme.Assign(i, err)
 | 
| +		i++
 | 
| +	})
 | 
| +	if err == nil {
 | 
| +		err = lme.Get()
 | 
| +	}
 | 
| +	return err
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) AddMulti(items []Item) error {
 | 
| +	return multiCall(items, m.RawInterface.AddMulti)
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) SetMulti(items []Item) error {
 | 
| +	return multiCall(items, m.RawInterface.SetMulti)
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) CompareAndSwapMulti(items []Item) error {
 | 
| +	return multiCall(items, m.RawInterface.CompareAndSwapMulti)
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) DeleteMulti(keys []string) error {
 | 
| +	lme := errors.LazyMultiError{Size: len(keys)}
 | 
| +	i := 0
 | 
| +	err := m.RawInterface.DeleteMulti(keys, func(err error) {
 | 
| +		lme.Assign(i, err)
 | 
| +		i++
 | 
| +	})
 | 
| +	if err == nil {
 | 
| +		err = lme.Get()
 | 
| +	}
 | 
| +	return err
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) GetMulti(items []Item) error {
 | 
| +	lme := errors.LazyMultiError{Size: len(items)}
 | 
| +	i := 0
 | 
| +	keys := make([]string, len(items))
 | 
| +	for i, itm := range items {
 | 
| +		keys[i] = itm.Key()
 | 
| +	}
 | 
| +	err := m.RawInterface.GetMulti(keys, func(item Item, err error) {
 | 
| +		if !lme.Assign(i, err) {
 | 
| +			items[i].SetAll(item)
 | 
| +		}
 | 
| +		i++
 | 
| +	})
 | 
| +	if err == nil {
 | 
| +		err = lme.Get()
 | 
| +	}
 | 
| +	return err
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) Increment(key string, delta int64, initialValue uint64) (newValue uint64, err error) {
 | 
| +	return m.RawInterface.Increment(key, delta, &initialValue)
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) IncrementExisting(key string, delta int64) (newValue uint64, err error) {
 | 
| +	return m.RawInterface.Increment(key, delta, nil)
 | 
| +}
 | 
| +
 | 
| +func (m *memcacheImpl) Raw() RawInterface { return m.RawInterface }
 | 
| +
 | 
| +// Get gets the current memcache implementation from the context.
 | 
| +func Get(c context.Context) Interface {
 | 
| +	return &memcacheImpl{GetRaw(c)}
 | 
| +}
 | 
| 
 |