jruby-memcached 0.4.1 → 0.5.0

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/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