lunar 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/examples/ohm.rb +23 -0
- data/lib/lunar.rb +12 -0
- data/lib/lunar/doc.rb +13 -0
- data/lib/lunar/index.rb +70 -0
- data/lib/lunar/scoring.rb +11 -0
- data/test/helper.rb +13 -0
- data/test/test_lunar.rb +4 -0
- data/test/test_lunar_document.rb +20 -0
- data/test/test_lunar_index.rb +174 -0
- data/test/test_lunar_scoring.rb +26 -0
- data/vendor/nest/nest.rb +7 -0
- data/vendor/redis/.gitignore +9 -0
- data/vendor/redis/LICENSE +20 -0
- data/vendor/redis/README.markdown +120 -0
- data/vendor/redis/Rakefile +75 -0
- data/vendor/redis/benchmarking/logging.rb +62 -0
- data/vendor/redis/benchmarking/pipeline.rb +44 -0
- data/vendor/redis/benchmarking/speed.rb +21 -0
- data/vendor/redis/benchmarking/suite.rb +24 -0
- data/vendor/redis/benchmarking/worker.rb +71 -0
- data/vendor/redis/bin/distredis +33 -0
- data/vendor/redis/examples/basic.rb +15 -0
- data/vendor/redis/examples/dist_redis.rb +43 -0
- data/vendor/redis/examples/incr-decr.rb +17 -0
- data/vendor/redis/examples/list.rb +26 -0
- data/vendor/redis/examples/pubsub.rb +25 -0
- data/vendor/redis/examples/sets.rb +36 -0
- data/vendor/redis/lib/edis.rb +3 -0
- data/vendor/redis/lib/redis.rb +496 -0
- data/vendor/redis/lib/redis/client.rb +265 -0
- data/vendor/redis/lib/redis/dist_redis.rb +118 -0
- data/vendor/redis/lib/redis/distributed.rb +460 -0
- data/vendor/redis/lib/redis/hash_ring.rb +131 -0
- data/vendor/redis/lib/redis/pipeline.rb +13 -0
- data/vendor/redis/lib/redis/raketasks.rb +1 -0
- data/vendor/redis/lib/redis/subscribe.rb +79 -0
- data/vendor/redis/profile.rb +22 -0
- data/vendor/redis/tasks/redis.tasks.rb +140 -0
- data/vendor/redis/test/db/.gitignore +1 -0
- data/vendor/redis/test/distributed_test.rb +1131 -0
- data/vendor/redis/test/redis_test.rb +1134 -0
- data/vendor/redis/test/test.conf +8 -0
- data/vendor/redis/test/test_helper.rb +113 -0
- metadata +127 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class LunarScoringTest < Test::Unit::TestCase
|
4
|
+
describe "scores of 'the quick brown fox jumps over the lazy dog'" do
|
5
|
+
should "return a hash of the words with score 1 except the, with score 2" do
|
6
|
+
scoring = Lunar::Scoring.new("the quick brown fox jumps over the lazy dog")
|
7
|
+
assert_equal 2, scoring.scores["the"]
|
8
|
+
assert_equal 1, scoring.scores["quick"]
|
9
|
+
assert_equal 1, scoring.scores["brown"]
|
10
|
+
assert_equal 1, scoring.scores["fox"]
|
11
|
+
assert_equal 1, scoring.scores["jumps"]
|
12
|
+
assert_equal 1, scoring.scores["over"]
|
13
|
+
assert_equal 1, scoring.scores["lazy"]
|
14
|
+
assert_equal 1, scoring.scores["dog"]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "scores of 'tHe qUick bRowN the quick brown THE QUICK BROWN'" do
|
19
|
+
should "return a hash of each of the words the quick brown with score 3" do
|
20
|
+
scoring = Lunar::Scoring.new('tHe qUick bRowN the quick brown THE QUICK BROWN')
|
21
|
+
assert_equal 3, scoring.scores['the']
|
22
|
+
assert_equal 3, scoring.scores['quick']
|
23
|
+
assert_equal 3, scoring.scores['brown']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/vendor/nest/nest.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Ezra Zygmuntowicz
|
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,120 @@
|
|
1
|
+
# redis-rb
|
2
|
+
|
3
|
+
A Ruby client library for the [Redis](http://code.google.com/p/redis) key-value store.
|
4
|
+
|
5
|
+
## A note about versions
|
6
|
+
|
7
|
+
Versions *1.0.x* target all versions of Redis. You have to use this one if you are using Redis < 1.2.
|
8
|
+
|
9
|
+
Version *2.0* is a big refactoring of the previous version and makes little effort to be
|
10
|
+
backwards-compatible when it shouldn't. It does not support Redis' original protocol, favoring the
|
11
|
+
new, binary-safe one. You should be using this version if you're running Redis 1.2+.
|
12
|
+
|
13
|
+
## Information about Redis
|
14
|
+
|
15
|
+
Redis is a key-value store with some interesting features:
|
16
|
+
|
17
|
+
1. It's fast.
|
18
|
+
2. Keys are strings but values are typed. Currently Redis supports strings, lists, sets, sorted sets and hashes. [Atomic operations](http://code.google.com/p/redis/wiki/CommandReference) can be done on all of these types.
|
19
|
+
|
20
|
+
See [the Redis homepage](http://code.google.com/p/redis/wiki/README) for more information.
|
21
|
+
|
22
|
+
## Getting started
|
23
|
+
|
24
|
+
You can connect to Redis by instantiating the `Redis` class:
|
25
|
+
|
26
|
+
require "redis"
|
27
|
+
|
28
|
+
redis = Redis.new
|
29
|
+
|
30
|
+
This assumes Redis was started with default values listening on `localhost`, port 6379. If you need to connect to a remote server or a different port, try:
|
31
|
+
|
32
|
+
redis = Redis.new(:host => "10.0.1.1", :port => 6380)
|
33
|
+
|
34
|
+
Once connected, you can start running commands against Redis:
|
35
|
+
|
36
|
+
>> redis.set "foo", "bar"
|
37
|
+
=> "OK"
|
38
|
+
|
39
|
+
>> redis.get "foo"
|
40
|
+
=> "bar"
|
41
|
+
|
42
|
+
>> redis.sadd "users", "albert"
|
43
|
+
=> true
|
44
|
+
|
45
|
+
>> redis.sadd "users", "bernard"
|
46
|
+
=> true
|
47
|
+
|
48
|
+
>> redis.sadd "users", "charles"
|
49
|
+
=> true
|
50
|
+
|
51
|
+
How many users?
|
52
|
+
|
53
|
+
>> redis.scard "users"
|
54
|
+
=> 3
|
55
|
+
|
56
|
+
Is `albert` a user?
|
57
|
+
|
58
|
+
>> redis.sismember "users", "albert"
|
59
|
+
=> true
|
60
|
+
|
61
|
+
Is `isabel` a user?
|
62
|
+
|
63
|
+
>> redis.sismember "users", "isabel"
|
64
|
+
=> false
|
65
|
+
|
66
|
+
Handle groups:
|
67
|
+
|
68
|
+
>> redis.sadd "admins", "albert"
|
69
|
+
=> true
|
70
|
+
|
71
|
+
>> redis.sadd "admins", "isabel"
|
72
|
+
=> true
|
73
|
+
|
74
|
+
Users who are also admins:
|
75
|
+
|
76
|
+
>> redis.sinter "users", "admins"
|
77
|
+
=> ["albert"]
|
78
|
+
|
79
|
+
Users who are not admins:
|
80
|
+
|
81
|
+
>> redis.sdiff "users", "admins"
|
82
|
+
=> ["bernard", "charles"]
|
83
|
+
|
84
|
+
Admins who are not users:
|
85
|
+
|
86
|
+
>> redis.sdiff "admins", "users"
|
87
|
+
=> ["isabel"]
|
88
|
+
|
89
|
+
All users and admins:
|
90
|
+
|
91
|
+
>> redis.sunion "admins", "users"
|
92
|
+
=> ["albert", "bernard", "charles", "isabel"]
|
93
|
+
|
94
|
+
|
95
|
+
## Storing objects
|
96
|
+
|
97
|
+
Redis only stores strings as values. If you want to store an object inside a key, you can use a serialization/deseralization mechanism like JSON:
|
98
|
+
|
99
|
+
>> redis.set "foo", [1, 2, 3].to_json
|
100
|
+
=> OK
|
101
|
+
|
102
|
+
>> JSON.parse(redis.get("foo"))
|
103
|
+
=> [1, 2, 3]
|
104
|
+
|
105
|
+
## Executing multiple commands atomically
|
106
|
+
|
107
|
+
You can use `MULTI/EXEC` to run arbitrary commands in an atomic fashion:
|
108
|
+
|
109
|
+
redis.multi do
|
110
|
+
redis.set "foo", "bar"
|
111
|
+
redis.incr "baz"
|
112
|
+
end
|
113
|
+
|
114
|
+
## More info
|
115
|
+
|
116
|
+
Check the [Redis Command Reference](http://code.google.com/p/redis/wiki/CommandReference) or check the tests to find out how to use this client.
|
117
|
+
|
118
|
+
## Contributing
|
119
|
+
|
120
|
+
[Fork the project](http://github.com/ezmobius/redis-rb) and send pull requests. You can also ask for help at `#redis` on Freenode.
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'tasks/redis.tasks'
|
5
|
+
|
6
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
7
|
+
require 'redis'
|
8
|
+
|
9
|
+
GEM = 'redis'
|
10
|
+
GEM_NAME = 'redis'
|
11
|
+
GEM_VERSION = Redis::VERSION
|
12
|
+
AUTHORS = ['Ezra Zygmuntowicz', 'Taylor Weibley', 'Matthew Clark', 'Brian McKinney', 'Salvatore Sanfilippo', 'Luca Guidi']
|
13
|
+
EMAIL = "ez@engineyard.com"
|
14
|
+
HOMEPAGE = "http://github.com/ezmobius/redis-rb"
|
15
|
+
SUMMARY = "Ruby client library for Redis, the key value storage server"
|
16
|
+
|
17
|
+
spec = Gem::Specification.new do |s|
|
18
|
+
s.name = GEM
|
19
|
+
s.version = GEM_VERSION
|
20
|
+
s.platform = Gem::Platform::RUBY
|
21
|
+
s.has_rdoc = true
|
22
|
+
s.extra_rdoc_files = ["LICENSE"]
|
23
|
+
s.summary = SUMMARY
|
24
|
+
s.description = s.summary
|
25
|
+
s.authors = AUTHORS
|
26
|
+
s.email = EMAIL
|
27
|
+
s.homepage = HOMEPAGE
|
28
|
+
s.require_path = 'lib'
|
29
|
+
s.autorequire = GEM
|
30
|
+
s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("{lib,tasks,spec}/**/*")
|
31
|
+
end
|
32
|
+
|
33
|
+
REDIS_DIR = File.expand_path(File.join("..", "test"), __FILE__)
|
34
|
+
REDIS_CNF = File.join(REDIS_DIR, "test.conf")
|
35
|
+
REDIS_PID = File.join(REDIS_DIR, "db", "redis.pid")
|
36
|
+
|
37
|
+
task :default => :run
|
38
|
+
|
39
|
+
desc "Run tests and manage server start/stop"
|
40
|
+
task :run => [:start, :test, :stop]
|
41
|
+
|
42
|
+
desc "Start the Redis server"
|
43
|
+
task :start do
|
44
|
+
unless File.exists?(REDIS_PID)
|
45
|
+
system "redis-server #{REDIS_CNF}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Stop the Redis server"
|
50
|
+
task :stop do
|
51
|
+
if File.exists?(REDIS_PID)
|
52
|
+
system "kill #{File.read(REDIS_PID)}"
|
53
|
+
system "rm #{REDIS_PID}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Rake::TestTask.new(:test) do |t|
|
58
|
+
t.pattern = 'test/**/*_test.rb'
|
59
|
+
end
|
60
|
+
|
61
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
62
|
+
pkg.gem_spec = spec
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "install the gem locally"
|
66
|
+
task :install => [:package] do
|
67
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "create a gemspec file"
|
71
|
+
task :gemspec do
|
72
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
73
|
+
file.puts spec.to_ruby
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Run with
|
2
|
+
#
|
3
|
+
# $ ruby -Ilib benchmarking/logging.rb
|
4
|
+
#
|
5
|
+
|
6
|
+
begin
|
7
|
+
require "bench"
|
8
|
+
rescue LoadError
|
9
|
+
$stderr.puts "`gem install bench` and try again."
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
require "redis"
|
14
|
+
require "logger"
|
15
|
+
|
16
|
+
def log(level, namespace = nil)
|
17
|
+
logger = (namespace || Kernel).const_get(:Logger).new("/dev/null")
|
18
|
+
logger.level = (namespace || Logger).const_get(level)
|
19
|
+
logger
|
20
|
+
end
|
21
|
+
|
22
|
+
def stress(redis)
|
23
|
+
redis.flushdb
|
24
|
+
|
25
|
+
n = (ARGV.shift || 2000).to_i
|
26
|
+
|
27
|
+
n.times do |i|
|
28
|
+
key = "foo:#{i}"
|
29
|
+
redis.set key, i
|
30
|
+
redis.get key
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
default = Redis.new
|
35
|
+
|
36
|
+
logging_redises = [
|
37
|
+
Redis.new(:logger => log(:DEBUG)),
|
38
|
+
Redis.new(:logger => log(:INFO)),
|
39
|
+
]
|
40
|
+
|
41
|
+
begin
|
42
|
+
require "log4r"
|
43
|
+
|
44
|
+
logging_redises += [
|
45
|
+
Redis.new(:logger => log(:DEBUG, Log4r)),
|
46
|
+
Redis.new(:logger => log(:INFO, Log4r)),
|
47
|
+
]
|
48
|
+
rescue LoadError
|
49
|
+
$stderr.puts "Log4r not installed. `gem install log4r` if you want to compare it against Ruby's Logger (spoiler: it's much faster)."
|
50
|
+
end
|
51
|
+
|
52
|
+
benchmark "Default options (no logger)" do
|
53
|
+
stress(default)
|
54
|
+
end
|
55
|
+
|
56
|
+
logging_redises.each do |redis|
|
57
|
+
benchmark "#{redis.client.logger.class} on #{Logger::SEV_LABEL[redis.client.logger.level]}" do
|
58
|
+
stress(redis)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
run 10
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
$:.push File.join(File.dirname(__FILE__), 'lib')
|
3
|
+
require 'redis'
|
4
|
+
|
5
|
+
times = 20000
|
6
|
+
|
7
|
+
@r = Redis.new#(:debug => true)
|
8
|
+
@r['foo'] = "The first line we sent to the server is some text"
|
9
|
+
|
10
|
+
Benchmark.bmbm do |x|
|
11
|
+
x.report("set") do
|
12
|
+
20000.times do |i|
|
13
|
+
@r["set#{i}"] = "The first line we sent to the server is some text"; @r["foo#{i}"]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
x.report("set (pipelined)") do
|
18
|
+
@r.pipelined do |pipeline|
|
19
|
+
20000.times do |i|
|
20
|
+
pipeline["set_pipelined#{i}"] = "The first line we sent to the server is some text"; @r["foo#{i}"]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
x.report("push+trim") do
|
26
|
+
20000.times do |i|
|
27
|
+
@r.push_head "push_trim#{i}", i
|
28
|
+
@r.list_trim "push_trim#{i}", 0, 30
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
x.report("push+trim (pipelined)") do
|
33
|
+
@r.pipelined do |pipeline|
|
34
|
+
20000.times do |i|
|
35
|
+
pipeline.push_head "push_trim_pipelined#{i}", i
|
36
|
+
pipeline.list_trim "push_trim_pipelined#{i}", 0, 30
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
@r.keys('*').each do |k|
|
43
|
+
@r.delete k
|
44
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Run with
|
2
|
+
#
|
3
|
+
# $ ruby -Ilib benchmarking/speed.rb
|
4
|
+
#
|
5
|
+
|
6
|
+
require "benchmark"
|
7
|
+
require "redis"
|
8
|
+
|
9
|
+
r = Redis.new
|
10
|
+
n = (ARGV.shift || 20000).to_i
|
11
|
+
|
12
|
+
elapsed = Benchmark.realtime do
|
13
|
+
# n sets, n gets
|
14
|
+
n.times do |i|
|
15
|
+
key = "foo#{i}"
|
16
|
+
r[key] = key * 10
|
17
|
+
r[key]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
puts '%.2f Kops' % (2 * n / 1000 / elapsed)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
def run_in_background(command)
|
4
|
+
fork { system command }
|
5
|
+
end
|
6
|
+
|
7
|
+
def with_all_segments(&block)
|
8
|
+
0.upto(9) do |segment_number|
|
9
|
+
block_size = 100000
|
10
|
+
start_index = segment_number * block_size
|
11
|
+
end_index = start_index + block_size - 1
|
12
|
+
block.call(start_index, end_index)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
#with_all_segments do |start_index, end_index|
|
17
|
+
# puts "Initializing keys from #{start_index} to #{end_index}"
|
18
|
+
# system "ruby worker.rb initialize #{start_index} #{end_index} 0"
|
19
|
+
#end
|
20
|
+
|
21
|
+
with_all_segments do |start_index, end_index|
|
22
|
+
run_in_background "ruby worker.rb write #{start_index} #{end_index} 10"
|
23
|
+
run_in_background "ruby worker.rb read #{start_index} #{end_index} 1"
|
24
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
BENCHMARK_ROOT = File.dirname(__FILE__)
|
2
|
+
REDIS_ROOT = File.join(BENCHMARK_ROOT, "..", "lib")
|
3
|
+
|
4
|
+
$: << REDIS_ROOT
|
5
|
+
require 'redis'
|
6
|
+
require 'benchmark'
|
7
|
+
|
8
|
+
def show_usage
|
9
|
+
puts <<-EOL
|
10
|
+
Usage: worker.rb [read:write] <start_index> <end_index> <sleep_msec>
|
11
|
+
EOL
|
12
|
+
end
|
13
|
+
|
14
|
+
def shift_from_argv
|
15
|
+
value = ARGV.shift
|
16
|
+
unless value
|
17
|
+
show_usage
|
18
|
+
exit -1
|
19
|
+
end
|
20
|
+
value
|
21
|
+
end
|
22
|
+
|
23
|
+
operation = shift_from_argv.to_sym
|
24
|
+
start_index = shift_from_argv.to_i
|
25
|
+
end_index = shift_from_argv.to_i
|
26
|
+
sleep_msec = shift_from_argv.to_i
|
27
|
+
sleep_duration = sleep_msec/1000.0
|
28
|
+
|
29
|
+
redis = Redis.new
|
30
|
+
|
31
|
+
case operation
|
32
|
+
when :initialize
|
33
|
+
|
34
|
+
start_index.upto(end_index) do |i|
|
35
|
+
redis[i] = 0
|
36
|
+
end
|
37
|
+
|
38
|
+
when :clear
|
39
|
+
|
40
|
+
start_index.upto(end_index) do |i|
|
41
|
+
redis.delete(i)
|
42
|
+
end
|
43
|
+
|
44
|
+
when :read, :write
|
45
|
+
|
46
|
+
puts "Starting to #{operation} at segment #{end_index + 1}"
|
47
|
+
|
48
|
+
loop do
|
49
|
+
t1 = Time.now
|
50
|
+
start_index.upto(end_index) do |i|
|
51
|
+
case operation
|
52
|
+
when :read
|
53
|
+
redis.get(i)
|
54
|
+
when :write
|
55
|
+
redis.incr(i)
|
56
|
+
else
|
57
|
+
raise "Unknown operation: #{operation}"
|
58
|
+
end
|
59
|
+
sleep sleep_duration
|
60
|
+
end
|
61
|
+
t2 = Time.now
|
62
|
+
|
63
|
+
requests_processed = end_index - start_index
|
64
|
+
time = t2 - t1
|
65
|
+
puts "#{t2.strftime("%H:%M")} [segment #{end_index + 1}] : Processed #{requests_processed} requests in #{time} seconds - #{(requests_processed/time).round} requests/sec"
|
66
|
+
end
|
67
|
+
|
68
|
+
else
|
69
|
+
raise "Unknown operation: #{operation}"
|
70
|
+
end
|
71
|
+
|