jruby-memcached 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in jruby-memcached.gemspec
4
4
  gemspec
5
+
6
+ gem "rake"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jruby-memcached (0.4.1)
4
+ jruby-memcached (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -10,6 +10,7 @@ GEM
10
10
  metaclass (0.0.1)
11
11
  mocha (0.12.1)
12
12
  metaclass (~> 0.0.1)
13
+ rake (0.9.2.2)
13
14
  rspec (2.11.0)
14
15
  rspec-core (~> 2.11.0)
15
16
  rspec-expectations (~> 2.11.0)
@@ -25,4 +26,5 @@ PLATFORMS
25
26
  DEPENDENCIES
26
27
  jruby-memcached!
27
28
  mocha
29
+ rake
28
30
  rspec
data/Rakefile CHANGED
@@ -1,2 +1,16 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+
4
+ require "rake"
5
+ require "rspec"
6
+ require "rspec/core/rake_task"
7
+
8
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
9
+ require "memcached/version"
10
+
11
+ RSpec::Core::RakeTask.new(:spec) do |spec|
12
+ spec.pattern = "spec/**/*_spec.rb"
13
+ end
14
+
15
+ task :default => :spec
16
+ task :test => :spec
data/benchmark.rb CHANGED
@@ -52,10 +52,8 @@ dalli = Dalli::Client.new(['localhost:11211'])
52
52
  }
53
53
  }
54
54
 
55
- if JRUBY
56
- memcached.shutdown
57
- spymemcached.shutdown
58
- end
55
+ memcached.quit
56
+ spymemcached.shutdown if JRUBY
59
57
  dalli.close
60
58
 
61
59
  # I run benchmark for each client 3 times, but only list the last result for each.
@@ -1,3 +1,3 @@
1
1
  class Memcached
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
data/pom.xml CHANGED
@@ -35,7 +35,7 @@
35
35
  <dependency>
36
36
  <groupId>spy</groupId>
37
37
  <artifactId>spymemcached</artifactId>
38
- <version>2.8.1</version>
38
+ <version>2.8.3</version>
39
39
  </dependency>
40
40
  </dependencies>
41
41
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Memcached do
4
4
  context "localhost" do
5
5
  before(:all) { @memcached = Memcached.new(["127.0.0.1:11211"]) }
6
- after(:all) { @memcached.shutdown }
6
+ after(:all) { @memcached.quit }
7
7
 
8
8
  it "should get all servers" do
9
9
  @memcached.set "foo", "bar"
@@ -124,14 +124,51 @@ describe Memcached do
124
124
  @memcached.delete "key" rescue nil
125
125
  lambda { @memcached.delete "key" }.should raise_error(Memcached::NotFound)
126
126
  end
127
+ end
128
+
129
+ context "increment" do
130
+ it "should increment to default value" do
131
+ @memcached.delete "intkey" rescue nil
132
+ @memcached.increment "intkey"
133
+ @memcached.get("intkey").should == 1
134
+ end
135
+
136
+ it "should increment by 1" do
137
+ @memcached.delete "intkey" rescue nil
138
+ @memcached.increment "intkey"
139
+ @memcached.increment "intkey"
140
+ @memcached.get("intkey").should == 2
141
+ end
127
142
 
128
- #context "incr/decr" do
129
- #it "should incr key" do
130
- #@memcached.incr "intkey"
131
- #@memcached.incr "intkey"
132
- #@memcached.get("intkey").should == 1
133
- #end
134
- #end
143
+ it "should increment by 10" do
144
+ @memcached.delete "intkey" rescue nil
145
+ @memcached.increment "intkey"
146
+ @memcached.increment "intkey", 10
147
+ @memcached.get("intkey").should == 11
148
+ end
149
+ end
150
+
151
+ context "decrement" do
152
+ it "should decrement to default value" do
153
+ @memcached.delete "intkey" rescue nil
154
+ @memcached.decrement "intkey"
155
+ @memcached.get("intkey").should == 0
156
+ end
157
+
158
+ it "should decrement by 1" do
159
+ @memcached.delete "intkey" rescue nil
160
+ 2.times { @memcached.increment "intkey" }
161
+ @memcached.decrement "intkey"
162
+ @memcached.get("intkey").should == 1
163
+ end
164
+
165
+ it "should decrement by 10" do
166
+ @memcached.delete "intkey" rescue nil
167
+ @memcached.increment "intkey"
168
+ @memcached.increment "intkey", 20
169
+ @memcached.decrement "intkey", 10
170
+ @memcached.get("intkey").should == 11
171
+ end
135
172
  end
136
173
 
137
174
  context "flush" do
@@ -163,12 +200,6 @@ describe Memcached do
163
200
  @memcached.get("jrubykey").should == "value"
164
201
  end
165
202
 
166
- #it "should incr/decr with prefix_key" do
167
- #@prefix_memcached.incr "intkey"
168
- #@prefix_memcached.decr "intkey"
169
- #@memcached.get("jrubyintkey").should == 0
170
- #end
171
-
172
203
  it "should add/replace with prefix_key" do
173
204
  @prefix_memcached.add "newkey", "value"
174
205
  @prefix_memcached.replace "newkey", "new_value"
@@ -186,6 +217,57 @@ describe Memcached do
186
217
  @prefix_memcached.set "key2", "value2"
187
218
  @prefix_memcached.get(["key1", "key2"]).should == {"key1" => "value1", "key2" => "value2"}
188
219
  end
220
+
221
+ it "should increment/decrement with prefix_key" do
222
+ @prefix_memcached.delete "intkey" rescue nil
223
+ @prefix_memcached.increment "intkey"
224
+ @prefix_memcached.increment "intkey", 10
225
+ @prefix_memcached.decrement "intkey", 5
226
+ @memcached.get("jrubyintkey").should == 6
227
+ end
228
+ end
229
+ end
230
+
231
+ context "timeout" do
232
+ before(:all) do
233
+ @memcached = Memcached.new("127.0.0.1:11211")
234
+ @timeout_memcached = Memcached.new("127.0.0.1:11211", :timeout => 1, :exception_retry_limit => 0)
235
+ end
236
+ after(:all) do
237
+ @timeout_memcached.quit
238
+ @memcached.quit
239
+ end
240
+
241
+ it "should set timeout" do
242
+ lambda { @timeout_memcached.set "key", "new_value" }.should raise_error(Memcached::ATimeoutOccurred)
243
+ end
244
+
245
+ it "should add timeout" do
246
+ @memcached.delete "key" rescue nil
247
+ lambda { @timeout_memcached.add "key", "new_value" }.should raise_error(Memcached::ATimeoutOccurred)
248
+ end
249
+
250
+ it "should replace timeout" do
251
+ @memcached.set "key", "value"
252
+ lambda { @timeout_memcached.replace "key", "new_value" }.should raise_error(Memcached::ATimeoutOccurred)
253
+ end
254
+
255
+ it "should delete timeout" do
256
+ @memcached.set "key", "value"
257
+ lambda { @timeout_memcached.delete "key" }.should raise_error(Memcached::ATimeoutOccurred)
258
+ end
259
+
260
+ it "should get timeout" do
261
+ @memcached.set "key", "value"
262
+ lambda { @timeout_memcached.get "key" }.should raise_error(Memcached::ATimeoutOccurred)
263
+ end
264
+
265
+ it "should increment timeout" do
266
+ lambda { @timeout_memcached.increment "intkey" }.should raise_error(Memcached::ATimeoutOccurred)
267
+ end
268
+
269
+ it "should decrement timeout" do
270
+ lambda { @timeout_memcached.decrement "intkey" }.should raise_error(Memcached::ATimeoutOccurred)
189
271
  end
190
272
  end
191
273
  end
@@ -1,6 +1,7 @@
1
1
  package com.openfeint.memcached;
2
2
 
3
3
  import com.openfeint.memcached.error.Error;
4
+ import com.openfeint.memcached.error.NotFound;
4
5
  import com.openfeint.memcached.transcoder.MarshalTranscoder;
5
6
  import com.openfeint.memcached.transcoder.MarshalZlibTranscoder;
6
7
  import net.spy.memcached.AddrUtil;
@@ -9,6 +10,7 @@ import net.spy.memcached.ConnectionFactoryBuilder.Locator;
9
10
  import net.spy.memcached.ConnectionFactoryBuilder.Protocol;
10
11
  import net.spy.memcached.DefaultHashAlgorithm;
11
12
  import net.spy.memcached.MemcachedClient;
13
+ import net.spy.memcached.OperationTimeoutException;
12
14
  import net.spy.memcached.transcoders.Transcoder;
13
15
  import org.jruby.Ruby;
14
16
  import org.jruby.RubyArray;
@@ -19,6 +21,7 @@ import org.jruby.RubyObject;
19
21
  import org.jruby.RubyString;
20
22
  import org.jruby.anno.JRubyClass;
21
23
  import org.jruby.anno.JRubyMethod;
24
+ import org.jruby.exceptions.RaiseException;
22
25
  import org.jruby.runtime.ThreadContext;
23
26
  import org.jruby.runtime.builtin.IRubyObject;
24
27
 
@@ -34,16 +37,22 @@ import java.util.concurrent.ExecutionException;
34
37
  public class Memcached extends RubyObject {
35
38
  private MemcachedClient client;
36
39
 
37
- private Transcoder<IRubyObject> transcoder;
40
+ private Transcoder transcoder;
38
41
 
39
42
  private int ttl;
40
43
 
44
+ private int timeout;
45
+
46
+ private int exceptionRetryLimit;
47
+
41
48
  private String prefixKey;
42
49
 
43
50
  public Memcached(final Ruby ruby, RubyClass rubyClass) {
44
51
  super(ruby, rubyClass);
45
52
 
46
53
  ttl = 604800;
54
+ timeout = -1;
55
+ exceptionRetryLimit = 5;
47
56
  prefixKey = "";
48
57
  }
49
58
 
@@ -89,17 +98,41 @@ public class Memcached extends RubyObject {
89
98
  Ruby ruby = context.getRuntime();
90
99
  String key = getFullKey(args[0].toString());
91
100
  IRubyObject value = args[1];
92
- int timeout = getTimeout(args);
93
- try {
94
- boolean result = client.add(key, timeout, value, transcoder).get();
95
- if (result == false) {
96
- throw Error.newNotStored(ruby, "not stored");
101
+ int expiry = getExpiry(args);
102
+ int retry = 0;
103
+ while (true) {
104
+ try {
105
+ boolean result = (Boolean) client.add(key, expiry, value, transcoder).get();
106
+ if (result == false) {
107
+ throw Error.newNotStored(ruby, "not stored");
108
+ }
109
+ return context.nil;
110
+ } catch (RaiseException e) {
111
+ throw e;
112
+ } catch (ExecutionException e) {
113
+ if ("net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
114
+ if (retry == exceptionRetryLimit) {
115
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
116
+ }
117
+ retry++;
118
+ continue;
119
+ } else {
120
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
121
+ }
122
+ } catch (RuntimeException e) {
123
+ if (e.getCause() != null &&
124
+ "net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
125
+ if (retry == exceptionRetryLimit) {
126
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
127
+ }
128
+ retry++;
129
+ continue;
130
+ } else {
131
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
132
+ }
133
+ } catch (InterruptedException e) {
134
+ throw ruby.newThreadError(e.getLocalizedMessage());
97
135
  }
98
- return context.nil;
99
- } catch (ExecutionException ee) {
100
- throw ruby.newRuntimeError(ee.getLocalizedMessage());
101
- } catch (InterruptedException ie) {
102
- throw ruby.newThreadError(ie.getLocalizedMessage());
103
136
  }
104
137
  }
105
138
 
@@ -108,17 +141,41 @@ public class Memcached extends RubyObject {
108
141
  Ruby ruby = context.getRuntime();
109
142
  String key = getFullKey(args[0].toString());
110
143
  IRubyObject value = args[1];
111
- int timeout = getTimeout(args);
112
- try {
113
- boolean result = client.replace(key, timeout, value, transcoder).get();
114
- if (result == false) {
115
- throw Error.newNotStored(ruby, "not stored");
144
+ int expiry = getExpiry(args);
145
+ int retry = 0;
146
+ while (true) {
147
+ try {
148
+ boolean result = (Boolean) client.replace(key, expiry, value, transcoder).get();
149
+ if (result == false) {
150
+ throw Error.newNotStored(ruby, "not stored");
151
+ }
152
+ return context.nil;
153
+ } catch (RaiseException e) {
154
+ throw e;
155
+ } catch (ExecutionException e) {
156
+ if ("net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
157
+ if (retry == exceptionRetryLimit) {
158
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
159
+ }
160
+ retry++;
161
+ continue;
162
+ } else {
163
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
164
+ }
165
+ } catch (RuntimeException e) {
166
+ if (e.getCause() != null &&
167
+ "net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
168
+ if (retry == exceptionRetryLimit) {
169
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
170
+ }
171
+ retry++;
172
+ continue;
173
+ } else {
174
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
175
+ }
176
+ } catch (InterruptedException e) {
177
+ throw ruby.newThreadError(e.getLocalizedMessage());
116
178
  }
117
- return context.nil;
118
- } catch (ExecutionException ee) {
119
- throw ruby.newRuntimeError(ee.getLocalizedMessage());
120
- } catch (InterruptedException ie) {
121
- throw ruby.newThreadError(ie.getLocalizedMessage());
122
179
  }
123
180
  }
124
181
 
@@ -127,17 +184,41 @@ public class Memcached extends RubyObject {
127
184
  Ruby ruby = context.getRuntime();
128
185
  String key = getFullKey(args[0].toString());
129
186
  IRubyObject value = args[1];
130
- int timeout = getTimeout(args);
131
- try {
132
- boolean result = client.set(key, timeout, value, transcoder).get();
133
- if (result == false) {
134
- throw Error.newNotStored(ruby, "not stored");
187
+ int expiry = getExpiry(args);
188
+ int retry = 0;
189
+ while (true) {
190
+ try {
191
+ boolean result = (Boolean) client.set(key, expiry, value, transcoder).get();
192
+ if (result == false) {
193
+ throw Error.newNotStored(ruby, "not stored");
194
+ }
195
+ return context.nil;
196
+ } catch (RaiseException e) {
197
+ throw e;
198
+ } catch (ExecutionException e) {
199
+ if ("net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
200
+ if (retry == exceptionRetryLimit) {
201
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
202
+ }
203
+ retry++;
204
+ continue;
205
+ } else {
206
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
207
+ }
208
+ } catch (RuntimeException e) {
209
+ if (e.getCause() != null &&
210
+ "net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
211
+ if (retry == exceptionRetryLimit) {
212
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
213
+ }
214
+ retry++;
215
+ continue;
216
+ } else {
217
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
218
+ }
219
+ } catch (InterruptedException e) {
220
+ throw ruby.newThreadError(e.getLocalizedMessage());
135
221
  }
136
- return context.nil;
137
- } catch (ExecutionException ee) {
138
- throw ruby.newRuntimeError(ee.getLocalizedMessage());
139
- } catch (InterruptedException ie) {
140
- throw ruby.newThreadError(ie.getLocalizedMessage());
141
222
  }
142
223
  }
143
224
 
@@ -145,59 +226,122 @@ public class Memcached extends RubyObject {
145
226
  public IRubyObject get(ThreadContext context, IRubyObject[] args) {
146
227
  Ruby ruby = context.getRuntime();
147
228
  IRubyObject keys = args[0];
148
- if (keys instanceof RubyString) {
149
- IRubyObject value = client.get(getFullKey(keys.toString()), transcoder);
150
- if (value == null) {
151
- throw Error.newNotFound(ruby, "not found");
152
- }
153
- return value;
154
- } else if (keys instanceof RubyArray) {
155
- RubyHash results = RubyHash.newHash(ruby);
156
-
157
- Map<String, IRubyObject> bulkResults = client.getBulk(getFullKeys(keys.convertToArray()), transcoder);
158
- for (String key : (List<String>) keys.convertToArray()) {
159
- if (bulkResults.containsKey(getFullKey(key))) {
160
- results.put(key, bulkResults.get(getFullKey(key)));
229
+ int retry = 0;
230
+ while (true) {
231
+ try {
232
+ if (keys instanceof RubyString) {
233
+ Object ret = client.get(getFullKey(keys.toString()), transcoder);
234
+ if (ret == null) {
235
+ throw Error.newNotFound(ruby, "not found");
236
+ }
237
+ IRubyObject value;
238
+ if (ret instanceof IRubyObject) {
239
+ value = (IRubyObject) ret;
240
+ } else {
241
+ value = ruby.newFixnum((Long) ret);
242
+ }
243
+ return value;
244
+ } else if (keys instanceof RubyArray) {
245
+ RubyHash results = RubyHash.newHash(ruby);
246
+
247
+ Map<String, IRubyObject> bulkResults = client.getBulk(getFullKeys(keys.convertToArray()), transcoder);
248
+ for (String key : (List<String>) keys.convertToArray()) {
249
+ if (bulkResults.containsKey(getFullKey(key))) {
250
+ results.put(key, (IRubyObject) bulkResults.get(getFullKey(key)));
251
+ }
252
+ }
253
+ return results;
161
254
  }
255
+ } catch (RaiseException e) {
256
+ throw e;
257
+ } catch (OperationTimeoutException e) {
258
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
259
+ } catch (RuntimeException e) {
260
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
162
261
  }
163
- return results;
262
+ return context.nil;
164
263
  }
165
- return context.nil;
166
264
  }
167
265
 
168
- @JRubyMethod(name = "incr", required = 1, optional = 2)
266
+ @JRubyMethod(name = { "increment", "incr" }, required = 1, optional = 2)
169
267
  public IRubyObject incr(ThreadContext context, IRubyObject[] args) {
170
268
  Ruby ruby = context.getRuntime();
171
269
  String key = getFullKey(args[0].toString());
172
270
  int by = getIncrDecrBy(args);
173
- int timeout = getTimeout(args);
174
- long result = client.incr(key, by, 1, timeout);
175
- return ruby.newFixnum(result);
271
+ int expiry = getExpiry(args);
272
+ int retry = 0;
273
+ while (true) {
274
+ try {
275
+ long result = client.incr(key, by, 1, expiry);
276
+ return ruby.newFixnum(result);
277
+ } catch (OperationTimeoutException e) {
278
+ if (retry == exceptionRetryLimit) {
279
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
280
+ }
281
+ retry++;
282
+ continue;
283
+ }
284
+ }
176
285
  }
177
286
 
178
- @JRubyMethod(name = "decr", required = 1, optional = 2)
287
+ @JRubyMethod(name = { "decrement", "decr" }, required = 1, optional = 2)
179
288
  public IRubyObject decr(ThreadContext context, IRubyObject[] args) {
180
289
  Ruby ruby = context.getRuntime();
181
290
  String key = getFullKey(args[0].toString());
182
291
  int by = getIncrDecrBy(args);
183
- int timeout = getTimeout(args);
184
- long result = client.decr(key, by, 0, timeout);
185
- return ruby.newFixnum(result);
292
+ int expiry = getExpiry(args);
293
+ int retry = 0;
294
+ while (true) {
295
+ try {
296
+ long result = client.decr(key, by, 0, expiry);
297
+ return ruby.newFixnum(result);
298
+ } catch (OperationTimeoutException e) {
299
+ if (retry == exceptionRetryLimit) {
300
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
301
+ }
302
+ retry++;
303
+ continue;
304
+ }
305
+ }
186
306
  }
187
307
 
188
- @JRubyMethod
308
+ @JRubyMethod(name = "delete")
189
309
  public IRubyObject delete(ThreadContext context, IRubyObject key) {
190
310
  Ruby ruby = context.getRuntime();
191
- try {
192
- boolean result = client.delete(getFullKey(key.toString())).get();
193
- if (result == false) {
194
- throw Error.newNotFound(ruby, "not found");
311
+ int retry = 0;
312
+ while (true) {
313
+ try {
314
+ boolean result = client.delete(getFullKey(key.toString())).get();
315
+ if (result == false) {
316
+ throw Error.newNotFound(ruby, "not found");
317
+ }
318
+ return context.nil;
319
+ } catch (RaiseException e) {
320
+ throw e;
321
+ } catch (ExecutionException e) {
322
+ if ("net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
323
+ if (retry == exceptionRetryLimit) {
324
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
325
+ }
326
+ retry++;
327
+ continue;
328
+ } else {
329
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
330
+ }
331
+ } catch (RuntimeException e) {
332
+ if (e.getCause() != null &&
333
+ "net.spy.memcached.internal.CheckedOperationTimeoutException".equals(e.getCause().getClass().getName())) {
334
+ if (retry == exceptionRetryLimit) {
335
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
336
+ }
337
+ retry++;
338
+ continue;
339
+ } else {
340
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
341
+ }
342
+ } catch (InterruptedException e) {
343
+ throw ruby.newThreadError(e.getLocalizedMessage());
195
344
  }
196
- return context.nil;
197
- } catch (ExecutionException ee) {
198
- throw ruby.newRuntimeError(ee.getLocalizedMessage());
199
- } catch (InterruptedException ie) {
200
- throw ruby.newThreadError(ie.getLocalizedMessage());
201
345
  }
202
346
  }
203
347
 
@@ -207,10 +351,12 @@ public class Memcached extends RubyObject {
207
351
  try {
208
352
  client.flush().get();
209
353
  return context.nil;
210
- } catch (ExecutionException ee) {
211
- throw ruby.newRuntimeError(ee.getLocalizedMessage());
212
- } catch (InterruptedException ie) {
213
- throw ruby.newThreadError(ie.getLocalizedMessage());
354
+ } catch (OperationTimeoutException e) {
355
+ throw Error.newATimeoutOccurred(ruby, e.getLocalizedMessage());
356
+ } catch (ExecutionException e) {
357
+ throw ruby.newRuntimeError(e.getLocalizedMessage());
358
+ } catch (InterruptedException e) {
359
+ throw ruby.newThreadError(e.getLocalizedMessage());
214
360
  }
215
361
  }
216
362
 
@@ -248,6 +394,7 @@ public class Memcached extends RubyObject {
248
394
  String distributionValue = "ketama";
249
395
  String hashValue = "fnv1_32";
250
396
  RubyBoolean binaryValue = ruby.getFalse();
397
+ RubyBoolean shouldOptimize = ruby.getFalse();
251
398
  String transcoderValue = null;
252
399
  if (!options.isEmpty()) {
253
400
  RubyHash opts = options.convertToHash();
@@ -260,9 +407,18 @@ public class Memcached extends RubyObject {
260
407
  if (opts.containsKey(ruby.newSymbol("binary_protocol"))) {
261
408
  binaryValue = (RubyBoolean) opts.get(ruby.newSymbol("binary_protocol"));
262
409
  }
410
+ if (opts.containsKey(ruby.newSymbol("should_optimize"))) {
411
+ shouldOptimize = (RubyBoolean) opts.get(ruby.newSymbol("should_optimize"));
412
+ }
263
413
  if (opts.containsKey(ruby.newSymbol("default_ttl"))) {
264
414
  ttl = Integer.parseInt(opts.get(ruby.newSymbol("default_ttl")).toString());
265
415
  }
416
+ if (opts.containsKey(ruby.newSymbol("timeout"))) {
417
+ timeout = Integer.parseInt(opts.get(ruby.newSymbol("timeout")).toString());
418
+ }
419
+ if (opts.containsKey(ruby.newSymbol("exception_retry_limit"))) {
420
+ exceptionRetryLimit = Integer.parseInt(opts.get(ruby.newSymbol("exception_retry_limit")).toString());
421
+ }
266
422
  if (opts.containsKey(ruby.newSymbol("namespace"))) {
267
423
  prefixKey = opts.get(ruby.newSymbol("namespace")).toString();
268
424
  }
@@ -302,15 +458,22 @@ public class Memcached extends RubyObject {
302
458
  if (ruby.getTrue() == binaryValue) {
303
459
  builder.setProtocol(Protocol.BINARY);
304
460
  }
461
+ if (ruby.getTrue() == shouldOptimize) {
462
+ builder.setShouldOptimize(true);
463
+ }
305
464
 
465
+ if (timeout != -1) {
466
+ builder.setOpTimeout(timeout);
467
+ }
306
468
  builder.setDaemon(true);
307
- client = new MemcachedClient(builder.build(), addresses);
308
-
309
469
  if ("marshal_zlib".equals(transcoderValue)) {
310
470
  transcoder = new MarshalZlibTranscoder(ruby);
311
471
  } else {
312
472
  transcoder = new MarshalTranscoder(ruby);
313
473
  }
474
+ builder.setTranscoder(transcoder);
475
+
476
+ client = new MemcachedClient(builder.build(), addresses);
314
477
  } catch (IOException ioe) {
315
478
  throw ruby.newIOErrorFromException(ioe);
316
479
  }
@@ -318,7 +481,7 @@ public class Memcached extends RubyObject {
318
481
  return context.nil;
319
482
  }
320
483
 
321
- private int getTimeout(IRubyObject[] args) {
484
+ private int getExpiry(IRubyObject[] args) {
322
485
  if (args.length > 2) {
323
486
  return (int) args[2].convertToInteger().getLongValue();
324
487
  }
@@ -29,6 +29,7 @@ public class MemcachedService implements BasicLibraryService {
29
29
  memcached.defineClassUnder("NotFound", memcachedError, memcachedError.getAllocator());
30
30
  memcached.defineClassUnder("NotStored", memcachedError, memcachedError.getAllocator());
31
31
  memcached.defineClassUnder("NotSupport", memcachedError, memcachedError.getAllocator());
32
+ memcached.defineClassUnder("ATimeoutOccurred", memcachedError, memcachedError.getAllocator());
32
33
  return true;
33
34
  }
34
35
  }
@@ -0,0 +1,7 @@
1
+ package com.openfeint.memcached.error;
2
+
3
+ import org.jruby.anno.JRubyClass;
4
+
5
+ @JRubyClass(name="Memcached::ATimeoutOccurred", parent="Memcached::Error")
6
+ public class ATimeoutOccurred extends Error {
7
+ }
@@ -20,6 +20,10 @@ public class Error {
20
20
  return newMemcachedError(ruby, "NotSupport", message);
21
21
  }
22
22
 
23
+ public static RaiseException newATimeoutOccurred(Ruby ruby, String message) {
24
+ return newMemcachedError(ruby, "ATimeoutOccurred", message);
25
+ }
26
+
23
27
  private static RaiseException newMemcachedError(Ruby ruby, String klass, String message) {
24
28
  RubyClass errorClass = ruby.getModule("Memcached").getClass(klass);
25
29
  return new RaiseException(RubyException.newException(ruby, errorClass, message), true);
@@ -3,6 +3,7 @@ package com.openfeint.memcached.transcoder;
3
3
  import net.spy.memcached.CachedData;
4
4
  import net.spy.memcached.transcoders.Transcoder;
5
5
  import org.jruby.Ruby;
6
+ import org.jruby.exceptions.RaiseException;
6
7
  import org.jruby.runtime.builtin.IRubyObject;
7
8
  import org.jruby.runtime.marshal.MarshalStream;
8
9
  import org.jruby.runtime.marshal.UnmarshalStream;
@@ -16,8 +17,8 @@ import java.io.IOException;
16
17
  * MarshalTranscoder does marshaling and unmarshaling.
17
18
  *
18
19
  */
19
- public class MarshalTranscoder implements Transcoder<IRubyObject> {
20
- private Ruby ruby;
20
+ public class MarshalTranscoder implements Transcoder {
21
+ protected Ruby ruby;
21
22
  private int flags;
22
23
 
23
24
  public MarshalTranscoder(Ruby ruby) {
@@ -33,23 +34,29 @@ public class MarshalTranscoder implements Transcoder<IRubyObject> {
33
34
  return false;
34
35
  }
35
36
 
36
- public CachedData encode(IRubyObject o) {
37
- try {
38
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
39
- MarshalStream marshal = new MarshalStream(ruby, baos, Integer.MAX_VALUE);
40
- marshal.dumpObject(o);
41
- byte[] bytes = baos.toByteArray();
42
- return new CachedData(getFlags(), bytes, bytes.length);
43
- } catch (IOException ioe) {
44
- throw ruby.newIOErrorFromException(ioe);
37
+ public CachedData encode(Object o) {
38
+ if (o instanceof IRubyObject) {
39
+ try {
40
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
41
+ MarshalStream marshal = new MarshalStream(ruby, baos, Integer.MAX_VALUE);
42
+ marshal.dumpObject((IRubyObject) o);
43
+ byte[] bytes = baos.toByteArray();
44
+ return new CachedData(getFlags(), bytes, bytes.length);
45
+ } catch (IOException e) {
46
+ throw ruby.newIOErrorFromException(e);
47
+ }
48
+ } else {
49
+ return encodeNumber(o);
45
50
  }
46
51
  }
47
52
 
48
- public IRubyObject decode(CachedData d) {
53
+ public Object decode(CachedData d) {
49
54
  try {
50
55
  return new UnmarshalStream(ruby, new ByteArrayInputStream(d.getData()), null, false, false).unmarshalObject();
51
- } catch (IOException ioe) {
52
- throw ruby.newIOErrorFromException(ioe);
56
+ } catch (RaiseException e) {
57
+ return decodeNumber(d, e);
58
+ } catch (IOException e) {
59
+ return decodeNumber(d, e);
53
60
  }
54
61
  }
55
62
 
@@ -60,4 +67,25 @@ public class MarshalTranscoder implements Transcoder<IRubyObject> {
60
67
  public int getFlags() {
61
68
  return flags;
62
69
  }
70
+
71
+ protected CachedData encodeNumber(Object o) {
72
+ byte[] bytes = o.toString().getBytes();
73
+ return new CachedData(getFlags(), bytes, bytes.length);
74
+ }
75
+
76
+ protected Long decodeNumber(CachedData d, RaiseException originalException) {
77
+ try {
78
+ return Long.valueOf(new String(d.getData()).trim());
79
+ } catch (NumberFormatException e) {
80
+ throw ruby.newRuntimeError(originalException.getLocalizedMessage());
81
+ }
82
+ }
83
+
84
+ protected Long decodeNumber(CachedData d, IOException originalException) {
85
+ try {
86
+ return Long.valueOf(new String(d.getData()).trim());
87
+ } catch (NumberFormatException e) {
88
+ throw ruby.newIOErrorFromException(originalException);
89
+ }
90
+ }
63
91
  }
@@ -6,6 +6,7 @@ import com.jcraft.jzlib.JZlib;
6
6
  import net.spy.memcached.CachedData;
7
7
  import net.spy.memcached.transcoders.Transcoder;
8
8
  import org.jruby.Ruby;
9
+ import org.jruby.exceptions.RaiseException;
9
10
  import org.jruby.runtime.builtin.IRubyObject;
10
11
  import org.jruby.runtime.marshal.MarshalStream;
11
12
  import org.jruby.runtime.marshal.UnmarshalStream;
@@ -22,77 +23,69 @@ import java.io.IOException;
22
23
  * MarshalZlibTranscoder do marshaling/unmarshaling and compressing/decompressing with zlib.
23
24
  *
24
25
  */
25
- public class MarshalZlibTranscoder implements Transcoder<IRubyObject> {
26
- private Ruby ruby;
27
- private int flags;
26
+ public class MarshalZlibTranscoder extends MarshalTranscoder {
27
+ static final int COMPRESS_FLAG = 1;
28
28
 
29
29
  public MarshalZlibTranscoder(Ruby ruby) {
30
- this(ruby, 1);
30
+ super(ruby, COMPRESS_FLAG);
31
31
  }
32
32
 
33
33
  public MarshalZlibTranscoder(Ruby ruby, int flags) {
34
- this.ruby = ruby;
35
- this.flags = flags;
34
+ super(ruby, flags);
36
35
  }
37
36
 
38
- public boolean asyncDecode(CachedData d) {
39
- return false;
40
- }
37
+ public CachedData encode(Object o) {
38
+ if (o instanceof IRubyObject) {
39
+ try {
40
+ ByteArrayOutputStream out1 = new ByteArrayOutputStream();
41
+ MarshalStream marshal = new MarshalStream(ruby, out1, Integer.MAX_VALUE);
42
+ marshal.dumpObject((IRubyObject) o);
41
43
 
42
- public CachedData encode(IRubyObject o) {
43
- try {
44
- ByteArrayOutputStream out1 = new ByteArrayOutputStream();
45
- MarshalStream marshal = new MarshalStream(ruby, out1, Integer.MAX_VALUE);
46
- marshal.dumpObject(o);
44
+ byte[] bytes;
45
+ if (getFlags() == COMPRESS_FLAG) {
46
+ ByteArrayOutputStream out2 = new ByteArrayOutputStream();
47
+ ZOutputStream zout = new ZOutputStream(out2, JZlib.Z_DEFAULT_COMPRESSION);
48
+ zout.write(out1.toByteArray());
49
+ zout.close();
50
+ bytes = out2.toByteArray();
51
+ } else {
52
+ bytes = out1.toByteArray();
53
+ }
47
54
 
48
- byte[] bytes;
49
- if (flags == 1) {
50
- ByteArrayOutputStream out2 = new ByteArrayOutputStream();
51
- ZOutputStream zout = new ZOutputStream(out2, JZlib.Z_DEFAULT_COMPRESSION);
52
- zout.write(out1.toByteArray());
53
- zout.close();
54
- bytes = out2.toByteArray();
55
- } else {
56
- bytes = out1.toByteArray();
55
+ return new CachedData(super.getFlags(), bytes, bytes.length);
56
+ } catch (IOException e) {
57
+ throw ruby.newIOErrorFromException(e);
57
58
  }
58
-
59
- return new CachedData(getFlags(), bytes, bytes.length);
60
- } catch (IOException ioe) {
61
- throw ruby.newIOErrorFromException(ioe);
59
+ } else {
60
+ return super.encodeNumber(o);
62
61
  }
63
62
  }
64
63
 
65
- public IRubyObject decode(CachedData d) {
64
+ public Object decode(CachedData d) {
66
65
  try {
67
66
  byte[] bytes;
68
- if (d.getFlags() == 1) {
69
- ByteArrayInputStream in = new ByteArrayInputStream(d.getData());
70
- ZInputStream zin = new ZInputStream(in);
67
+ if (d.getFlags() == COMPRESS_FLAG) {
68
+ ByteArrayInputStream in = new ByteArrayInputStream(d.getData());
69
+ ZInputStream zin = new ZInputStream(in);
71
70
 
72
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
73
- int nRead;
74
- byte[] data = new byte[1024];
75
- while ((nRead = zin.read(data, 0, data.length)) != -1) {
76
- buffer.write(data, 0, nRead);
77
- }
78
- buffer.flush();
79
- bytes = buffer.toByteArray();
80
- zin.close();
71
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
72
+ int nRead;
73
+ byte[] data = new byte[1024];
74
+ while ((nRead = zin.read(data, 0, data.length)) != -1) {
75
+ buffer.write(data, 0, nRead);
76
+ }
77
+ buffer.flush();
78
+ bytes = buffer.toByteArray();
79
+ zin.close();
81
80
  } else {
82
- bytes = d.getData();
81
+ bytes = d.getData();
83
82
  }
84
83
 
85
84
  return new UnmarshalStream(ruby, new ByteArrayInputStream(bytes), null, false, false).unmarshalObject();
86
- } catch (IOException ioe) {
87
- throw ruby.newIOErrorFromException(ioe);
85
+ } catch (RaiseException e) {
86
+ return super.decodeNumber(d, e);
87
+ } catch (IOException e) {
88
+ return super.decodeNumber(d, e);
88
89
  }
89
90
  }
90
-
91
- public int getMaxSize() {
92
- return CachedData.MAX_SIZE;
93
- }
94
-
95
- public int getFlags() {
96
- return flags;
97
- }
98
91
  }
Binary file
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: jruby-memcached
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.1
5
+ version: 0.5.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Richard Huang
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-08-17 00:00:00 Z
13
+ date: 2012-08-22 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -63,6 +63,7 @@ files:
63
63
  - src/main/java/com/openfeint/memcached/Memcached.java
64
64
  - src/main/java/com/openfeint/memcached/MemcachedService.java
65
65
  - src/main/java/com/openfeint/memcached/Rails.java
66
+ - src/main/java/com/openfeint/memcached/error/ATimeoutOccurred.java
66
67
  - src/main/java/com/openfeint/memcached/error/Error.java
67
68
  - src/main/java/com/openfeint/memcached/error/NotFound.java
68
69
  - src/main/java/com/openfeint/memcached/error/NotStored.java