memcached 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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��{\.