ikai-jruby-memcache-client 1.5.1

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.
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ nbproject/private
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2008 Abhi Yerra <abhi@traytwo.com>
2
+ Copyright (c) 2009 Ikai Lan <ikai.lan@gmail.com>
3
+ Copyright (c) 2009 Tiago Bastos <comechao@gmail.com>
4
+ Copyright (c) 2009 Frederic Jean <frederic.jean@sun.com>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
data/README ADDED
@@ -0,0 +1,69 @@
1
+ This projects provides memcached based stores for JRuby. It is a gem based on Ikai Lan's jruby-memcache-client project hosted at http://github.com/ikai/jruby-memcache-client/tree
2
+
3
+ This project is a JRuby wrapper of the Java MemCache library by Greg Whalin
4
+
5
+ http://www.whalin.com/memcached/
6
+
7
+ In production, the standard Ruby MemCache client can cause a thread to hang. In the Glassfish application server, by default there are 5 Grizzly connectors that handle incoming requests. A site that uses MemCache heavily can quickly cause all Grizzly connectors to block and take down a site. I'm hoping that this work I am doing here will help others adopt JRuby as a production platform for their Ruby on Rails applications.
8
+
9
+ The Ruby MemCache library was never written with threaded applications in mind. All threads use the same socket, and multithreaded mode basically wraps the IO with a Mutex. The Java library provides several features that are not available in the Ruby MemCache library:
10
+
11
+ - connection pooling
12
+ - socket timeouts. In forks of the Ruby MemCache library this is achieved either with a Mongrel timeout or use of the Ruby Timeout class, which, at least at the writing of this README, will work unpredictably when being used as a failsafe against hanging IO.
13
+
14
+ As of right now this code only provides a very minimal amount of functionality, but it is enough to use with the Rails cache and cache_fu.
15
+
16
+ Installation
17
+ ------------
18
+ This is a ruby gem that can be installed.
19
+
20
+ gem sources -a http://gems.github.com
21
+ gem install fredjean-jruby-memcache-client --remote
22
+
23
+ Replacing Rail's MemCache Client
24
+ --------------------------------
25
+
26
+ Rails ships with a bundled copy of the MemCache client. This client will prevent you from using this gem instead. Adding the following code into your environment.rb file:
27
+
28
+ if RUBY_PLATFORM =~ /java/i
29
+ # Based on instructions from http://www.mikeperham.com/2009/03/03/using-memcache-client-16x-in-rails-23/
30
+ # Brain surgery to use our own version of memcache-client without
31
+ # having to modify activesupport directly.
32
+ # Unload any previous instance of the class
33
+ if Object.const_defined? :MemCache
34
+ Object.instance_eval { remove_const :MemCache }
35
+ end
36
+ # Pull in the exact version we want
37
+ gem 'fredjean-jruby-memcache-client', '1.5.0'
38
+
39
+ # Ensure that the memcache-client path is at the front of the loadpath
40
+ $LOAD_PATH.each do |path|
41
+ if path =~ /fredjean-jruby-memcache-client/
42
+ $LOAD_PATH.delete(path)
43
+ $LOAD_PATH.unshift(path)
44
+ end
45
+ end
46
+ # If Ruby thinks it's already loaded memcache.rb, force
47
+ # a reload otherwise just require.
48
+ if $".find { |file| file =~ /\Amemcache.rb\Z/ }
49
+ load 'memcache.rb'
50
+ else
51
+ require 'memcache'
52
+ end
53
+ end
54
+
55
+ This will remove the original MemCache client and load our version of the MemCache class instead.
56
+
57
+ Configuration
58
+ -------------
59
+ The JRuby MemCache client uses the same configuration options as the regular MemCache client. Here is how to build the configuration in your environment.rb file:
60
+
61
+ memcache_options = {
62
+ :namespace => 'fortaleza:production_live:',
63
+ }
64
+ memcached_servers = [ ENV['MEMCACHED_LOCATION'] || '0.0.0.0:11211']
65
+
66
+ # Constant used by libs
67
+ CACHE = MemCache.new memcached_servers, memcache_options if RUBY_PLATFORM =~ /java/
68
+
69
+ Note that this may vary based on your particular configuration method and environment.
@@ -0,0 +1,28 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "jruby-memcache-client"
5
+ gemspec.summary = "A drop in replacement for Ruby's memcache-client."
6
+ gemspec.email = "abhi@traytwo.com"
7
+ gemspec.homepage = "http://github.com/abhiyerra/jruby-memcache-client"
8
+ gemspec.description = "A drop in replacement for Ruby's memcache-client."
9
+ gemspec.authors = ["Abhi Yerra", "Ikai Lan", "Frederic Jean", "Lennon Day-Reynolds"]
10
+ end
11
+ rescue LoadError
12
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
13
+ end
14
+
15
+ if RUBY_PLATFORM =~ /java/i
16
+ begin
17
+ require 'spec/rake/spectask'
18
+
19
+ task :default => :spec
20
+
21
+ desc "Run the specs for the jruby-memcache-client gem"
22
+ Spec::Rake::SpecTask.new
23
+ rescue LoadError
24
+ puts "You must have rspec installed in order to run the tests."
25
+ end
26
+ else
27
+ puts "You must run rake under JRuby."
28
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 5
3
+ :major: 1
4
+ :patch: 1
@@ -0,0 +1,45 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{jruby-memcache-client}
5
+ s.version = "1.5.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Abhi Yerra", "Ikai Lan", "Frederic Jean", "Lennon Day-Reynolds"]
9
+ s.date = %q{2009-05-20}
10
+ s.description = %q{A drop in replacement for Ruby's memcache-client.}
11
+ s.email = %q{abhi@traytwo.com}
12
+ s.extra_rdoc_files = [
13
+ "README"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "MIT-LICENSE",
18
+ "README",
19
+ "Rakefile",
20
+ "VERSION.yml",
21
+ "jruby-memcache-client.gemspec",
22
+ "lib/java/java_memcached-release_2.0.1.jar",
23
+ "lib/memcache.rb",
24
+ "spec/jruby_memcache_spec.rb"
25
+ ]
26
+ s.has_rdoc = true
27
+ s.homepage = %q{http://github.com/ikai/jruby-memcache-client}
28
+ s.rdoc_options = ["--charset=UTF-8"]
29
+ s.require_paths = ["lib"]
30
+ s.rubygems_version = %q{1.3.1}
31
+ s.summary = %q{A drop in replacement for Ruby's memcache-client.}
32
+ s.test_files = [
33
+ "spec/jruby_memcache_spec.rb"
34
+ ]
35
+
36
+ if s.respond_to? :specification_version then
37
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
38
+ s.specification_version = 2
39
+
40
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
41
+ else
42
+ end
43
+ else
44
+ end
45
+ end
@@ -0,0 +1,237 @@
1
+ require File.dirname(__FILE__) + '/java/java_memcached-release_2.0.1.jar'
2
+
3
+ class MemCache
4
+ include_class 'com.danga.MemCached.MemCachedClient'
5
+ include_class 'com.danga.MemCached.SockIOPool'
6
+
7
+ VERSION = '1.5.0'
8
+
9
+ ##
10
+ # Default options for the cache object.
11
+
12
+ DEFAULT_OPTIONS = {
13
+ :namespace => nil,
14
+ :readonly => false,
15
+ :multithread => true,
16
+ :pool_initial_size => 5,
17
+ :pool_min_size => 5,
18
+ :pool_max_size => 250,
19
+ :pool_max_idle => (1000 * 60 * 60 * 6),
20
+ :pool_maintenance_thread_sleep => 30,
21
+ :pool_use_nagle => false,
22
+ :pool_socket_timeout => 3000,
23
+ :pool_socket_connect_timeout => 3000,
24
+ :pool_name => 'default'
25
+ }
26
+
27
+ ## CHARSET for Marshalling
28
+ MARSHALLING_CHARSET = 'UTF-8'
29
+
30
+ ##
31
+ # Default memcached port.
32
+
33
+ DEFAULT_PORT = 11211
34
+
35
+ ##
36
+ # Default memcached server weight.
37
+
38
+ DEFAULT_WEIGHT = 1
39
+
40
+ attr_accessor :request_timeout
41
+
42
+ ##
43
+ # The namespace for this instance
44
+
45
+ attr_reader :namespace
46
+
47
+ ##
48
+ # The multithread setting for this instance
49
+
50
+ attr_reader :multithread
51
+
52
+ ##
53
+ # The configured socket pool name for this client.
54
+ attr_reader :pool_name
55
+
56
+ def initialize(*args)
57
+ @servers = []
58
+ opts = {}
59
+
60
+ case args.length
61
+ when 0 then # NOP
62
+ when 1 then
63
+ arg = args.shift
64
+ case arg
65
+ when Hash then opts = arg
66
+ when Array then @servers = arg
67
+ when String then @servers = [arg]
68
+ else raise ArgumentError, 'first argument must be Array, Hash or String'
69
+ end
70
+ when 2 then
71
+ @servers, opts = args
72
+ @servers = [@servers].flatten
73
+ else
74
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 2)"
75
+ end
76
+
77
+ opts = DEFAULT_OPTIONS.merge opts
78
+
79
+ @namespace = opts[:namespace] || opts["namespace"]
80
+ @pool_name = opts[:pool_name] || opts["pool_name"]
81
+
82
+ @client = MemCachedClient.new(@pool_name)
83
+
84
+ @client.primitiveAsString = true
85
+ @client.sanitizeKeys = false
86
+
87
+ weights = Array.new(@servers.size, DEFAULT_WEIGHT)
88
+
89
+ @pool = SockIOPool.getInstance(@pool_name)
90
+ unless @pool.initialized?
91
+ # // set the servers and the weights
92
+ @pool.servers = @servers.to_java(:string)
93
+ @pool.weights = weights.to_java(:Integer)
94
+
95
+ # // set some basic pool settings
96
+ # // 5 initial, 5 min, and 250 max conns
97
+ # // and set the max idle time for a conn
98
+ # // to 6 hours
99
+ @pool.initConn = opts[:pool_initial_size]
100
+ @pool.minConn = opts[:pool_min_size]
101
+ @pool.maxConn = opts[:pool_max_size]
102
+ @pool.maxIdle = opts[:pool_max_idle]
103
+
104
+ # // set the sleep for the maint thread
105
+ # // it will wake up every x seconds and
106
+ # // maintain the pool size
107
+ @pool.maintSleep = opts[:pool_maintenance_thread_sleep]
108
+ #
109
+ # // set some TCP settings
110
+ # // disable nagle
111
+ # // set the read timeout to 3 secs
112
+ # // and don't set a connect timeout
113
+ @pool.nagle = opts[:pool_use_nagle]
114
+ @pool.socketTO = opts[:pool_socket_timeout]
115
+ @pool.socketConnectTO = opts[:pool_socket_connect_timeout]
116
+ @pool.aliveCheck = true
117
+ @pool.initialize__method
118
+ end
119
+ end
120
+
121
+ def servers
122
+ @pool.get_servers.to_a rescue []
123
+ end
124
+
125
+ def alive?
126
+ @pool.servers.to_a.any?
127
+ end
128
+
129
+ def get(key, raw = false)
130
+ value = @client.get(make_cache_key(key))
131
+ return nil if value.nil?
132
+ unless raw
133
+ marshal_bytes = java.lang.String.new(value).getBytes(MARSHALLING_CHARSET)
134
+ value = Marshal.load(String.from_java_bytes(marshal_bytes))
135
+ end
136
+ value
137
+ end
138
+
139
+ alias :[] :get
140
+
141
+ def get_multi(keys, raw = false)
142
+ keys = keys.map {|k| make_cache_key(k)}
143
+ keys = keys.to_java :String
144
+ values = {}
145
+ values_j = @client.getMulti(keys)
146
+ values_j.to_a.each {|kv|
147
+ k,v = kv
148
+ next if v.nil?
149
+ unless raw
150
+ marshal_bytes = java.lang.String.new(v).getBytes(MARSHALLING_CHARSET)
151
+ v = Marshal.load(String.from_java_bytes(marshal_bytes))
152
+ end
153
+ values[k] = v
154
+ }
155
+ values
156
+ end
157
+
158
+ def set(key, value, expiry = 0, raw = false)
159
+ value = marshal_value(value) unless raw
160
+ key = make_cache_key(key)
161
+ if expiry == 0
162
+ @client.set key, value
163
+ else
164
+ @client.set key, value, expiration(expiry)
165
+ end
166
+ end
167
+
168
+ alias :[]= :set
169
+
170
+ def add(key, value, expiry = 0, raw = false)
171
+ value = marshal_value(value) unless raw
172
+ if expiry == 0
173
+ @client.add make_cache_key(key), value
174
+ else
175
+ @client.add make_cache_key(key), value, expiration(expiry)
176
+ end
177
+ end
178
+
179
+ def delete(key, expiry = 0)
180
+ @client.delete(make_cache_key(key))
181
+ end
182
+
183
+ def incr(key, amount = 1)
184
+ value = get(key) || 0
185
+ value += amount
186
+ set key, value
187
+ value
188
+ end
189
+
190
+ def decr(key, amount = 1)
191
+ value = get(key) || 0
192
+ value -= amount
193
+ set key, value
194
+ value
195
+ end
196
+
197
+ def flush_all
198
+ @client.flushAll
199
+ end
200
+
201
+ def stats
202
+ stats_hash = {}
203
+ @client.stats.each do |server, stats|
204
+ stats_hash[server] = Hash.new
205
+ stats.each do |key, value|
206
+ unless key == 'version'
207
+ value = value.to_f
208
+ value = value.to_i if value == value.ceil
209
+ end
210
+ stats_hash[server][key] = value
211
+ end
212
+ end
213
+ stats_hash
214
+ end
215
+
216
+ protected
217
+ def make_cache_key(key)
218
+ if namespace.nil? then
219
+ key
220
+ else
221
+ "#{@namespace}:#{key}"
222
+ end
223
+ end
224
+
225
+ def expiration(expiry)
226
+ java.util.Date.new((Time.now.to_i + expiry) * 1000)
227
+ end
228
+
229
+ def marshal_value(value)
230
+ marshal_bytes = Marshal.dump(value).to_java_bytes
231
+ java.lang.String.new(marshal_bytes, MARSHALLING_CHARSET)
232
+ end
233
+
234
+ class MemCacheError < RuntimeError; end
235
+
236
+ end
237
+
@@ -0,0 +1,208 @@
1
+ #require 'rubygems'
2
+ #require 'spec'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/memcache'
5
+
6
+ describe MemCache do
7
+ before(:all) do
8
+ @server = "127.0.0.1:11211"
9
+ @client = MemCache.new @server
10
+ @client.flush_all
11
+ end
12
+
13
+ after(:each) do
14
+ @client.flush_all
15
+ end
16
+
17
+ it "should return nil for a non-existent key" do
18
+ @client.get('non-existent-key').should be_nil
19
+ end
20
+
21
+ describe "setting servers" do
22
+ it "should work if the instance is created with a single String argument" do
23
+ @client = MemCache.new @server
24
+ @client.servers.should == [@server]
25
+ end
26
+
27
+ it "should work if the instance is created with an Array" do
28
+ @client = MemCache.new [ @server ]
29
+ @client.servers.should == [ @server ]
30
+ end
31
+
32
+ it "should work if the instance is created with a Hash" do
33
+ @client = MemCache.new [ @server ], :namespace => 'test'
34
+ @client.servers.should == [ @server ]
35
+ end
36
+
37
+ it "should work with an explicit pool name" do
38
+ @client = MemCache.new([@server], :pool_name => 'new_pool')
39
+ @client.pool_name.should == 'new_pool'
40
+ end
41
+ end
42
+
43
+ describe "namespacing" do
44
+ before(:each) do
45
+ @ns = 'namespace'
46
+ @nsclient = MemCache.new [ @server ] , :namespace => @ns
47
+ @nsclient.flush_all
48
+ @nsclient.set "test", 333, 0
49
+ end
50
+
51
+ it "should set and get values transparently" do
52
+ @nsclient.get("test").to_i.should == 333
53
+ end
54
+
55
+ it "should set values to the given namespace" do
56
+ @client.get("#{@ns}:test").to_i.should == 333
57
+ end
58
+
59
+ it "should not set a value without the given namespace" do
60
+ @client.get("test").to_i.should_not == 333
61
+ end
62
+
63
+ it "should delete values in the given namespace" do
64
+ @nsclient.delete "test"
65
+ @nsclient.get("test").should be_nil
66
+ end
67
+
68
+ it "should increment in the given namespace" do
69
+ @nsclient.incr("test").to_i.should == 334
70
+ end
71
+
72
+ it "should decrement values in the given namespace" do
73
+ @nsclient.decr("test").should == 332
74
+ end
75
+ end
76
+
77
+ describe "after setting a value to MemCache" do
78
+ before(:each) do
79
+ @client.set 'key', 'value'
80
+ end
81
+
82
+ it "should be able to retrieve the value" do
83
+ @client.get('key').should == 'value'
84
+ end
85
+
86
+ it "should not be able to retrieve the value after deleting" do
87
+ @client.delete('key')
88
+ @client.get('key').should be_nil
89
+ end
90
+
91
+ it "should not be able to retrieve the value after flushing everything" do
92
+ @client.flush_all
93
+ @client.get("key").should be_nil
94
+ end
95
+
96
+ it "should work exactly the same if the []= operator were used" do
97
+ @client['key'] = 'val'
98
+ @client.get('key').should == 'val'
99
+ end
100
+ end
101
+
102
+ describe "using the Hash notation" do
103
+ before :each do
104
+ @client['key'] = 'value'
105
+ end
106
+
107
+ it "should be able to retrieve the value using []" do
108
+ @client['key'].should == 'value'
109
+ end
110
+
111
+ it "should be able to retrieve the value using get" do
112
+ @client.get('key').should == 'value'
113
+ end
114
+ end
115
+
116
+ describe "#stats" do
117
+ it "should return a hash" do
118
+ @client.stats.should be_instance_of(Hash)
119
+ end
120
+
121
+ # it "should return 0 for curr_items" do
122
+ # @client.stats[@server]['curr_items'].should == 0
123
+ # end
124
+
125
+ it "should return a float for rusage_system and rusage_user" do
126
+ @client.stats[@server]['rusage_system'].should be_instance_of(Float)
127
+ @client.stats[@server]['rusage_user'].should be_instance_of(Float)
128
+ end
129
+
130
+ it "should return a String for version" do
131
+ @client.stats[@server]['version'].should be_instance_of(String)
132
+ end
133
+
134
+ end
135
+
136
+ describe "#incr" do
137
+
138
+ it "should increment a value by 1 without a second parameter" do
139
+ @client.set 'incr', 100, 0
140
+ @client.incr 'incr'
141
+ @client.get('incr').to_i.should == 101
142
+ end
143
+
144
+ it "should increment a value by a given second parameter" do
145
+ @client.set 'incr', 100, 0
146
+ @client.incr 'incr', 20
147
+ @client.get('incr').to_i.should == 120
148
+ end
149
+ end
150
+
151
+ describe "#decr" do
152
+
153
+ it "should decrement a value by 1 without a second parameter" do
154
+ @client.set 'decr', 100, 0
155
+ @client.decr 'decr'
156
+ @client.get('decr').to_i.should == 99
157
+ end
158
+
159
+ it "should decrement a value by a given second parameter" do
160
+ @client.set 'decr', 100, 0
161
+ @client.decr 'decr', 20
162
+ @client.get('decr').to_i.should == 80
163
+ end
164
+ end
165
+
166
+ describe "with Ruby Objects" do
167
+ it "should be able to transparently set and get equivalent Ruby objects" do
168
+ obj = { :test => :hi }
169
+ @client.set('obj', obj)
170
+ @client.get('obj').should == obj
171
+ end
172
+ end
173
+
174
+ describe "using set with an expiration" do
175
+ it "should make a value unretrievable if the expiry is set to a negative value" do
176
+ @client.set('key', 'val', -1)
177
+ @client.get('key').should be_nil
178
+ end
179
+
180
+ it "should make a value retrievable for only the amount of time if a value is given" do
181
+ @client.set('key', 'val', 2)
182
+ @client.get('key').should == 'val'
183
+ sleep(3)
184
+ @client.get('key').should be_nil
185
+ end
186
+ end
187
+
188
+ describe "#get_multi" do
189
+ it "should get 2 keys" do
190
+ @client.set('key', 'val')
191
+ @client.set('key2', 'val2')
192
+ @client.get_multi(%w/key key2/).should == {'key' => 'val', 'key2' => 'val2'}
193
+ end
194
+
195
+ it "should ignore nil values" do
196
+ @client.set('key', 'val')
197
+ @client.set('key2', 'val2')
198
+ @client.get_multi(%w/key key2 key3/).should == {'key' => 'val', 'key2' => 'val2'}
199
+ end
200
+
201
+ it "should not marshall if requested" do
202
+ @client.set('key', 'val', 0, true)
203
+ @client.set('key2', 'val2', 0, true)
204
+ @client.get_multi(%w/key key2/, true).should == {'key' => 'val', 'key2' => 'val2'}
205
+ end
206
+ end
207
+ end
208
+
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ikai-jruby-memcache-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.5.1
5
+ platform: ruby
6
+ authors:
7
+ - Abhi Yerra
8
+ - Ikai Lan
9
+ - Frederic Jean
10
+ - Lennon Day-Reynolds
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+
15
+ date: 2009-05-20 00:00:00 -07:00
16
+ default_executable:
17
+ dependencies: []
18
+
19
+ description: A drop in replacement for Ruby's memcache-client.
20
+ email: abhi@traytwo.com
21
+ executables: []
22
+
23
+ extensions: []
24
+
25
+ extra_rdoc_files:
26
+ - README
27
+ files:
28
+ - .gitignore
29
+ - MIT-LICENSE
30
+ - README
31
+ - Rakefile
32
+ - VERSION.yml
33
+ - jruby-memcache-client.gemspec
34
+ - lib/java/java_memcached-release_2.0.1.jar
35
+ - lib/memcache.rb
36
+ - spec/jruby_memcache_spec.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/ikai/jruby-memcache-client
39
+ licenses:
40
+ post_install_message:
41
+ rdoc_options:
42
+ - --charset=UTF-8
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.3.5
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: A drop in replacement for Ruby's memcache-client.
64
+ test_files:
65
+ - spec/jruby_memcache_spec.rb