| OLD | NEW | 
|    1 // Copyright 2015 The Chromium Authors. All rights reserved. |    1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 package memory |    5 package memory | 
|    6  |    6  | 
|    7 import ( |    7 import ( | 
|    8         "infra/gae/libs/wrapper" |    8         "infra/gae/libs/wrapper" | 
|    9         "infra/gae/libs/wrapper/gae/commonErrors" |    9         "infra/gae/libs/wrapper/gae/commonErrors" | 
|   10         "infra/gae/libs/wrapper/unsafe" |   10         "infra/gae/libs/wrapper/unsafe" | 
|   11         "sync" |   11         "sync" | 
|   12         "time" |   12         "time" | 
|   13  |   13  | 
|   14         "golang.org/x/net/context" |   14         "golang.org/x/net/context" | 
|   15  |   15  | 
|   16         "appengine/memcache" |   16         "appengine/memcache" | 
|   17 ) |   17 ) | 
|   18  |   18  | 
|   19 type memcacheData struct { |   19 type memcacheData struct { | 
 |   20         wrapper.BrokenFeatures | 
 |   21  | 
|   20         lock  sync.Mutex |   22         lock  sync.Mutex | 
|   21         items map[string]*unsafe.Item |   23         items map[string]*unsafe.Item | 
|   22         casID uint64 |   24         casID uint64 | 
|   23 } |   25 } | 
|   24  |   26  | 
|   25 // memcacheImpl binds the current connection's memcache data to an |   27 // memcacheImpl binds the current connection's memcache data to an | 
|   26 // implementation of {wrapper.Memcache, wrapper.Testable}. |   28 // implementation of {wrapper.Memcache, wrapper.Testable}. | 
|   27 type memcacheImpl struct { |   29 type memcacheImpl struct { | 
|   28         wrapper.Memcache |   30         wrapper.Memcache | 
|   29         wrapper.BrokenFeatures |  | 
|   30  |  | 
|   31         // TODO(riannucci): bind+use namespace too |  | 
|   32  |   31  | 
|   33         data    *memcacheData |   32         data    *memcacheData | 
|   34         timeNow func() time.Time |   33         timeNow func() time.Time | 
|   35 } |   34 } | 
|   36  |   35  | 
|   37 var ( |   36 var ( | 
|   38         _ = wrapper.Memcache((*memcacheImpl)(nil)) |   37         _ = wrapper.Memcache((*memcacheImpl)(nil)) | 
|   39         _ = wrapper.Testable((*memcacheImpl)(nil)) |   38         _ = wrapper.Testable((*memcacheImpl)(nil)) | 
|   40 ) |   39 ) | 
|   41  |   40  | 
|   42 // useMC adds a wrapper.Memcache implementation to context, accessible |   41 // useMC adds a wrapper.Memcache implementation to context, accessible | 
|   43 // by wrapper.GetMC(c) |   42 // by wrapper.GetMC(c) | 
|   44 func useMC(c context.Context) context.Context { |   43 func useMC(c context.Context) context.Context { | 
|   45         lck := sync.Mutex{} |   44         lck := sync.Mutex{} | 
|   46         mcdMap := map[string]*memcacheData{} |   45         mcdMap := map[string]*memcacheData{} | 
|   47  |   46  | 
|   48         return wrapper.SetMCFactory(c, func(ic context.Context) wrapper.Memcache
      { |   47         return wrapper.SetMCFactory(c, func(ic context.Context) wrapper.Memcache
      { | 
|   49                 lck.Lock() |   48                 lck.Lock() | 
|   50                 defer lck.Unlock() |   49                 defer lck.Unlock() | 
|   51  |   50  | 
|   52                 ns := curGID(ic).namespace |   51                 ns := curGID(ic).namespace | 
|   53                 mcd, ok := mcdMap[ns] |   52                 mcd, ok := mcdMap[ns] | 
|   54                 if !ok { |   53                 if !ok { | 
|   55 »       »       »       mcd = &memcacheData{items: map[string]*unsafe.Item{}} |   54 »       »       »       mcd = &memcacheData{ | 
 |   55 »       »       »       »       BrokenFeatures: wrapper.BrokenFeatures{ | 
 |   56 »       »       »       »       »       DefaultError: commonErrors.ErrServerErro
     rMC}, | 
 |   57 »       »       »       »       items: map[string]*unsafe.Item{}} | 
|   56                         mcdMap[ns] = mcd |   58                         mcdMap[ns] = mcd | 
|   57                 } |   59                 } | 
|   58  |   60  | 
|   59                 return &memcacheImpl{ |   61                 return &memcacheImpl{ | 
|   60                         wrapper.DummyMC(), |   62                         wrapper.DummyMC(), | 
|   61                         wrapper.BrokenFeatures{DefaultError: commonErrors.ErrSer
     verErrorMC}, |  | 
|   62                         mcd, |   63                         mcd, | 
|   63                         func() time.Time { return wrapper.GetTimeNow(ic) }, |   64                         func() time.Time { return wrapper.GetTimeNow(ic) }, | 
|   64                 } |   65                 } | 
|   65         }) |   66         }) | 
|   66 } |   67 } | 
|   67  |   68  | 
|   68 func (m *memcacheImpl) mkItemLocked(i *memcache.Item) *unsafe.Item { |   69 func (m *memcacheImpl) mkItemLocked(i *memcache.Item) *unsafe.Item { | 
|   69         m.data.casID++ |   70         m.data.casID++ | 
|   70         var exp time.Duration |   71         var exp time.Duration | 
|   71         if i.Expiration != 0 { |   72         if i.Expiration != 0 { | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|   97 func (m *memcacheImpl) retrieve(key string) (*unsafe.Item, bool) { |   98 func (m *memcacheImpl) retrieve(key string) (*unsafe.Item, bool) { | 
|   98         ret, ok := m.data.items[key] |   99         ret, ok := m.data.items[key] | 
|   99         if ok && ret.Expiration != 0 && ret.Expiration < time.Duration(m.timeNow
     ().UnixNano()) { |  100         if ok && ret.Expiration != 0 && ret.Expiration < time.Duration(m.timeNow
     ().UnixNano()) { | 
|  100                 ret = nil |  101                 ret = nil | 
|  101                 ok = false |  102                 ok = false | 
|  102                 delete(m.data.items, key) |  103                 delete(m.data.items, key) | 
|  103         } |  104         } | 
|  104         return ret, ok |  105         return ret, ok | 
|  105 } |  106 } | 
|  106  |  107  | 
 |  108 func (m *memcacheImpl) BreakFeatures(err error, features ...string) { | 
 |  109         m.data.BreakFeatures(err, features...) | 
 |  110 } | 
 |  111  | 
 |  112 func (m *memcacheImpl) UnbreakFeatures(features ...string) { | 
 |  113         m.data.UnbreakFeatures(features...) | 
 |  114 } | 
 |  115  | 
|  107 // Add implements context.MCSingleReadWriter.Add. |  116 // Add implements context.MCSingleReadWriter.Add. | 
|  108 func (m *memcacheImpl) Add(i *memcache.Item) error { |  117 func (m *memcacheImpl) Add(i *memcache.Item) error { | 
|  109 »       if err := m.IsBroken(); err != nil { |  118 »       if err := m.data.IsBroken(); err != nil { | 
|  110                 return err |  119                 return err | 
|  111         } |  120         } | 
|  112  |  121  | 
|  113         m.data.lock.Lock() |  122         m.data.lock.Lock() | 
|  114         defer m.data.lock.Unlock() |  123         defer m.data.lock.Unlock() | 
|  115  |  124  | 
|  116         if _, ok := m.retrieve(i.Key); !ok { |  125         if _, ok := m.retrieve(i.Key); !ok { | 
|  117                 m.data.items[i.Key] = m.mkItemLocked(i) |  126                 m.data.items[i.Key] = m.mkItemLocked(i) | 
|  118                 return nil |  127                 return nil | 
|  119         } |  128         } | 
|  120         return memcache.ErrNotStored |  129         return memcache.ErrNotStored | 
|  121 } |  130 } | 
|  122  |  131  | 
|  123 // CompareAndSwap implements context.MCSingleReadWriter.CompareAndSwap. |  132 // CompareAndSwap implements context.MCSingleReadWriter.CompareAndSwap. | 
|  124 func (m *memcacheImpl) CompareAndSwap(item *memcache.Item) error { |  133 func (m *memcacheImpl) CompareAndSwap(item *memcache.Item) error { | 
|  125 »       if err := m.IsBroken(); err != nil { |  134 »       if err := m.data.IsBroken(); err != nil { | 
|  126                 return err |  135                 return err | 
|  127         } |  136         } | 
|  128  |  137  | 
|  129         m.data.lock.Lock() |  138         m.data.lock.Lock() | 
|  130         defer m.data.lock.Unlock() |  139         defer m.data.lock.Unlock() | 
|  131  |  140  | 
|  132         if cur, ok := m.retrieve(item.Key); ok { |  141         if cur, ok := m.retrieve(item.Key); ok { | 
|  133                 if cur.CasID == unsafe.MCGetCasID(item) { |  142                 if cur.CasID == unsafe.MCGetCasID(item) { | 
|  134                         m.data.items[item.Key] = m.mkItemLocked(item) |  143                         m.data.items[item.Key] = m.mkItemLocked(item) | 
|  135                 } else { |  144                 } else { | 
|  136                         return memcache.ErrCASConflict |  145                         return memcache.ErrCASConflict | 
|  137                 } |  146                 } | 
|  138         } else { |  147         } else { | 
|  139                 return memcache.ErrNotStored |  148                 return memcache.ErrNotStored | 
|  140         } |  149         } | 
|  141         return nil |  150         return nil | 
|  142 } |  151 } | 
|  143  |  152  | 
|  144 // Set implements context.MCSingleReadWriter.Set. |  153 // Set implements context.MCSingleReadWriter.Set. | 
|  145 func (m *memcacheImpl) Set(i *memcache.Item) error { |  154 func (m *memcacheImpl) Set(i *memcache.Item) error { | 
|  146 »       if err := m.IsBroken(); err != nil { |  155 »       if err := m.data.IsBroken(); err != nil { | 
|  147                 return err |  156                 return err | 
|  148         } |  157         } | 
|  149  |  158  | 
|  150         m.data.lock.Lock() |  159         m.data.lock.Lock() | 
|  151         defer m.data.lock.Unlock() |  160         defer m.data.lock.Unlock() | 
|  152  |  161  | 
|  153         m.data.items[i.Key] = m.mkItemLocked(i) |  162         m.data.items[i.Key] = m.mkItemLocked(i) | 
|  154         return nil |  163         return nil | 
|  155 } |  164 } | 
|  156  |  165  | 
|  157 // Get implements context.MCSingleReadWriter.Get. |  166 // Get implements context.MCSingleReadWriter.Get. | 
|  158 func (m *memcacheImpl) Get(key string) (*memcache.Item, error) { |  167 func (m *memcacheImpl) Get(key string) (*memcache.Item, error) { | 
|  159 »       if err := m.IsBroken(); err != nil { |  168 »       if err := m.data.IsBroken(); err != nil { | 
|  160                 return nil, err |  169                 return nil, err | 
|  161         } |  170         } | 
|  162  |  171  | 
|  163         m.data.lock.Lock() |  172         m.data.lock.Lock() | 
|  164         defer m.data.lock.Unlock() |  173         defer m.data.lock.Unlock() | 
|  165  |  174  | 
|  166         if val, ok := m.retrieve(key); ok { |  175         if val, ok := m.retrieve(key); ok { | 
|  167                 return copyBack(val), nil |  176                 return copyBack(val), nil | 
|  168         } |  177         } | 
|  169         return nil, memcache.ErrCacheMiss |  178         return nil, memcache.ErrCacheMiss | 
|  170 } |  179 } | 
|  171  |  180  | 
|  172 // Delete implements context.MCSingleReadWriter.Delete. |  181 // Delete implements context.MCSingleReadWriter.Delete. | 
|  173 func (m *memcacheImpl) Delete(key string) error { |  182 func (m *memcacheImpl) Delete(key string) error { | 
|  174 »       if err := m.IsBroken(); err != nil { |  183 »       if err := m.data.IsBroken(); err != nil { | 
|  175                 return err |  184                 return err | 
|  176         } |  185         } | 
|  177  |  186  | 
|  178         m.data.lock.Lock() |  187         m.data.lock.Lock() | 
|  179         defer m.data.lock.Unlock() |  188         defer m.data.lock.Unlock() | 
|  180  |  189  | 
|  181         if _, ok := m.retrieve(key); ok { |  190         if _, ok := m.retrieve(key); ok { | 
|  182                 delete(m.data.items, key) |  191                 delete(m.data.items, key) | 
|  183                 return nil |  192                 return nil | 
|  184         } |  193         } | 
|  185         return memcache.ErrCacheMiss |  194         return memcache.ErrCacheMiss | 
|  186 } |  195 } | 
| OLD | NEW |