memcached 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,4 +1,6 @@
1
1
 
2
+ v0.7.2. Auto-repair unprintable characters and too-long keys; improve performance of namespacing operation.
3
+
2
4
  v0.7.1. Allow for explicit resetting of the struct on each request, at least until Brian fixes the synchronization problem.
3
5
 
4
6
  v0.7. Rails compatibility wrapper; real multiget; rescue UnknownReadFailures in order to reset the struct..
@@ -4,6 +4,7 @@
4
4
  This chart shows which versions of the Ruby library are compatible with which versions of libmemcached.
5
5
 
6
6
  <b>Library version</b>:: <b>libmemcached version</b>
7
+ 0.7.1:: 0.15
7
8
  0.7:: 0.15
8
9
  0.6:: 0.13
9
10
  0.5:: 0.13
data/Manifest CHANGED
@@ -14,6 +14,7 @@ LICENSE
14
14
  Manifest
15
15
  README
16
16
  test/profile/benchmark.rb
17
+ test/profile/key.rb
17
18
  test/profile/profile.rb
18
19
  test/profile/valgrind.rb
19
20
  test/setup.rb
data/README CHANGED
@@ -22,7 +22,7 @@ The <b>memcached</b> library wraps the pure-C libmemcached client via SWIG.
22
22
 
23
23
  == Installation
24
24
 
25
- You need {libmemcached 0.15}[http://tangent.org/552/libmemcached.html]. Other versions of libmemcached are not supported. You also need {memcached itself}[http://www.danga.com/memcached/] if you want to test against a local server.
25
+ You need Ruby 1.8.6, and {libmemcached 0.15}[http://tangent.org/552/libmemcached.html]. Other versions are not supported. You also need {memcached itself}[http://www.danga.com/memcached/] if you want to test against a local server.
26
26
 
27
27
  Download and extract the {libmemcached tarball}[http://download.tangent.org/libmemcached-0.15.tar.gz]. Then for Linux, run:
28
28
  ./configure
@@ -35,6 +35,9 @@ For OS X/MacPorts, run:
35
35
  Now install the gem:
36
36
  sudo gem install memcached --no-rdoc --no-ri
37
37
 
38
+ Note that on OS X 10.5 you may need to set the architecture explicitly:
39
+ sudo env ARCHFLAGS="-arch i386" gem install memcached --no-rdoc --no-ri
40
+
38
41
  == Usage
39
42
 
40
43
  Start a local memcached server:
@@ -62,7 +65,9 @@ You can get multiple values at once:
62
65
 
63
66
  value = 'hello'
64
67
  $cache.set 'test', value
65
- $cache.get ['test', 'test2'] #=> ["hello", Memcached::NotFound]
68
+ $cache.set 'test2', value
69
+ $cache.get ['test', 'test2', 'missing']
70
+ #=> {"test" => "hello", "test2" => "hello"}
66
71
 
67
72
  You can set a counter and increment it:
68
73
 
@@ -12,11 +12,13 @@
12
12
  %include "typemaps.i"
13
13
 
14
14
  //// Input maps
15
+
15
16
  %apply unsigned short { uint8_t };
16
17
  %apply unsigned int { uint16_t };
17
18
  %apply unsigned long { uint32_t flags, uint32_t offset };
18
19
 
19
20
  // For behavior's weird set interface
21
+
20
22
  %typemap(in) (void *data) {
21
23
  int value = FIX2INT($input);
22
24
  if (value == 0 || value == 1) {
@@ -29,6 +31,7 @@
29
31
  };
30
32
 
31
33
  // Array of strings map for multiget
34
+
32
35
  %typemap(in) (char **keys, size_t *key_length, unsigned int number_of_keys) {
33
36
  int i;
34
37
  Check_Type($input, T_ARRAY);
@@ -46,23 +49,27 @@
46
49
  }
47
50
 
48
51
  // Generic strings
52
+
49
53
  %typemap(in) (char *str, size_t len) {
50
54
  $1 = STR2CSTR($input);
51
55
  $2 = (size_t) RSTRING($input)->len;
52
56
  };
53
57
 
54
58
  %apply (char *str, size_t len) {
59
+ (char *namespace, size_t namespace_length),
55
60
  (char *key, size_t key_length),
56
61
  (char *value, size_t value_length)
57
62
  };
58
63
 
59
64
  //// Output maps
65
+
60
66
  %apply unsigned short *OUTPUT {memcached_return *error}
61
67
  %apply unsigned int *OUTPUT {uint32_t *flags}
62
68
  %apply size_t *OUTPUT {size_t *value_length}
63
69
  %apply unsigned long long *OUTPUT {uint64_t *value}
64
70
 
65
71
  // String
72
+
66
73
  %typemap(in, numinputs=0) (char *key, size_t *key_length) {
67
74
  $1 = malloc(512*sizeof(char));
68
75
  $2 = malloc(sizeof(size_t)); // XXX Could possibly be the address of a local
@@ -76,6 +83,7 @@
76
83
  }
77
84
 
78
85
  // Array of strings
86
+
79
87
  %typemap(out) (char **) {
80
88
  int i;
81
89
  VALUE ary = rb_ary_new();
@@ -90,7 +98,33 @@
90
98
 
91
99
  %include "/opt/local/include/libmemcached/memcached.h"
92
100
 
93
- // Manual wrappers
101
+ //// Custom C functions
102
+
103
+ // Namespace and validate key. We could avoid several more dispatches and allocations if we called this from the libmemcached wrappers directly.
104
+
105
+ VALUE ns(char *namespace, size_t namespace_length, char *key, size_t key_length);
106
+ %{
107
+ VALUE ns(char *namespace, size_t namespace_length, char *key, size_t key_length) {
108
+ char namespaced_key[250];
109
+ size_t namespaced_key_length = namespace_length + key_length;
110
+
111
+ if (namespaced_key_length > 250)
112
+ namespaced_key_length = 250;
113
+
114
+ strncpy(namespaced_key, namespace, namespace_length);
115
+ strncpy(namespaced_key + namespace_length, key, namespaced_key_length - namespace_length);
116
+
117
+ int i;
118
+ for (i = 0; i < namespaced_key_length; i++)
119
+ if ((namespaced_key[i] < 33) || (namespaced_key[i] > 126))
120
+ // Outside printable range
121
+ namespaced_key[i] = '_';
122
+
123
+ return rb_str_new(namespaced_key, namespaced_key_length);
124
+ };
125
+ %}
126
+
127
+ //// Manual wrappers
94
128
 
95
129
  // Single get. SWIG likes to use SWIG_FromCharPtr instead of SWIG_FromCharPtrAndSize because
96
130
  // of the retval/argout split, so it truncates return values with \0 in them.
@@ -1869,6 +1869,26 @@ SWIG_From_unsigned_SS_long_SS_long (unsigned long long value)
1869
1869
  }
1870
1870
 
1871
1871
 
1872
+ VALUE ns(char *namespace, size_t namespace_length, char *key, size_t key_length) {
1873
+ char namespaced_key[250];
1874
+ size_t namespaced_key_length = namespace_length + key_length;
1875
+
1876
+ if (namespaced_key_length > 250)
1877
+ namespaced_key_length = 250;
1878
+
1879
+ strncpy(namespaced_key, namespace, namespace_length);
1880
+ strncpy(namespaced_key + namespace_length, key, namespaced_key_length - namespace_length);
1881
+
1882
+ int i;
1883
+ for (i = 0; i < namespaced_key_length; i++)
1884
+ if ((namespaced_key[i] < 33) || (namespaced_key[i] > 126))
1885
+ // Outside printable range
1886
+ namespaced_key[i] = '_';
1887
+
1888
+ return rb_str_new(namespaced_key, namespaced_key_length);
1889
+ };
1890
+
1891
+
1872
1892
  VALUE memcached_get_rvalue(memcached_st *ptr, char *key, size_t key_length, uint32_t *flags, memcached_return *error) {
1873
1893
  VALUE ret;
1874
1894
  size_t value_length;
@@ -8691,6 +8711,34 @@ fail:
8691
8711
  }
8692
8712
 
8693
8713
 
8714
+ SWIGINTERN VALUE
8715
+ _wrap_ns(int argc, VALUE *argv, VALUE self) {
8716
+ char *arg1 = (char *) 0 ;
8717
+ size_t arg2 ;
8718
+ char *arg3 = (char *) 0 ;
8719
+ size_t arg4 ;
8720
+ VALUE result;
8721
+ VALUE vresult = Qnil;
8722
+
8723
+ if ((argc < 2) || (argc > 2)) {
8724
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)",argc); SWIG_fail;
8725
+ }
8726
+ {
8727
+ arg1 = STR2CSTR(argv[0]);
8728
+ arg2 = (size_t) RSTRING(argv[0])->len;
8729
+ }
8730
+ {
8731
+ arg3 = STR2CSTR(argv[1]);
8732
+ arg4 = (size_t) RSTRING(argv[1])->len;
8733
+ }
8734
+ result = (VALUE)ns(arg1,arg2,arg3,arg4);
8735
+ vresult = result;
8736
+ return vresult;
8737
+ fail:
8738
+ return Qnil;
8739
+ }
8740
+
8741
+
8694
8742
  SWIGINTERN VALUE
8695
8743
  _wrap_memcached_get_rvalue(int argc, VALUE *argv, VALUE self) {
8696
8744
  memcached_st *arg1 = (memcached_st *) 0 ;
@@ -9595,6 +9643,7 @@ SWIGEXPORT void Init_rlibmemcached(void) {
9595
9643
  rb_define_module_function(mRlibmemcached, "memcached_result_create", _wrap_memcached_result_create, -1);
9596
9644
  rb_define_module_function(mRlibmemcached, "memcached_result_value", _wrap_memcached_result_value, -1);
9597
9645
  rb_define_module_function(mRlibmemcached, "memcached_result_length", _wrap_memcached_result_length, -1);
9646
+ rb_define_module_function(mRlibmemcached, "ns", _wrap_ns, -1);
9598
9647
  rb_define_module_function(mRlibmemcached, "memcached_get_rvalue", _wrap_memcached_get_rvalue, -1);
9599
9648
  rb_define_module_function(mRlibmemcached, "memcached_fetch_rvalue", _wrap_memcached_fetch_rvalue, -1);
9600
9649
  rb_define_module_function(mRlibmemcached, "memcached_stat_get_rvalue", _wrap_memcached_stat_get_rvalue, -1);
@@ -19,6 +19,8 @@ class Memcached
19
19
  #:stopdoc:
20
20
  IGNORED = 0
21
21
 
22
+ Lib = Rlibmemcached
23
+
22
24
  NOTFOUND_INSTANCE = NotFound.new
23
25
  #:startdoc:
24
26
 
@@ -46,8 +48,8 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
46
48
  =end
47
49
 
48
50
  def initialize(servers, opts = {})
49
- @struct = Rlibmemcached::MemcachedSt.new
50
- Rlibmemcached.memcached_create(@struct)
51
+ @struct = Lib::MemcachedSt.new
52
+ Lib.memcached_create(@struct)
51
53
 
52
54
  # Servers
53
55
  Array(servers).each_with_index do |server, index|
@@ -55,7 +57,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
55
57
  raise ArgumentError, "Servers must be in the format ip:port (e.g., '127.0.0.1:11211')"
56
58
  end
57
59
  host, port = server.split(":")
58
- Rlibmemcached.memcached_server_add(@struct, host, port.to_i)
60
+ Lib.memcached_server_add(@struct, host, port.to_i)
59
61
  end
60
62
 
61
63
  # Behaviors
@@ -90,7 +92,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
90
92
  #
91
93
  def clone
92
94
  memcached = super
93
- memcached.instance_variable_set('@struct', Rlibmemcached.memcached_clone(nil, @struct))
95
+ memcached.instance_variable_set('@struct', Lib.memcached_clone(nil, @struct))
94
96
  memcached
95
97
  end
96
98
 
@@ -100,7 +102,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
100
102
  # runs much faster, but your instance will segfault if you try to call any other methods on it
101
103
  # after destroy. Defaults to <tt>true</tt>, which safely overwrites all instance methods.
102
104
  def destroy(disable_methods = true)
103
- Rlibmemcached.memcached_free(@struct)
105
+ Lib.memcached_free(@struct)
104
106
  @struct = nil
105
107
  if disable_methods
106
108
  class << self
@@ -115,8 +117,8 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
115
117
 
116
118
  # Reset the state of the libmemcached struct. Fixes out-of-sync errors with the Memcached pool.
117
119
  def reset
118
- new_struct = Rlibmemcached.memcached_clone(nil, @struct)
119
- Rlibmemcached.memcached_free(@struct)
120
+ new_struct = Lib.memcached_clone(nil, @struct)
121
+ Lib.memcached_free(@struct)
120
122
  @struct = new_struct
121
123
  end
122
124
 
@@ -132,7 +134,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
132
134
  def server_structs
133
135
  array = []
134
136
  @struct.hosts.count.times do |i|
135
- array << Rlibmemcached.memcached_select_server_at(@struct, i)
137
+ array << Lib.memcached_select_server_at(@struct, i)
136
138
  end
137
139
  array
138
140
  end
@@ -152,7 +154,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
152
154
  def set(key, value, timeout=0, marshal=true)
153
155
  value = marshal ? Marshal.dump(value) : value.to_s
154
156
  check_return_code(
155
- Rlibmemcached.memcached_set(@struct, ns(key), value, timeout, FLAGS)
157
+ Lib.memcached_set(@struct, Lib.ns(@namespace, key), value, timeout, FLAGS)
156
158
  )
157
159
  end
158
160
 
@@ -160,7 +162,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
160
162
  def add(key, value, timeout=0, marshal=true)
161
163
  value = marshal ? Marshal.dump(value) : value.to_s
162
164
  check_return_code(
163
- Rlibmemcached.memcached_add(@struct, ns(key), value, timeout, FLAGS)
165
+ Lib.memcached_add(@struct, Lib.ns(@namespace, key), value, timeout, FLAGS)
164
166
  )
165
167
  end
166
168
 
@@ -170,14 +172,14 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
170
172
  #
171
173
  # Note that the key must be initialized to an unmarshalled integer first, via <tt>set</tt>, <tt>add</tt>, or <tt>replace</tt> with <tt>marshal</tt> set to <tt>false</tt>.
172
174
  def increment(key, offset=1)
173
- ret, value = Rlibmemcached.memcached_increment(@struct, ns(key), offset)
175
+ ret, value = Lib.memcached_increment(@struct, Lib.ns(@namespace, key), offset)
174
176
  check_return_code(ret)
175
177
  value
176
178
  end
177
179
 
178
180
  # Decrement a key's value. The parameters and exception behavior are the same as <tt>increment</tt>.
179
181
  def decrement(key, offset=1)
180
- ret, value = Rlibmemcached.memcached_decrement(@struct, ns(key), offset)
182
+ ret, value = Lib.memcached_decrement(@struct, Lib.ns(@namespace, key), offset)
181
183
  check_return_code(ret)
182
184
  value
183
185
  end
@@ -191,7 +193,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
191
193
  def replace(key, value, timeout=0, marshal=true)
192
194
  value = marshal ? Marshal.dump(value) : value.to_s
193
195
  check_return_code(
194
- Rlibmemcached.memcached_replace(@struct, ns(key), value, timeout, FLAGS)
196
+ Lib.memcached_replace(@struct, Lib.ns(@namespace, key), value, timeout, FLAGS)
195
197
  )
196
198
  end
197
199
 
@@ -201,7 +203,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
201
203
  def append(key, value)
202
204
  # Requires memcached 1.2.4
203
205
  check_return_code(
204
- Rlibmemcached.memcached_append(@struct, ns(key), value.to_s, IGNORED, FLAGS)
206
+ Lib.memcached_append(@struct, Lib.ns(@namespace, key), value.to_s, IGNORED, FLAGS)
205
207
  )
206
208
  end
207
209
 
@@ -209,7 +211,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
209
211
  def prepend(key, value)
210
212
  # Requires memcached 1.2.4
211
213
  check_return_code(
212
- Rlibmemcached.memcached_prepend(@struct, ns(key), value.to_s, IGNORED, FLAGS)
214
+ Lib.memcached_prepend(@struct, Lib.ns(@namespace, key), value.to_s, IGNORED, FLAGS)
213
215
  )
214
216
  end
215
217
 
@@ -231,7 +233,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
231
233
  # Deletes a key/value pair from the server. Accepts a String <tt>key</tt>. Raises <b>Memcached::NotFound</b> if the key does not exist.
232
234
  def delete(key)
233
235
  check_return_code(
234
- Rlibmemcached.memcached_delete(@struct, ns(key), IGNORED)
236
+ Lib.memcached_delete(@struct, Lib.ns(@namespace, key), IGNORED)
235
237
  )
236
238
  end
237
239
 
@@ -250,14 +252,14 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
250
252
  def get(keys, marshal=true)
251
253
  if keys.is_a? Array
252
254
  # Multi get
253
- keys.map! { |key| ns(key) }
255
+ keys.map! { |key| Lib.ns(@namespace, key) }
254
256
  hash = {}
255
257
 
256
- Rlibmemcached.memcached_mget(@struct, keys);
258
+ Lib.memcached_mget(@struct, keys);
257
259
 
258
260
  keys.size.times do
259
- value, key, flags, ret = Rlibmemcached.memcached_fetch_rvalue(@struct)
260
- break if ret == Rlibmemcached::MEMCACHED_END
261
+ value, key, flags, ret = Lib.memcached_fetch_rvalue(@struct)
262
+ break if ret == Lib::MEMCACHED_END
261
263
  check_return_code(ret)
262
264
  value = Marshal.load(value) if marshal
263
265
  # Assign the value, removing the namespace, if present
@@ -266,7 +268,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
266
268
  hash
267
269
  else
268
270
  # Single get
269
- value, flags, ret = Rlibmemcached.memcached_get_rvalue(@struct, ns(keys))
271
+ value, flags, ret = Lib.memcached_get_rvalue(@struct, Lib.ns(@namespace, keys))
270
272
  check_return_code(ret)
271
273
  value = Marshal.load(value) if marshal
272
274
  value
@@ -279,18 +281,18 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
279
281
  def stats
280
282
  stats = Hash.new([])
281
283
 
282
- stat_struct, ret = Rlibmemcached.memcached_stat(@struct, "")
284
+ stat_struct, ret = Lib.memcached_stat(@struct, "")
283
285
  check_return_code(ret)
284
286
 
285
- keys, ret = Rlibmemcached.memcached_stat_get_keys(@struct, stat_struct)
287
+ keys, ret = Lib.memcached_stat_get_keys(@struct, stat_struct)
286
288
  check_return_code(ret)
287
289
 
288
290
  keys.each do |key|
289
291
  server_structs.size.times do |index|
290
292
 
291
- value, ret = Rlibmemcached.memcached_stat_get_rvalue(
293
+ value, ret = Lib.memcached_stat_get_rvalue(
292
294
  @struct,
293
- Rlibmemcached.memcached_select_stat_at(@struct, stat_struct, index),
295
+ Lib.memcached_select_stat_at(@struct, stat_struct, index),
294
296
  key)
295
297
  check_return_code(ret)
296
298
 
@@ -304,19 +306,13 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
304
306
  end
305
307
  end
306
308
 
307
- Rlibmemcached.memcached_stat_free(@struct, stat_struct)
309
+ Lib.memcached_stat_free(@struct, stat_struct)
308
310
  stats
309
311
  end
310
312
 
311
313
  ### Operations helpers
312
314
 
313
315
  private
314
-
315
- # Return a namespaced key for this Memcached instance. Accepts a String <tt>key</tt> value.
316
- def ns(key) #:doc:
317
- # raise ClientError, "Invalid key" if key =~ /\s/ # XXX Slow
318
- "#{@namespace}#{key}"
319
- end
320
316
 
321
317
  # Checks the return code from Rlibmemcached against the exception list. Raises the corresponding exception if the return code is not Memcached::Success or Memcached::ActionQueued. Accepts an integer return code.
322
318
  def check_return_code(ret) #:doc:
@@ -4,10 +4,6 @@ class Memcached
4
4
  alias :get_multi :get #:nodoc:
5
5
 
6
6
  # A legacy compatibility wrapper for the Memcached class. It has basic compatibility with the <b>memcache-client</b> API.
7
- #
8
- # There is currently a libmemcached stability issue with long-lived instances, so you will want to call Memcached#reset before each
9
- # request (for example, in an ActionController filter).
10
- #
11
7
  class Rails < ::Memcached
12
8
 
13
9
  DEFAULTS = {}
@@ -1,20 +1,20 @@
1
1
 
2
- # Gem::Specification for Memcached-0.7.1
2
+ # Gem::Specification for Memcached-0.7.2
3
3
  # Originally generated by Echoe
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = %q{memcached}
7
- s.version = "0.7.1"
7
+ s.version = "0.7.2"
8
8
 
9
9
  s.specification_version = 2 if s.respond_to? :specification_version=
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.authors = ["Evan Weaver"]
13
- s.date = %q{2008-02-05}
13
+ s.date = %q{2008-02-10}
14
14
  s.description = %q{An interface to the libmemcached C client.}
15
15
  s.email = %q{}
16
16
  s.extensions = ["ext/extconf.rb"]
17
- s.files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "ext/extconf.rb", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "Manifest", "README", "test/profile/benchmark.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb", "TODO", "memcached.gemspec"]
17
+ s.files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "ext/extconf.rb", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "Manifest", "README", "test/profile/benchmark.rb", "test/profile/key.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb", "TODO", "memcached.gemspec"]
18
18
  s.has_rdoc = true
19
19
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/memcached/}
20
20
  s.require_paths = ["lib", "ext"]
@@ -0,0 +1,41 @@
1
+
2
+ HERE = File.dirname(__FILE__)
3
+ $LOAD_PATH << "#{HERE}/../../lib/"
4
+
5
+ require 'rubygems'
6
+ require 'memcached'
7
+ require 'ruby-prof'
8
+ require 'benchmark'
9
+
10
+ KEYS = ["ch\303\242teau"*10, "long"*100, "spaces space spaces", "null \000"]
11
+
12
+ @namespace = "benchmark_namespace"
13
+ @cache = Memcached.new(
14
+ ['127.0.0.1:43042', '127.0.0.1:43043'],
15
+ :namespace => @namespace
16
+ )
17
+
18
+ def dispatch(n, k)
19
+ Rlibmemcached.ns(@namespace, key)
20
+ end
21
+
22
+ #result = RubyProf.profile do
23
+ Benchmark.bm(15) do |x|
24
+ x.report("direct") do
25
+ KEYS.each do |key|
26
+ 10000.times do
27
+ Rlibmemcached.ns(@namespace, key)
28
+ end
29
+ end
30
+ end
31
+ x.report("dispatch") do
32
+ KEYS.each do |key|
33
+ 10000.times do
34
+ Rlibmemcached.ns(@namespace, key)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ #printer = RubyProf::GraphPrinter.new(result)
41
+ #printer.print(STDOUT, 0)
@@ -6,6 +6,11 @@ require 'rubygems'
6
6
  require 'memcached'
7
7
  require 'ruby-prof'
8
8
 
9
+ @cache = Memcached.new(
10
+ '127.0.0.1:43042', '127.0.0.1:43043'],
11
+ :namespace => "benchmark_namespace"
12
+ )
13
+
9
14
  result = RubyProf.profile do
10
15
  load "#{HERE}/valgrind.rb"
11
16
  end
@@ -22,6 +22,12 @@ class MemcachedTest < Test::Unit::TestCase
22
22
  @marshalled_value = Marshal.dump(@value)
23
23
  end
24
24
 
25
+ def teardown
26
+ ObjectSpace.each_object(Memcached) do |cache|
27
+ cache.destroy rescue Memcached::ClientError
28
+ end
29
+ end
30
+
25
31
  # Initialize
26
32
 
27
33
  def test_initialize
@@ -49,9 +55,9 @@ class MemcachedTest < Test::Unit::TestCase
49
55
 
50
56
  def test_initialize_with_missing_server
51
57
  # XXX Triggers abort trap with libmemcached --enable-debug.
52
- @cache = Memcached.new "127.0.0.1:43044"
58
+ cache = Memcached.new "127.0.0.1:43044"
53
59
  assert_raises Memcached::SystemError do
54
- @cache.get key
60
+ cache.get key
55
61
  end
56
62
  end
57
63
 
@@ -121,19 +127,6 @@ class MemcachedTest < Test::Unit::TestCase
121
127
  assert result.size > non_wrapped_result.size
122
128
  end
123
129
 
124
- def test_get_invalid_key
125
- assert_raise(Memcached::ClientError) { @cache.get(key * 100) }
126
- # XXX Trying to get Krow to change this to ProtocolError
127
- assert_raise(Memcached::NotFound) { @cache.get "I'm so bad" }
128
- end
129
-
130
- def test_get_multi_invalid_key
131
- assert_raise(Memcached::ClientError) { @cache.get([key * 100]) }
132
- # XXX Trying to get Krow to change this to ProtocolError
133
- assert_equal({},
134
- @cache.get(["I'm so bad"]))
135
- end
136
-
137
130
  def test_get_multi
138
131
  @cache.set "#{key}_1", 1
139
132
  @cache.set "#{key}_2", 2
@@ -185,13 +178,7 @@ class MemcachedTest < Test::Unit::TestCase
185
178
  @cache.set(key, @value)
186
179
  end
187
180
  end
188
-
189
- def test_set_invalid_key
190
- assert_raise(Memcached::ProtocolError) do
191
- @cache.set "I'm so bad", @value
192
- end
193
- end
194
-
181
+
195
182
  def test_set_expiry
196
183
  @cache.set key, @value, 1
197
184
  assert_nothing_raised do
@@ -202,12 +189,6 @@ class MemcachedTest < Test::Unit::TestCase
202
189
  @cache.get key
203
190
  end
204
191
  end
205
-
206
- def test_set_object_too_large
207
- assert_raise(Memcached::ServerError) do
208
- @cache.set key, "I'm big" * 1000000
209
- end
210
- end
211
192
 
212
193
  # Delete
213
194
 
@@ -362,6 +343,85 @@ class MemcachedTest < Test::Unit::TestCase
362
343
  end
363
344
  end
364
345
 
346
+ # Namespace and key validation
347
+
348
+ def test_ns
349
+ assert_equal "#{@namespace}i_have_a_space",
350
+ Rlibmemcached.ns(@namespace, "i have a space")
351
+
352
+ # STR2CSTR doesn't handle strings with nulls very well, so this is what happens
353
+ assert_equal "#{@namespace}with_____",
354
+ Rlibmemcached.ns(@namespace, "with\000null")
355
+
356
+ assert_equal "#{@namespace}ch__teau",
357
+ Rlibmemcached.ns(@namespace, "ch\303\242teau")
358
+
359
+ assert_equal "#{@namespace}#{'x'*251}"[0..249],
360
+ Rlibmemcached.ns(@namespace, 'x'*251)
361
+ end
362
+
363
+ # Error states
364
+
365
+ def test_key_with_spaces
366
+ value = "value"
367
+ key = "i have a space"
368
+ assert_nothing_raised do
369
+ @cache.set key, value
370
+ end
371
+ assert_nothing_raised do
372
+ assert_equal(value, @cache.get(key))
373
+ end
374
+ # Spaces were stripped
375
+ assert_not_equal(key,
376
+ @cache.get([key]).keys.first)
377
+ end
378
+
379
+ def test_key_with_null
380
+ value = "value"
381
+ key = "with\000null"
382
+ assert_nothing_raised do
383
+ @cache.set key, value
384
+ end
385
+ assert_nothing_raised do
386
+ assert_equal(value, @cache.get(key))
387
+ end
388
+ # Multiget returns
389
+ response = @cache.get([key])
390
+ assert_equal 1, response.size
391
+ # Nulls were stripped
392
+ assert_not_equal(key, response.keys.first)
393
+ end
394
+
395
+ def test_key_with_valid_control_characters
396
+ value = "value"
397
+ key = "ch\303\242teau"
398
+ @cache.set key, value
399
+ assert_equal(value,
400
+ @cache.get(key))
401
+ assert_not_equal(key,
402
+ @cache.get([key]).keys.first)
403
+ end
404
+
405
+ def test_key_too_long
406
+ key = "x"*251
407
+ assert_nothing_raised do
408
+ @cache.set key, @value
409
+ end
410
+ assert_nothing_raised do
411
+ assert_equal(@value,
412
+ @cache.get(key))
413
+ end
414
+ # Key was truncated
415
+ assert_not_equal(key,
416
+ @cache.get([key]).keys.first)
417
+ end
418
+
419
+ def test_set_object_too_large
420
+ assert_raise(Memcached::ServerError) do
421
+ @cache.set key, "I'm big" * 1000000
422
+ end
423
+ end
424
+
365
425
  # Stats
366
426
 
367
427
  def test_stats
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memcached
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Weaver
@@ -30,7 +30,7 @@ cert_chain:
30
30
  yZ0=
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2008-02-05 00:00:00 -05:00
33
+ date: 2008-02-10 00:00:00 -05:00
34
34
  default_executable:
35
35
  dependencies: []
36
36
 
@@ -59,6 +59,7 @@ files:
59
59
  - Manifest
60
60
  - README
61
61
  - test/profile/benchmark.rb
62
+ - test/profile/key.rb
62
63
  - test/profile/profile.rb
63
64
  - test/profile/valgrind.rb
64
65
  - test/setup.rb
metadata.gz.sig CHANGED
@@ -1 +1,2 @@
1
- RU�^ h�����V�4���t��n'�>��V�� �!������ÔR<>C��\
1
+ w��/o�+i�&� A=\�� ��WA�:]�&��_@� ��;
2
+ �.\�6���<3�'��@�sZ����c%)�y�c��;�0���ێ�<F��嗯����i�%���w�1��Zl���cNk�:.� �� �nWO '�n[�$�1� ���G��{\.