rev_memcache 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Andrew Rudenko
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ = rev_memcache
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Andrew Rudenko. See LICENSE for details.
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "rev_memcache"
8
+ gem.summary = %Q{Rev memcache client}
9
+ gem.description = %Q{Rev memcache client}
10
+ gem.email = "ceo@prepor.ru"
11
+ gem.homepage = "http://github.com/prepor/rev_memcache"
12
+ gem.authors = ["Andrew Rudenko"]
13
+ gem.add_dependency "rev", ">= 0"
14
+ end
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
+ end
19
+
20
+ require 'rake/testtask'
21
+ Rake::TestTask.new(:test) do |test|
22
+ test.libs << 'lib' << 'test'
23
+ test.pattern = 'test/**/test_*.rb'
24
+ test.verbose = true
25
+ end
26
+
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |test|
30
+ test.libs << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+ rescue LoadError
35
+ task :rcov do
36
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
+ end
38
+ end
39
+
40
+ task :test => :check_dependencies
41
+
42
+ task :default => :test
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "rev_memcache #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'rev'
3
+ require File.dirname(__FILE__) + '/../lib/rev_memcache'
4
+
5
+ event_loop = Rev::Loop.default
6
+ cache = Rev::Memcache.connect('localhost', 11211).attach(event_loop)
7
+
8
+ cache.set :a, 'hello'
9
+ cache.set :b, 'hi'
10
+ cache.set :c, 'how are you?'
11
+ cache.set :d, ''
12
+
13
+ cache.get(:a){ |v| p v }
14
+ cache.get_hash(:a, :b, :c, :d){ |v| p v }
15
+ cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
16
+
17
+ cache.get(:a,:z,:b,:y,:d){ |a,z,b,y,d| p [a,z,b,y,d] }
18
+
19
+ cache.get(:missing){ |m| p [:missing=, m] }
20
+ cache.set(:missing, 'abc'){ p :stored }
21
+ cache.get(:missing){ |m| p [:missing=, m] }
22
+ cache.del(:missing){ p :deleted }
23
+ cache.get(:missing){ |m| p [:missing=, m] }
24
+
25
+ event_loop.run
@@ -0,0 +1,205 @@
1
+ module Rev
2
+ # Implements the Memcache protocol (http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt).
3
+ # Requires memcached >= 1.2.4 w/ noreply support
4
+ #
5
+ # == Usage example
6
+ #
7
+ # EM.run{
8
+ # cache = EM::P::Memcache.connect 'localhost', 11211
9
+ #
10
+ # cache.set :a, 'hello'
11
+ # cache.set :b, 'hi'
12
+ # cache.set :c, 'how are you?'
13
+ # cache.set :d, ''
14
+ #
15
+ # cache.get(:a){ |v| p v }
16
+ # cache.get_hash(:a, :b, :c, :d){ |v| p v }
17
+ # cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
18
+ #
19
+ # cache.get(:a,:z,:b,:y,:d){ |a,z,b,y,d| p [a,z,b,y,d] }
20
+ #
21
+ # cache.get(:missing){ |m| p [:missing=, m] }
22
+ # cache.set(:missing, 'abc'){ p :stored }
23
+ # cache.get(:missing){ |m| p [:missing=, m] }
24
+ # cache.del(:missing){ p :deleted }
25
+ # cache.get(:missing){ |m| p [:missing=, m] }
26
+ # }
27
+ #
28
+ class Memcache < TCPSocket
29
+ require 'rev_memcache/deferrable'
30
+
31
+ include Deferrable
32
+ ##
33
+ # constants
34
+
35
+ # :stopdoc:
36
+ unless defined? Cempty
37
+ Cstored = 'STORED'.freeze
38
+ Cend = 'END'.freeze
39
+ Cdeleted = 'DELETED'.freeze
40
+ Cunknown = 'NOT_FOUND'.freeze
41
+ Cerror = 'ERROR'.freeze
42
+
43
+ Cempty = ''.freeze
44
+ Cdelimiter = "\r\n".freeze
45
+ end
46
+ # :startdoc:
47
+
48
+ ##
49
+ # commands
50
+
51
+ # Get the value associated with one or multiple keys
52
+ #
53
+ # cache.get(:a){ |v| p v }
54
+ # cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
55
+ #
56
+ def get *keys
57
+ raise ArgumentError unless block_given?
58
+
59
+ callback{
60
+ keys = keys.map{|k| k.to_s.gsub(/\s/,'_') }
61
+ write "get #{keys.join(' ')}\r\n"
62
+ @get_cbs << [keys, proc{ |values|
63
+ yield *keys.map{ |k| values[k] }
64
+ }]
65
+ }
66
+ end
67
+
68
+ # Set the value for a given key
69
+ #
70
+ # cache.set :a, 'hello'
71
+ # cache.set(:missing, 'abc'){ puts "stored the value!" }
72
+ #
73
+ def set key, val, exptime = 0, &cb
74
+ callback{
75
+ val = val.to_s
76
+ send_cmd :set, key, 0, exptime, val.respond_to?(:bytesize) ? val.bytesize : val.size, !block_given?
77
+ write val
78
+ write Cdelimiter
79
+ @set_cbs << cb if cb
80
+ }
81
+ end
82
+
83
+ # Gets multiple values as a hash
84
+ #
85
+ # cache.get_hash(:a, :b, :c, :d){ |h| puts h[:a] }
86
+ #
87
+ def get_hash *keys
88
+ raise ArgumentError unless block_given?
89
+
90
+ get *keys do |*values|
91
+ yield keys.inject({}){ |hash, k| hash.update k => values[keys.index(k)] }
92
+ end
93
+ end
94
+
95
+ # Delete the value associated with a key
96
+ #
97
+ # cache.del :a
98
+ # cache.del(:b){ puts "deleted the value!" }
99
+ #
100
+ def delete key, expires = 0, &cb
101
+ callback{
102
+ write "delete #{key} #{expires}#{cb ? '' : ' noreply'}\r\n"
103
+ @del_cbs << cb if cb
104
+ }
105
+ end
106
+ alias del delete
107
+
108
+ # :stopdoc:
109
+
110
+ def send_cmd cmd, key, flags = 0, exptime = 0, bytes = 0, noreply = false # :nodoc:
111
+ write "#{cmd} #{key} #{flags} #{exptime} #{bytes}#{noreply ? ' noreply' : ''}\r\n"
112
+ end
113
+ private :send_cmd
114
+
115
+ ##
116
+ # errors
117
+
118
+ class ParserError < StandardError
119
+ end
120
+
121
+ ##
122
+ # em hooks
123
+
124
+ def on_connect
125
+ @get_cbs = []
126
+ @set_cbs = []
127
+ @del_cbs = []
128
+
129
+ @values = {}
130
+
131
+ @reconnecting = false
132
+ @connected = true
133
+ succeed
134
+ # set_delimiter "\r\n"
135
+ # set_line_mode
136
+ end
137
+
138
+ def on_read data
139
+ (@buffer||='') << data
140
+
141
+ while index = @buffer.index(Cdelimiter)
142
+ begin
143
+ line = @buffer.slice!(0,index+2)
144
+ process_cmd line
145
+ rescue ParserError
146
+ @buffer[0...0] = line
147
+ break
148
+ end
149
+ end
150
+ end
151
+
152
+ def process_cmd line
153
+ case line.strip
154
+ when /^VALUE\s+(.+?)\s+(\d+)\s+(\d+)/ # VALUE <key> <flags> <bytes>
155
+ bytes = Integer($3)
156
+ # set_binary_mode bytes+2
157
+ # @cur_key = $1
158
+ if @buffer.size >= bytes + 2
159
+ @values[$1] = @buffer.slice!(0,bytes)
160
+ @buffer.slice!(0,2) # \r\n
161
+ else
162
+ raise ParserError
163
+ end
164
+
165
+ when Cend # END
166
+ if entry = @get_cbs.shift
167
+ keys, cb = entry
168
+ cb.call(@values)
169
+ end
170
+ @values = {}
171
+
172
+ when Cstored # STORED
173
+ if cb = @set_cbs.shift
174
+ cb.call(true)
175
+ end
176
+
177
+ when Cdeleted # DELETED
178
+ if cb = @del_cbs.shift
179
+ cb.call(true)
180
+ end
181
+
182
+ when Cunknown # NOT_FOUND
183
+ if cb = @del_cbs.shift
184
+ cb.call(false)
185
+ end
186
+
187
+ else
188
+ p [:MEMCACHE_UNKNOWN, line]
189
+ end
190
+ end
191
+
192
+ def on_close
193
+ if @connected or @reconnecting
194
+ # EM.add_timer(1){ reconnect @host, @port }
195
+ @connected = false
196
+ @reconnecting = true
197
+ @deferred_status = nil
198
+ else
199
+ raise 'Unable to connect to memcached server'
200
+ end
201
+ end
202
+
203
+ # :startdoc:
204
+ end
205
+ end
@@ -0,0 +1,192 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 16 Jul 2006
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+ module Rev
27
+ module Memcache::Deferrable
28
+
29
+ # Specify a block to be executed if and when the Deferrable object receives
30
+ # a status of :succeeded. See #set_deferred_status for more information.
31
+ #
32
+ # Calling this method on a Deferrable object whose status is not yet known
33
+ # will cause the callback block to be stored on an internal list.
34
+ # If you call this method on a Deferrable whose status is :succeeded, the
35
+ # block will be executed immediately, receiving the parameters given to the
36
+ # prior #set_deferred_status call.
37
+ #
38
+ #--
39
+ # If there is no status, add a callback to an internal list.
40
+ # If status is succeeded, execute the callback immediately.
41
+ # If status is failed, do nothing.
42
+ #
43
+ def callback &block
44
+ return unless block
45
+ @deferred_status ||= :unknown
46
+ if @deferred_status == :succeeded
47
+ block.call(*@deferred_args)
48
+ elsif @deferred_status != :failed
49
+ @callbacks ||= []
50
+ @callbacks.unshift block # << block
51
+ end
52
+ end
53
+
54
+ # Specify a block to be executed if and when the Deferrable object receives
55
+ # a status of :failed. See #set_deferred_status for more information.
56
+ #--
57
+ # If there is no status, add an errback to an internal list.
58
+ # If status is failed, execute the errback immediately.
59
+ # If status is succeeded, do nothing.
60
+ #
61
+ def errback &block
62
+ return unless block
63
+ @deferred_status ||= :unknown
64
+ if @deferred_status == :failed
65
+ block.call(*@deferred_args)
66
+ elsif @deferred_status != :succeeded
67
+ @errbacks ||= []
68
+ @errbacks.unshift block # << block
69
+ end
70
+ end
71
+
72
+ # Sets the "disposition" (status) of the Deferrable object. See also the large set of
73
+ # sugarings for this method.
74
+ # Note that if you call this method without arguments,
75
+ # no arguments will be passed to the callback/errback.
76
+ # If the user has coded these with arguments, then the
77
+ # user code will throw an argument exception.
78
+ # Implementors of deferrable classes <b>must</b>
79
+ # document the arguments they will supply to user callbacks.
80
+ #
81
+ # OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
82
+ # on the INSIDE of a callback. This is very useful when a previously-registered
83
+ # callback wants to change the parameters that will be passed to subsequently-registered
84
+ # ones.
85
+ #
86
+ # You may give either :succeeded or :failed as the status argument.
87
+ #
88
+ # If you pass :succeeded, then all of the blocks passed to the object using the #callback
89
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
90
+ # passed to the object using #errback will be discarded.
91
+ #
92
+ # If you pass :failed, then all of the blocks passed to the object using the #errback
93
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
94
+ # passed to the object using # callback will be discarded.
95
+ #
96
+ # If you pass any arguments to #set_deferred_status in addition to the status argument,
97
+ # they will be passed as arguments to any callbacks or errbacks that are executed.
98
+ # It's your responsibility to ensure that the argument lists specified in your callbacks and
99
+ # errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
100
+ # an ArgumentError.
101
+ #
102
+ #--
103
+ # We're shifting callbacks off and discarding them as we execute them.
104
+ # This is valid because by definition callbacks are executed no more than
105
+ # once. It also has the magic effect of permitting recursive calls, which
106
+ # means that a callback can call #set_deferred_status and change the parameters
107
+ # that will be sent to subsequent callbacks down the chain.
108
+ #
109
+ # Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
110
+ # by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
111
+ # versions.
112
+ #
113
+ # Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
114
+ # handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
115
+ # which only allows status to be set once. Prior to making this change, it was possible
116
+ # to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
117
+ # triggering its errbacks! That is clearly undesirable, but it's just as undesirable
118
+ # to raise an exception is status is set more than once on a Deferrable. The latter
119
+ # behavior would invalidate the idiom of resetting arguments by setting status from
120
+ # within a callback or errback, but more seriously it would cause spurious errors
121
+ # if a Deferrable was timed out and then an attempt was made to succeed it. See the
122
+ # comments under the new method #timeout.
123
+ #
124
+ def set_deferred_status status, *args
125
+ cancel_timeout
126
+ @errbacks ||= nil
127
+ @callbacks ||= nil
128
+ @deferred_status = status
129
+ @deferred_args = args
130
+ case @deferred_status
131
+ when :succeeded
132
+ if @callbacks
133
+ while cb = @callbacks.pop
134
+ cb.call(*@deferred_args)
135
+ end
136
+ end
137
+ @errbacks.clear if @errbacks
138
+ when :failed
139
+ if @errbacks
140
+ while eb = @errbacks.pop
141
+ eb.call(*@deferred_args)
142
+ end
143
+ end
144
+ @callbacks.clear if @callbacks
145
+ end
146
+ end
147
+
148
+
149
+ # Setting a timeout on a Deferrable causes it to go into the failed state after
150
+ # the Timeout expires (passing no arguments to the object's errbacks).
151
+ # Setting the status at any time prior to a call to the expiration of the timeout
152
+ # will cause the timer to be cancelled.
153
+ def timeout seconds
154
+ cancel_timeout
155
+ me = self
156
+ @deferred_timeout = EventMachine::Timer.new(seconds) {me.fail}
157
+ end
158
+
159
+ # Cancels an outstanding timeout if any. Undoes the action of #timeout.
160
+ #
161
+ def cancel_timeout
162
+ @deferred_timeout ||= nil
163
+ if @deferred_timeout
164
+ @deferred_timeout.cancel
165
+ @deferred_timeout = nil
166
+ end
167
+ end
168
+
169
+
170
+ # Sugar for set_deferred_status(:succeeded, ...)
171
+ #
172
+ def succeed *args
173
+ set_deferred_status :succeeded, *args
174
+ end
175
+ alias set_deferred_success succeed
176
+
177
+ # Sugar for set_deferred_status(:failed, ...)
178
+ #
179
+ def fail *args
180
+ set_deferred_status :failed, *args
181
+ end
182
+ alias set_deferred_failure fail
183
+ end
184
+
185
+
186
+ # DefaultDeferrable is an otherwise empty class that includes Deferrable.
187
+ # This is very useful when you just need to return a Deferrable object
188
+ # as a way of communicating deferred status to some other part of a program.
189
+ class Memcache::DefaultDeferrable
190
+ include Memcache::Deferrable
191
+ end
192
+ end
File without changes
@@ -0,0 +1,54 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rev_memcache}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Andrew Rudenko"]
12
+ s.date = %q{2010-02-19}
13
+ s.description = %q{Rev memcache client}
14
+ s.email = %q{ceo@prepor.ru}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "examples/test.rb",
27
+ "lib/rev_memcache.rb",
28
+ "lib/rev_memcache/deferrable.rb",
29
+ "lib/t.rb",
30
+ "rev_memcache.gemspec"
31
+ ]
32
+ s.homepage = %q{http://github.com/prepor/rev_memcache}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.5}
36
+ s.summary = %q{Rev memcache client}
37
+ s.test_files = [
38
+ "examples/test.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<rev>, [">= 0"])
47
+ else
48
+ s.add_dependency(%q<rev>, [">= 0"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<rev>, [">= 0"])
52
+ end
53
+ end
54
+
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rev_memcache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Rudenko
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-19 00:00:00 +03:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rev
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Rev memcache client
26
+ email: ceo@prepor.ru
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - examples/test.rb
42
+ - lib/rev_memcache.rb
43
+ - lib/rev_memcache/deferrable.rb
44
+ - lib/t.rb
45
+ - rev_memcache.gemspec
46
+ has_rdoc: true
47
+ homepage: http://github.com/prepor/rev_memcache
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --charset=UTF-8
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Rev memcache client
74
+ test_files:
75
+ - examples/test.rb