Index: impl/memory/memcache.go |
diff --git a/impl/memory/memcache.go b/impl/memory/memcache.go |
index 1be03861ce851fdd81cb44a290cb522ead0b91d9..4a38c026a0fc3a06d9859e2d431f86fb8c5fea09 100644 |
--- a/impl/memory/memcache.go |
+++ b/impl/memory/memcache.go |
@@ -50,42 +50,47 @@ func (m *mcItem) SetExpiration(exp time.Duration) mc.Item { |
} |
func (m *mcItem) SetAll(other mc.Item) { |
- *m = *other.(*mcItem).duplicate(false) |
+ *m = *other.(*mcItem) |
} |
-func (m *mcItem) duplicate(deep bool) *mcItem { |
- ret := mcItem{} |
- ret = *m |
- if deep { |
- ret.value = make([]byte, len(m.value)) |
- copy(ret.value, m.value) |
- } |
- return &ret |
+type mcDataItem struct { |
+ value []byte |
+ flags uint32 |
+ expiration time.Time |
+ casID uint64 |
+} |
+ |
+func (m *mcDataItem) toUserItem(key string) *mcItem { |
+ value := make([]byte, len(m.value)) |
+ copy(value, m.value) |
+ // Expiration is defined to be 0 when retrieving items from memcache. |
+ // https://cloud.google.com/appengine/docs/go/memcache/reference#Item |
+ // ¯\_(ツ)_/¯ |
+ return &mcItem{key, value, m.flags, 0, m.casID} |
} |
type memcacheData struct { |
lock sync.RWMutex |
- items map[string]*mcItem |
+ items map[string]*mcDataItem |
casID uint64 |
stats mc.Statistics |
} |
-func (m *memcacheData) mkItemLocked(now time.Time, i mc.Item) (ret *mcItem) { |
+func (m *memcacheData) mkDataItemLocked(now time.Time, i mc.Item) (ret *mcDataItem) { |
m.casID++ |
- var exp time.Duration |
+ exp := time.Time{} |
if i.Expiration() != 0 { |
- exp = time.Duration(now.Add(i.Expiration()).UnixNano()) |
+ exp = now.Add(i.Expiration()).Truncate(time.Second) |
} |
value := make([]byte, len(i.Value())) |
copy(value, i.Value()) |
- return &mcItem{ |
- key: i.Key(), |
+ return &mcDataItem{ |
flags: i.Flags(), |
expiration: exp, |
value: value, |
- CasID: m.casID, |
+ casID: m.casID, |
} |
} |
@@ -96,7 +101,7 @@ func (m *memcacheData) setItemLocked(now time.Time, i mc.Item) { |
} |
m.stats.Items++ |
m.stats.Bytes += uint64(len(i.Value())) |
- m.items[i.Key()] = m.mkItemLocked(now, i) |
+ m.items[i.Key()] = m.mkDataItemLocked(now, i) |
} |
func (m *memcacheData) delItemLocked(k string) { |
@@ -109,19 +114,19 @@ func (m *memcacheData) delItemLocked(k string) { |
func (m *memcacheData) reset() { |
m.stats = mc.Statistics{} |
- m.items = map[string]*mcItem{} |
+ m.items = map[string]*mcDataItem{} |
} |
func (m *memcacheData) hasItemLocked(now time.Time, key string) bool { |
ret, ok := m.items[key] |
- if ok && ret.Expiration() != 0 && ret.Expiration() < time.Duration(now.UnixNano()) { |
+ if ok && !ret.expiration.IsZero() && ret.expiration.Before(now) { |
m.delItemLocked(key) |
return false |
} |
return ok |
} |
-func (m *memcacheData) retrieveLocked(now time.Time, key string) (*mcItem, error) { |
+func (m *memcacheData) retrieveLocked(now time.Time, key string) (*mcDataItem, error) { |
if !m.hasItemLocked(now, key) { |
m.stats.Misses++ |
return nil, mc.ErrCacheMiss |
@@ -155,7 +160,7 @@ func useMC(c context.Context) context.Context { |
ns := curGID(ic).namespace |
mcd, ok := mcdMap[ns] |
if !ok { |
- mcd = &memcacheData{items: map[string]*mcItem{}} |
+ mcd = &memcacheData{items: map[string]*mcDataItem{}} |
mcdMap[ns] = mcd |
} |
@@ -213,7 +218,7 @@ func (m *memcacheImpl) CompareAndSwapMulti(items []mc.Item, cb mc.RawCB) error { |
casid = mi.CasID |
} |
- if cur.CasID == casid { |
+ if cur.casID == casid { |
m.data.setItemLocked(now, itm) |
} else { |
return mc.ErrCASConflict |
@@ -250,7 +255,7 @@ func (m *memcacheImpl) GetMulti(keys []string, cb mc.RawItemCB) error { |
if err != nil { |
return nil, err |
} |
- return val.duplicate(true).SetExpiration(0), nil |
+ return val.toUserItem(k), nil |
}() |
} |