joshbuddy-tokyo_cache_cow 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -66,11 +66,11 @@ But <i>other_key</i> is still peachy.
66
66
  === Server
67
67
 
68
68
 
69
- >> ruby -rubygems runner.rb --help
69
+ >> tokyo_cache_cow --help
70
70
 
71
71
  --------------
72
72
 
73
- Usage: runner.rb [options]
73
+ Usage: tokyo_cache_cow [options]
74
74
  -p, --port[OPTIONAL] Port (default: 11211)
75
75
  -h, --host[OPTIONAL] Host (default: 0.0.0.0)
76
76
  --help Show this help message.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 1
3
- :major: 0
4
2
  :minor: 0
3
+ :patch: 2
4
+ :major: 0
data/bin/tokyo_cache_cow CHANGED
@@ -1,47 +1,6 @@
1
- require 'eventmachine'
2
- require 'optparse'
3
-
4
- $:.unshift File.join(File.dirname(__FILE__), '..')
5
- require 'lib/tokyo_cache_cow'
6
-
7
- options = {:port => '11211', :host => '0.0.0.0', :provider => 'tokyo_cabinet', :file => '/tmp/cache'}
8
- OptionParser.new do |opts|
9
- opts.banner = "Usage: runner.rb [options]"
10
-
11
- opts.on("-p[OPTIONAL]", "--port", "Port (default: #{options[:port]})") do |v|
12
- options[:port] = v
13
- end
14
-
15
- opts.on("-h[OPTIONAL]", "--host", "Host (default: #{options[:host]})") do |v|
16
- options[:host] = v
17
- end
18
-
19
- opts.on("-c[OPTIONAL]", "--cache-provider", "Cache provider (default: #{options[:provider]})") do |v|
20
- options[:provider] = v
21
- end
22
-
23
- opts.on("-f[OPTIONAL]", "--file", "File (default: #{options[:file]})") do |v|
24
- options[:file] = v
25
- end
26
-
27
- opts.on_tail("-h", "--help", "Show this help message.") { puts opts; exit }
28
-
29
- end.parse!
30
-
31
- trap("INT") { EM.stop; puts "moooooooo ya later" }
32
-
33
- if File.exists?(File.join(File.dirname(__FILE__), options[:provider]))
34
- require File.join(File.dirname(__FILE__), options[:provider])
35
- cache = $cache
36
- else
37
- require 'lib/tokyo_cache_cow/cache'
38
- cache = TokyoCacheCow::Cache.const_get("#{options[:provider]}_memcache".split('_').map{|e| e.capitalize}.join.to_sym).new(options[:file])
39
- end
40
-
41
- puts "Starting the tokyo cache cow"
42
- EM.run do
43
- EM.start_server(options[:host], options[:port], TokyoCacheCow::Server) do |c|
44
- c.cache = cache
45
- end
46
- end
1
+ #!/usr/bin/env ruby -rubygems
2
+ # Tokyo cache cow command line interface script.
3
+ # Run <tt>tokyo_cache_cow -h</tt> to get more usage.
4
+ require File.dirname(__FILE__) + '/../lib/tokyo_cache_cow'
47
5
 
6
+ TokyoCacheCow::Runner.new(ARGV).start!
@@ -1,4 +1,5 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
+ require 'tokyo_cache_cow/runner'
3
4
  require 'tokyo_cache_cow/server'
4
- require 'tokyo_cache_cow/providers'
5
+ require 'tokyo_cache_cow/cache'
@@ -1,6 +1,7 @@
1
1
  require 'yaml'
2
2
  require 'fileutils'
3
3
  require 'cgi'
4
+
4
5
  class TokyoCacheCow
5
6
  class Cache
6
7
  class FileMemcache < Base
@@ -13,10 +14,9 @@ class TokyoCacheCow
13
14
  end
14
15
  end
15
16
 
16
- def initialize(path)
17
- @path = path
18
- FileUtils.rm_rf(@path)
19
- FileUtils.mkdir_p(@path)
17
+ def initialize(options = {})
18
+ @path = options[:file] or raise('must supply file')
19
+ flush_all
20
20
  end
21
21
 
22
22
  def time_expired?(time)
@@ -70,7 +70,9 @@ class TokyoCacheCow
70
70
  end
71
71
 
72
72
  def flush_all
73
- FileUtils.rm(Dir.glob(File.join(@path, '*'))) and true
73
+ FileUtils.rm_rf(@path)
74
+ FileUtils.mkdir_p(@path)
75
+ true
74
76
  end
75
77
 
76
78
  def delete(key, expires = nil)
@@ -10,7 +10,7 @@ class TokyoCacheCow
10
10
  end
11
11
  end
12
12
 
13
- def initialize(file)
13
+ def initialize(options = {})
14
14
  @cache = {}
15
15
  end
16
16
 
@@ -108,9 +108,10 @@ class TokyoCacheCow
108
108
  q.searchout
109
109
  end
110
110
 
111
- def initialize(file)
111
+ def initialize(options = {})
112
112
  @cache = TDB::new # hash database
113
- @cache.open(file, TDB::OWRITER | TDB::OCREAT | TDB::OTRUNC)
113
+ options[:file] ?
114
+ @cache.open(options[:file], TDB::OWRITER | TDB::OCREAT | TDB::OTRUNC) : raise('must supply file')
114
115
  @cache.setxmsiz(500_000_000)
115
116
  end
116
117
 
@@ -0,0 +1,110 @@
1
+ require 'eventmachine'
2
+ require 'optparse'
3
+
4
+ class TokyoCacheCow
5
+ class Runner
6
+
7
+ attr_reader :options
8
+
9
+ def initialize(argv)
10
+ @argv = argv
11
+ # Default options values
12
+ @options = {
13
+ :chdir => Dir.pwd,
14
+ :address => '0.0.0.0',
15
+ :port => Server::DefaultPort,
16
+ :class => 'TokyoCacheCow::Cache::TokyoCabinetMemcache',
17
+ :require => [],
18
+ :file => '/tmp/tcc-cache',
19
+ :pid => '/tmp/tcc.pid',
20
+ :special_delete_prefix => nil,
21
+ :daemonize => false
22
+ }
23
+
24
+ parse!
25
+ end
26
+
27
+ def parser
28
+ OptionParser.new do |opts|
29
+ opts.banner = "Usage: tokyo_cache_cow [options]"
30
+
31
+ opts.separator ""
32
+ opts.separator "Options:"
33
+
34
+ opts.on("-p[OPTIONAL]", "--port", "Port (default: #{options[:port]})") do |v|
35
+ options[:port] = v
36
+ end
37
+
38
+ opts.on("-a[OPTIONAL]", "--address", "Address (default: #{options[:address]})") do |v|
39
+ options[:address] = v
40
+ end
41
+
42
+ opts.on("-c[OPTIONAL]", "--class", "Cache provider class (default: #{options[:class]})") do |v|
43
+ options[:provider] = v
44
+ end
45
+
46
+ opts.on("-r[OPTIONAL]", "--require", "require") do |v|
47
+ options[:require] << v
48
+ end
49
+
50
+ opts.on("-f[OPTIONAL]", "--file", "File (default: #{options[:file]})") do |v|
51
+ options[:file] = v
52
+ end
53
+
54
+ opts.on("-d[OPTIONAL]", "--daemonize", "Daemonize (default: #{options[:daemonize]})") do |v|
55
+ options[:daemonize] = true
56
+ end
57
+
58
+ opts.on("-P[OPTIONAL]", "--pid", "Pid file (default: #{options[:pid]})") do |v|
59
+ options[:pid] = true
60
+ end
61
+
62
+ opts.on("-m[OPTIONAL]", "--matcher", "Special flag for doing matched deletes (not enabled by default)") do |v|
63
+ options[:special_delete_char] = v
64
+ end
65
+
66
+ opts.on_tail("-h", "--help", "Show this help message.") { puts opts; exit }
67
+
68
+ end
69
+ end
70
+
71
+ def parse!
72
+ parser.parse!(@argv)
73
+ end
74
+
75
+ def start!
76
+ @options[:require].each {|r| require r}
77
+
78
+ clazz = @options[:class].to_s.split('::').inject(Kernel) do |parent, mod|
79
+ parent.const_get(mod)
80
+ end
81
+
82
+
83
+ address = @options[:address]
84
+ port = @options[:port]
85
+ special_delete_char = @options[:special_delete_char]
86
+ puts "Starting the tokyo cache cow #{address} #{port}"
87
+ pid = EM.fork_reactor do
88
+ cache = clazz.new(:file => @options[:file])
89
+ trap("INT") { EM.stop; puts "\nmoooooooo ya later"; exit(0)}
90
+ EM.run do
91
+ EM.start_server(address, port, TokyoCacheCow::Server) do |c|
92
+ c.cache = cache
93
+ c.special_delete_char = special_delete_char if special_delete_char
94
+ end
95
+ end
96
+ end
97
+
98
+ if @options[:daemonize]
99
+ File.open(options[:pid], 'w') {|f| f << pid}
100
+ Process.detach(pid)
101
+ else
102
+ trap("INT") { }
103
+ Process.wait(pid)
104
+ end
105
+
106
+ pid
107
+ end
108
+
109
+ end
110
+ end
@@ -4,6 +4,8 @@ require 'eventmachine'
4
4
  class TokyoCacheCow
5
5
  class Server < EventMachine::Connection
6
6
 
7
+ DefaultPort = 11211
8
+
7
9
  Terminator = "\r\n"
8
10
 
9
11
  #set
@@ -42,7 +44,7 @@ class TokyoCacheCow
42
44
 
43
45
  TerminatorRegex = /\r\n/
44
46
 
45
- attr_accessor :cache
47
+ attr_accessor :cache, :special_delete_char
46
48
 
47
49
  def send_client_error(message = "invalid arguments")
48
50
  send_data(ClientError % message.to_s)
@@ -68,7 +70,6 @@ class TokyoCacheCow
68
70
 
69
71
  def receive_data(data)
70
72
  ss = StringScanner.new(data)
71
-
72
73
  while part = ss.scan_until(TerminatorRegex)
73
74
  begin
74
75
  command_argument_separator_index = part.index(/\s/)
@@ -133,8 +134,14 @@ class TokyoCacheCow
133
134
  when DeleteCommand
134
135
  (key, noreply) = [$1.chomp, !$2.nil?]
135
136
  next unless validate_key(key)
136
- send_data @cache.delete(key) ?
137
- DeletedReply : NotDeletedReply
137
+ if special_delete_char && key.index(special_delete_char) == 0
138
+ key.slice!(0,special_delete_char.size)
139
+ @cache.delete_match(key)
140
+ send_data(DeletedReply)
141
+ else
142
+ send_data @cache.delete(key) ?
143
+ DeletedReply : NotDeletedReply
144
+ end
138
145
  end
139
146
  when 'delete_match'
140
147
  DeleteMatchCommand.match(args)
data/spec/cache_spec.rb CHANGED
@@ -2,11 +2,10 @@ require 'benchmark'
2
2
  require 'lib/tokyo_cache_cow/cache'
3
3
 
4
4
  {
5
- 'tokyo cabinet memcache' => TokyoCacheCow::Cache::TokyoCabinetMemcache.new('/tmp/tcc1'),
6
- 'hash memcache' => TokyoCacheCow::Cache::HashMemcache.new(nil),
7
- 'file memcache' => TokyoCacheCow::Cache::FileMemcache.new('/tmp/filecache')
5
+ 'tokyo cabinet memcache' => TokyoCacheCow::Cache::TokyoCabinetMemcache.new(:file => '/tmp/tcc1'),
6
+ 'hash memcache' => TokyoCacheCow::Cache::HashMemcache.new,
7
+ 'file memcache' => TokyoCacheCow::Cache::FileMemcache.new(:file => '/tmp/filecache')
8
8
  }.each do |name, cache|
9
-
10
9
  describe name do
11
10
 
12
11
  before(:each) do
data/spec/server_spec.rb CHANGED
@@ -1,11 +1,18 @@
1
1
  require 'rubygems'
2
2
  require 'memcached'
3
3
  require 'benchmark'
4
+ require 'lib/tokyo_cache_cow'
4
5
 
5
6
  cache = Memcached.new('127.0.0.1:11211')
6
7
 
7
8
  describe 'memcache server' do
8
9
 
10
+ before(:all) do
11
+ runner = TokyoCacheCow::Runner.new(['--daemonize'])
12
+ @pid = runner.start!
13
+ sleep(1)
14
+ end
15
+
9
16
  before(:each) do
10
17
  cache.flush
11
18
  end
@@ -20,5 +27,44 @@ describe 'memcache server' do
20
27
  cache.delete('asd')
21
28
  proc {cache.get('asd')}.should raise_error Memcached::NotFound
22
29
  end
30
+
31
+ after(:all) do
32
+ Process.kill('INT', @pid)
33
+ end
34
+
35
+
36
+ end
37
+
38
+ describe 'memcache server with special delete support' do
39
+
40
+ before(:all) do
41
+ runner = TokyoCacheCow::Runner.new(['--daemonize', '-m...'])
42
+ @pid = runner.start!
43
+ sleep(1)
44
+ end
45
+
46
+ before(:each) do
47
+ cache.flush
48
+ end
49
+
50
+ it "should delete match through special char " do
51
+ cache.set('asd123', "qweqweasd")
52
+ cache.set('asd456', "qweqweasd")
53
+ cache.set('asd678', "qweqweasd")
54
+ cache.set('qwe678', "qweqweasd")
55
+ cache.set('qwe679', "qweqweasd")
56
+ cache.delete('...asd')
57
+ proc {cache.get('asd123')}.should raise_error Memcached::NotFound
58
+ proc {cache.get('asd456')}.should raise_error Memcached::NotFound
59
+ proc {cache.get('asd678')}.should raise_error Memcached::NotFound
60
+ cache.delete('...qwe678')
61
+ proc {cache.get('qwe678')}.should raise_error Memcached::NotFound
62
+ cache.get('qwe679').should=='qweqweasd'
63
+ end
64
+
65
+ after(:all) do
66
+ Process.kill('INT', @pid)
67
+ end
68
+
23
69
 
24
70
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joshbuddy-tokyo_cache_cow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Hull
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-21 00:00:00 -07:00
12
+ date: 2009-04-30 00:00:00 -07:00
13
13
  default_executable: tokyo_cache_cow
14
14
  dependencies: []
15
15
 
@@ -33,6 +33,7 @@ files:
33
33
  - lib/tokyo_cache_cow/cache/tokyo_cabinet_memcache.rb
34
34
  - lib/tokyo_cache_cow/cache.rb
35
35
  - lib/tokyo_cache_cow/providers.rb
36
+ - lib/tokyo_cache_cow/runner.rb
36
37
  - lib/tokyo_cache_cow/server.rb
37
38
  - lib/tokyo_cache_cow.rb
38
39
  - spec/cache_spec.rb