Skip to content

Commit 07498a0

Browse files
author
Sean Reifschneider
committed
check_key disabling and performance improvements.
* Client() now takes a "check_key" option, which defaults to True. If False, it disables the checking of keys to ensure they have acceptable size and are composed of non-control characters. Suggested by Ben Hoyt. * Converting control character checking of keys based on performance testing of alternatives by Ben Hoyt.
1 parent 1b3f0c0 commit 07498a0

File tree

2 files changed

+28
-11
lines changed

2 files changed

+28
-11
lines changed

ChangeLog

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
* Client() now takes a "check_key" option, which defaults to True.
2+
If False, it disables the checking of keys to ensure they have
3+
acceptable size and are composed of non-control characters.
4+
Suggested by Ben Hoyt.
5+
6+
* Converting control character checking of keys based on performance
7+
testing of alternatives by Ben Hoyt.
8+
19
* Converted unicode tests from using u'', patch from Eren Güve.
210

311
* Included license file (pull request by "Philippe" pombredanne).

memcache.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ def decompress(val):
7777
except ImportError:
7878
from StringIO import StringIO
7979

80+
invalid_key_characters = ''.join(map(chr, range(33) + [127]))
81+
8082

8183
# Original author: Evan Martin of Danga Interactive
8284
__author__ = "Sean Reifschneider <jafo-memcached@tummy.com>"
@@ -161,7 +163,7 @@ def __init__(self, servers, debug=0, pickleProtocol=0,
161163
server_max_key_length=SERVER_MAX_KEY_LENGTH,
162164
server_max_value_length=SERVER_MAX_VALUE_LENGTH,
163165
dead_retry=_DEAD_RETRY, socket_timeout=_SOCKET_TIMEOUT,
164-
cache_cas = False, flush_on_reconnect=0):
166+
cache_cas = False, flush_on_reconnect=0, check_key=True):
165167
"""
166168
Create a new Client object with the given list of servers.
167169
@@ -194,6 +196,8 @@ def __init__(self, servers, debug=0, pickleProtocol=0,
194196
back, those keys will map to it again. If it still has its data, get()s
195197
can read stale data that was overwritten on another server. This flag
196198
is off by default for backwards compatibility.
199+
@param check_key: (default True) If True, the key is checked to
200+
ensure it is the correct length and composed of the right characters.
197201
"""
198202
local.__init__(self)
199203
self.debug = debug
@@ -204,6 +208,7 @@ def __init__(self, servers, debug=0, pickleProtocol=0,
204208
self.stats = {}
205209
self.cache_cas = cache_cas
206210
self.reset_cas()
211+
self.do_check_key = check_key
207212

208213
# Allow users to modify pickling/unpickling behavior
209214
self.pickleProtocol = pickleProtocol
@@ -430,7 +435,8 @@ def delete(self, key, time=0):
430435
should fail. Defaults to None for no delay.
431436
@rtype: int
432437
'''
433-
self.check_key(key)
438+
if self.do_check_key:
439+
self.check_key(key)
434440
server, key = self._get_server(key)
435441
if not server:
436442
return 0
@@ -490,7 +496,8 @@ def decr(self, key, delta=1):
490496
return self._incrdecr("decr", key, delta)
491497

492498
def _incrdecr(self, cmd, key, delta):
493-
self.check_key(key)
499+
if self.do_check_key:
500+
self.check_key(key)
494501
server, key = self._get_server(key)
495502
if not server:
496503
return None
@@ -615,7 +622,7 @@ def _map_and_prefix_keys(self, key_iterable, key_prefix):
615622
"""
616623
# Check it just once ...
617624
key_extra_len=len(key_prefix)
618-
if key_prefix:
625+
if key_prefix and self.do_check_key:
619626
self.check_key(key_prefix)
620627

621628
# server (_Host) -> list of unprefixed server keys in mapping
@@ -634,7 +641,8 @@ def _map_and_prefix_keys(self, key_iterable, key_prefix):
634641
server, key = self._get_server(key_prefix + str_orig_key)
635642

636643
# Now check to make sure key length is proper ...
637-
self.check_key(str_orig_key, key_extra_len=key_extra_len)
644+
if self.do_check_key:
645+
self.check_key(str_orig_key, key_extra_len=key_extra_len)
638646

639647
if not server:
640648
continue
@@ -781,7 +789,8 @@ def _val_to_store_info(self, val, min_compress_len):
781789
return (flags, len(val), val)
782790

783791
def _set(self, cmd, key, val, time, min_compress_len = 0):
784-
self.check_key(key)
792+
if self.do_check_key:
793+
self.check_key(key)
785794
server, key = self._get_server(key)
786795
if not server:
787796
return 0
@@ -823,7 +832,8 @@ def _unsafe_set():
823832
return 0
824833

825834
def _get(self, cmd, key):
826-
self.check_key(key)
835+
if self.do_check_key:
836+
self.check_key(key)
827837
server, key = self._get_server(key)
828838
if not server:
829839
return None
@@ -1036,10 +1046,9 @@ def check_key(self, key, key_extra_len=0):
10361046
len(key) + key_extra_len > self.server_max_key_length:
10371047
raise Client.MemcachedKeyLengthError("Key length is > %s"
10381048
% self.server_max_key_length)
1039-
for char in key:
1040-
if ord(char) < 33 or ord(char) == 127:
1041-
raise Client.MemcachedKeyCharacterError(
1042-
"Control characters not allowed")
1049+
if len(key) != len(key.translate(None, invalid_key_characters)):
1050+
raise Client.MemcachedKeyCharacterError(
1051+
"Control characters not allowed")
10431052

10441053

10451054
class _Host(object):

0 commit comments

Comments
 (0)