117 self._hits = 0 |
117 self._hits = 0 |
118 self._misses = 0 |
118 self._misses = 0 |
119 self._byte_hits = 0 |
119 self._byte_hits = 0 |
120 self._cache_creation_time = self._gettime() |
120 self._cache_creation_time = self._gettime() |
121 |
121 |
122 def _GetKey(self, key): |
122 def _GetKey(self, namespace, key): |
123 """Retrieves a CacheEntry from the cache if it hasn't expired. |
123 """Retrieves a CacheEntry from the cache if it hasn't expired. |
124 |
124 |
125 Does not take deletion timeout into account. |
125 Does not take deletion timeout into account. |
126 |
126 |
127 Args: |
127 Args: |
|
128 namespace: The namespace that keys are stored under. |
128 key: The key to retrieve from the cache. |
129 key: The key to retrieve from the cache. |
129 |
130 |
130 Returns: |
131 Returns: |
131 The corresponding CacheEntry instance, or None if it was not found or |
132 The corresponding CacheEntry instance, or None if it was not found or |
132 has already expired. |
133 has already expired. |
133 """ |
134 """ |
134 entry = self._the_cache.get(key, None) |
135 namespace_dict = self._the_cache.get(namespace, None) |
|
136 if namespace_dict is None: |
|
137 return None |
|
138 entry = namespace_dict.get(key, None) |
135 if entry is None: |
139 if entry is None: |
136 return None |
140 return None |
137 elif entry.CheckExpired(): |
141 elif entry.CheckExpired(): |
138 del self._the_cache[key] |
142 del namespace_dict[key] |
139 return None |
143 return None |
140 else: |
144 else: |
141 return entry |
145 return entry |
142 |
146 |
143 def _Dynamic_Get(self, request, response): |
147 def _Dynamic_Get(self, request, response): |
145 |
149 |
146 Args: |
150 Args: |
147 request: A MemcacheGetRequest. |
151 request: A MemcacheGetRequest. |
148 response: A MemcacheGetResponse. |
152 response: A MemcacheGetResponse. |
149 """ |
153 """ |
|
154 namespace = request.name_space() |
150 keys = set(request.key_list()) |
155 keys = set(request.key_list()) |
151 for key in keys: |
156 for key in keys: |
152 entry = self._GetKey(key) |
157 entry = self._GetKey(namespace, key) |
153 if entry is None or entry.CheckLocked(): |
158 if entry is None or entry.CheckLocked(): |
154 self._misses += 1 |
159 self._misses += 1 |
155 continue |
160 continue |
156 self._hits += 1 |
161 self._hits += 1 |
157 self._byte_hits += len(entry.value) |
162 self._byte_hits += len(entry.value) |
165 |
170 |
166 Args: |
171 Args: |
167 request: A MemcacheSetRequest. |
172 request: A MemcacheSetRequest. |
168 response: A MemcacheSetResponse. |
173 response: A MemcacheSetResponse. |
169 """ |
174 """ |
|
175 namespace = request.name_space() |
170 for item in request.item_list(): |
176 for item in request.item_list(): |
171 key = item.key() |
177 key = item.key() |
172 set_policy = item.set_policy() |
178 set_policy = item.set_policy() |
173 old_entry = self._GetKey(key) |
179 old_entry = self._GetKey(namespace, key) |
174 |
180 |
175 set_status = MemcacheSetResponse.NOT_STORED |
181 set_status = MemcacheSetResponse.NOT_STORED |
176 if ((set_policy == MemcacheSetRequest.SET) or |
182 if ((set_policy == MemcacheSetRequest.SET) or |
177 (set_policy == MemcacheSetRequest.ADD and old_entry is None) or |
183 (set_policy == MemcacheSetRequest.ADD and old_entry is None) or |
178 (set_policy == MemcacheSetRequest.REPLACE and old_entry is not None)): |
184 (set_policy == MemcacheSetRequest.REPLACE and old_entry is not None)): |
179 |
185 |
180 if (old_entry is None or |
186 if (old_entry is None or |
181 set_policy == MemcacheSetRequest.SET |
187 set_policy == MemcacheSetRequest.SET |
182 or not old_entry.CheckLocked()): |
188 or not old_entry.CheckLocked()): |
183 self._the_cache[key] = CacheEntry(item.value(), |
189 if namespace not in self._the_cache: |
184 item.expiration_time(), |
190 self._the_cache[namespace] = {} |
185 item.flags(), |
191 self._the_cache[namespace][key] = CacheEntry(item.value(), |
186 gettime=self._gettime) |
192 item.expiration_time(), |
|
193 item.flags(), |
|
194 gettime=self._gettime) |
187 set_status = MemcacheSetResponse.STORED |
195 set_status = MemcacheSetResponse.STORED |
188 |
196 |
189 response.add_set_status(set_status) |
197 response.add_set_status(set_status) |
190 |
198 |
191 def _Dynamic_Delete(self, request, response): |
199 def _Dynamic_Delete(self, request, response): |
193 |
201 |
194 Args: |
202 Args: |
195 request: A MemcacheDeleteRequest. |
203 request: A MemcacheDeleteRequest. |
196 response: A MemcacheDeleteResponse. |
204 response: A MemcacheDeleteResponse. |
197 """ |
205 """ |
|
206 namespace = request.name_space() |
198 for item in request.item_list(): |
207 for item in request.item_list(): |
199 key = item.key() |
208 key = item.key() |
200 entry = self._GetKey(key) |
209 entry = self._GetKey(namespace, key) |
201 |
210 |
202 delete_status = MemcacheDeleteResponse.DELETED |
211 delete_status = MemcacheDeleteResponse.DELETED |
203 if entry is None: |
212 if entry is None: |
204 delete_status = MemcacheDeleteResponse.NOT_FOUND |
213 delete_status = MemcacheDeleteResponse.NOT_FOUND |
205 elif item.delete_time() == 0: |
214 elif item.delete_time() == 0: |
206 del self._the_cache[key] |
215 del self._the_cache[namespace][key] |
207 else: |
216 else: |
208 entry.ExpireAndLock(item.delete_time()) |
217 entry.ExpireAndLock(item.delete_time()) |
209 |
218 |
210 response.add_delete_status(delete_status) |
219 response.add_delete_status(delete_status) |
211 |
220 |
214 |
223 |
215 Args: |
224 Args: |
216 request: A MemcacheIncrementRequest. |
225 request: A MemcacheIncrementRequest. |
217 response: A MemcacheIncrementResponse. |
226 response: A MemcacheIncrementResponse. |
218 """ |
227 """ |
|
228 namespace = request.name_space() |
219 key = request.key() |
229 key = request.key() |
220 entry = self._GetKey(key) |
230 entry = self._GetKey(namespace, key) |
221 if entry is None: |
231 if entry is None: |
222 return |
232 return |
223 |
233 |
224 try: |
234 try: |
225 old_value = long(entry.value) |
235 old_value = long(entry.value) |
226 if old_value < 0: |
236 if old_value < 0: |
227 raise ValueError |
237 raise ValueError |
228 except ValueError, e: |
238 except ValueError: |
229 logging.error('Increment/decrement failed: Could not interpret ' |
239 logging.error('Increment/decrement failed: Could not interpret ' |
230 'value for key = "%s" as an unsigned integer.', key) |
240 'value for key = "%s" as an unsigned integer.', key) |
231 return |
241 return |
232 |
242 |
233 delta = request.delta() |
243 delta = request.delta() |
260 """ |
270 """ |
261 stats = response.mutable_stats() |
271 stats = response.mutable_stats() |
262 stats.set_hits(self._hits) |
272 stats.set_hits(self._hits) |
263 stats.set_misses(self._misses) |
273 stats.set_misses(self._misses) |
264 stats.set_byte_hits(self._byte_hits) |
274 stats.set_byte_hits(self._byte_hits) |
265 stats.set_items(len(self._the_cache)) |
275 items = 0 |
266 |
|
267 total_bytes = 0 |
276 total_bytes = 0 |
268 for key, entry in self._the_cache.iteritems(): |
277 for namespace in self._the_cache.itervalues(): |
269 total_bytes += len(entry.value) |
278 items += len(namespace) |
|
279 for entry in namespace.itervalues(): |
|
280 total_bytes += len(entry.value) |
|
281 stats.set_items(items) |
270 stats.set_bytes(total_bytes) |
282 stats.set_bytes(total_bytes) |
271 |
283 |
272 stats.set_oldest_item_age(self._gettime() - self._cache_creation_time) |
284 stats.set_oldest_item_age(self._gettime() - self._cache_creation_time) |