lorentz 0.0.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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create --install maglev-26436@lorentz
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in lorentz.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'rspec'
8
+ end
data/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # Lorentz
2
+
3
+ Redis on MagLev
4
+
5
+ ## Why?
6
+
7
+ Because it's \_why day, \_why day, gotta write a hack it's \_why day!
8
+
9
+ ## What's implemented so far?
10
+
11
+ * set
12
+ * get
13
+ * exists
14
+ * del
15
+ * keys (with glob pattern)
16
+ * rename
17
+ * renamenx
18
+ * strlen
19
+ * randomkey
20
+ * append
21
+
22
+ ## Inspiration
23
+
24
+ \_why of course! [Redis](http://redis.io) also. [ctoneal's strc](https://github.com/ctoneal/strc) is cool too but I want a real Redis within MagLev.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/lib/lorentz.rb ADDED
@@ -0,0 +1,38 @@
1
+ require "lorentz/version"
2
+ require "lorentz/exceptions"
3
+ require "lorentz/strings"
4
+ require "lorentz/keys"
5
+
6
+ class Lorentz
7
+
8
+ attr_reader :db
9
+ def initialize(opts={})
10
+ db_name = opts.delete(:db) || 0
11
+
12
+ @db = begin
13
+ ::Maglev::PERSISTENT_ROOT[:"lorentz_db_#{db_name}"] ||= {}
14
+ rescue
15
+ $stderr.puts "Maglev only"
16
+ exit
17
+ end
18
+ end
19
+ include Lorentz::Strings
20
+ include Lorentz::Keys
21
+
22
+ private
23
+ def save(&block)
24
+ begin
25
+ Maglev.abort_transaction
26
+ yield
27
+ Maglev.commit_transaction
28
+ rescue Maglev::CommitFailedException
29
+ $stderr.puts "I tried to save but I couldn't. Trying again."
30
+ redo
31
+ end
32
+ end
33
+
34
+ def run(&block)
35
+ Maglev.abort_transaction
36
+ yield
37
+ end
38
+ end
@@ -0,0 +1 @@
1
+ class LorentzException < StandardError; end
@@ -0,0 +1,32 @@
1
+ module Lorentz::Glob
2
+ # jacked from https://github.com/karottenreibe/joker
3
+ # & specifically http://karottenreibe.github.com/2009/12/03/inside-the-joker/
4
+ def compile(source, case_sensitive=false)
5
+ ptr = 0
6
+ compiled = '^'
7
+ while ptr < source.length
8
+ snip = source[ptr..ptr]
9
+ case snip
10
+ when '\\'
11
+ lookahead = source[ptr+1..ptr+1]
12
+ case snip
13
+ when '\\\\', '\\?', '\\*'
14
+ compiled << snip << lookahead
15
+ else
16
+ compiled << Regexp.quote(lookahead)
17
+ end
18
+ ptr += 1
19
+ when '?' then compiled << '.'
20
+ when '*' then compiled << '.*'
21
+ when '[' then compiled << '['
22
+ when ']' then compiled << ']'
23
+ else compiled << Regexp.quote(snip)
24
+ end
25
+ ptr += 1
26
+ end
27
+ compiled << '$'
28
+ Regexp.compile(compiled, case_sensitive)
29
+ end
30
+
31
+ module_function :compile
32
+ end
@@ -0,0 +1,53 @@
1
+ require 'lorentz/glob'
2
+
3
+ module Lorentz::Keys
4
+ include Lorentz::Glob
5
+
6
+ def exists(key)
7
+ run do
8
+ !!@db[key]
9
+ end
10
+ end
11
+
12
+ def del(*keys)
13
+ run do
14
+ keys.map{ |k| @db.delete(k) }.compact.size
15
+ end
16
+ end
17
+
18
+ def keys(pattern)
19
+ run do
20
+ @db.keys.grep(compile(pattern))
21
+ end
22
+ end
23
+
24
+ def rename(key, newkey)
25
+ if key == newkey
26
+ raise LorentzException, "newkey: #{newkey} must be different than key: #{key}"
27
+ end
28
+ raise LorentzException, "key: #{key} does not exist" unless exists(key)
29
+ save do
30
+ val = get(key)
31
+ del(key)
32
+ set(newkey, val)
33
+ end
34
+ end
35
+
36
+ def renamenx(key, newkey)
37
+ if key == newkey
38
+ raise LorentzException, "newkey: #{newkey} must be different than key: #{key}"
39
+ end
40
+ raise LorentzException, "key: #{key} does not exist" unless exists(key)
41
+ return 0 if exists(newkey)
42
+ rename(key, newkey)
43
+ return 1
44
+ end
45
+
46
+ def randomkey
47
+ return nil if @db.empty?
48
+ run do
49
+ @db.keys[rand(@db.keys.length)]
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,40 @@
1
+ module Lorentz::Strings
2
+ def set(key, value)
3
+ save do
4
+ @db[key] = value
5
+ return "OK"
6
+ end
7
+ end
8
+
9
+ def get(key)
10
+ run do
11
+ @db[key]
12
+ end
13
+ end
14
+
15
+ def strlen(key)
16
+ val = get(key)
17
+ return 0 unless val
18
+ if val.kind_of?(String)
19
+ return val.length
20
+ else
21
+ raise LorentzException, "The value stored at key: #{key} is not a String"
22
+ end
23
+ end
24
+
25
+ def append(key, value)
26
+ if exists(key)
27
+ old_value = get(key)
28
+ if old_value.is_a?(String)
29
+ new_value = old_value << value
30
+ set(key, new_value)
31
+ return new_value.length
32
+ else
33
+ raise LorentzException, "The value stored at key: #{key} is not a String"
34
+ end
35
+ else
36
+ set(key, "")
37
+ return "OK"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,7 @@
1
+ class Lorentz
2
+ class << self
3
+ def version
4
+ "0.0.1".freeze
5
+ end
6
+ end
7
+ end
data/lorentz.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "lorentz/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "lorentz"
7
+ s.version = Lorentz.version
8
+ s.authors = ["Jesse Cooke"]
9
+ s.email = ["jesse@jc00ke.com"]
10
+ s.homepage = "https://github.com/jc00ke/lorentz"
11
+ s.summary = %q{Take one Redis, stick it on MagLev}
12
+ s.description = %q{You know, for _why day!}
13
+ s.licenses = ['MIT']
14
+
15
+ s.rubyforge_project = "lorentz"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency 'rspec', '~> 2.6.0'
23
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lorentz::Glob do
4
+ let(:wild) { Lorentz::Glob.compile('Fairy?ake*') }
5
+ let(:wildi) { Lorentz::Glob.compile('Fairy?ake*\?', true) }
6
+ let(:wildc) { Lorentz::Glob.compile('Fairy[cf]ake[!\\]]') }
7
+
8
+ it 'should match correct strings' do
9
+ wild.should match('Fairycake')
10
+ wild.should match('Fairyfakes')
11
+ wild.should match('Fairylake is a cool place')
12
+ end
13
+
14
+ it 'should not match incorrect strings' do
15
+ wild.should_not match('Dairycake')
16
+ wild.should_not match('Fairysteakes')
17
+ wild.should_not match('fairycake')
18
+ end
19
+
20
+ it 'should match case insensitive' do
21
+ wildi.should match('FairyCake?')
22
+ wildi.should match('fairyfakes?')
23
+ wildi.should match('FairyLake IS A COOL Place?')
24
+ end
25
+
26
+ it 'should know about character classes' do
27
+ wildc.should match('Fairycake!')
28
+ wildc.should match('Fairyfake]')
29
+ end
30
+ end
@@ -0,0 +1,183 @@
1
+ require 'spec_helper'
2
+
3
+ #EXPIRE
4
+ #EXPIREAT
5
+ #MOVE
6
+ #OBJECT
7
+ #PERSIST
8
+ #SORT
9
+ #TTL
10
+ #TYPE
11
+
12
+ describe "keys" do
13
+ let(:lorentz) { Lorentz.new }
14
+
15
+ describe "#exists" do
16
+ context "when key exists" do
17
+ it "should return true" do
18
+ lorentz.set("chunky", "bacon")
19
+ lorentz.exists("chunky").should be_true
20
+ end
21
+ end
22
+
23
+ context "when key doesn't exist" do
24
+ it "should return false" do
25
+ lorentz.exists("chunky").should be_false
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ describe "#del" do
32
+ before do
33
+ lorentz.set("chunky", 0)
34
+ lorentz.set("bacon", 1)
35
+ end
36
+ it "should delete keys that exist" do
37
+ lorentz.del("chunky", "bacon", "pet ham")
38
+ lorentz.exists("chunky").should be_false
39
+ lorentz.exists("bacon").should be_false
40
+ lorentz.exists("pet ham").should be_false
41
+ end
42
+
43
+ it "should return the number of deleted keys" do
44
+ lorentz.del("chunky", "bacon", "pet ham").should eq(2)
45
+ end
46
+ end
47
+
48
+ describe "#keys" do
49
+ before do
50
+ lorentz.set("chunky", 0)
51
+ lorentz.set("bacon", 1)
52
+ lorentz.set("chunked", 2)
53
+ lorentz.set("thunk", 3)
54
+ end
55
+
56
+ it "should match 'unk'" do
57
+ keys = lorentz.keys('*unk*')
58
+ keys.should have(3).items
59
+ %w(chunky chunked thunk).each do |k|
60
+ keys.should include(k)
61
+ end
62
+ end
63
+
64
+ it "should return all" do
65
+ keys = lorentz.keys('*')
66
+ keys.should have(4).items
67
+ %w(chunky chunked thunk bacon).each do |k|
68
+ keys.should include(k)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "#rename" do
74
+
75
+ context "when key exists" do
76
+
77
+ before do
78
+ lorentz.set("chunky", "bacon")
79
+ end
80
+
81
+ context "and newkey exists" do
82
+ before do
83
+ lorentz.set("yummy", "snacks")
84
+ end
85
+
86
+ it "should overwrite newkey" do
87
+ lorentz.rename("chunky", "yummy")
88
+ lorentz.get("yummy").should == "bacon"
89
+ end
90
+ end
91
+
92
+ context "and newkey doesn't exist" do
93
+ it "it should set new key" do
94
+ lorentz.rename("chunky", "yummy")
95
+ lorentz.get("yummy").should == "bacon"
96
+ end
97
+ end
98
+
99
+ context "and newkey is the same" do
100
+ it "should raise a LorentzException" do
101
+ expect do
102
+ lorentz.rename("chunky", "chunky")
103
+ end.to raise_error(LorentzException)
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ context "when key doesn't exist" do
110
+ it "should raise a LorentzException" do
111
+ expect do
112
+ lorentz.rename("chunky", "yummy")
113
+ end.to raise_error(LorentzException)
114
+ end
115
+
116
+ end
117
+ end
118
+
119
+ describe "renamenx" do
120
+
121
+ context "when key exists" do
122
+
123
+ before do
124
+ lorentz.set("chunky", "bacon")
125
+ end
126
+
127
+ context "and newkey exists" do
128
+ it "should return 0" do
129
+ lorentz.set("funky", "cold medina")
130
+ lorentz.renamenx("chunky", "funky").should be_zero
131
+ end
132
+ end
133
+
134
+ context "and newkey doesn't exist" do
135
+ it "should return 1" do
136
+ lorentz.renamenx("chunky", "funky").should eq(1)
137
+ end
138
+ end
139
+
140
+ context "and newkey is the same" do
141
+ it "should raise a LorentzException" do
142
+ expect do
143
+ lorentz.rename("chunky", "chunky")
144
+ end.to raise_error(LorentzException)
145
+ end
146
+ end
147
+ end
148
+
149
+ context "when key doesn't exist" do
150
+ it "should raise a LorentzException" do
151
+ expect do
152
+ lorentz.renamenx("chunky", "yummy")
153
+ end.to raise_error(LorentzException)
154
+ end
155
+
156
+ end
157
+ end
158
+
159
+ describe "randomkey" do
160
+ context "database with some keys" do
161
+ before do
162
+ 1.upto(1000){ |i| lorentz.set(i, i) }
163
+ end
164
+
165
+ it "should return a random key" do
166
+ (1..100).to_a.inject([]) do |memo, i|
167
+ memo << lorentz.randomkey
168
+ end.uniq.should have_at_least(90).keys
169
+ end
170
+ end
171
+
172
+ context "empty database" do
173
+ before do
174
+ # delete in case... paranoid much?
175
+ ::Maglev::PERSISTENT_ROOT.delete(:lorentz_db_100)
176
+ end
177
+ it "should return nil" do
178
+ l = Lorentz.new(:db => :lorentz_db_100)
179
+ l.randomkey.should be_nil
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ #DECR
4
+ #DECRBY
5
+ #GETBIT
6
+ #GETRANGE
7
+ #GETSET
8
+ #INCR
9
+ #INCRBY
10
+ #MGET
11
+ #MSET
12
+ #MSETNX
13
+ #SETBIT
14
+ #SETEX
15
+ #SETNX
16
+ #SETRANGE
17
+
18
+ describe "strings" do
19
+ let(:lorentz) { Lorentz.new }
20
+
21
+ describe "#set" do
22
+ it "should set the key to the value" do
23
+ lorentz.set("chunky", 'bacon').should == "OK"
24
+ lorentz.db["chunky"].should eq("bacon")
25
+ end
26
+ end
27
+
28
+ describe "#setnx" do
29
+ context "when key exists" do
30
+ xit "should not set" do
31
+
32
+ end
33
+ end
34
+
35
+ context "when key doesn't exist" do
36
+ xit "should set" do
37
+
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "#get" do
43
+ context "when key exists" do
44
+ it "should return the value" do
45
+ lorentz.set("chunky", "bacon")
46
+ lorentz.get("chunky").should == "bacon"
47
+ end
48
+ end
49
+ it "should return nil if key doesn't exist" do
50
+ lorentz.get("chunky").should be_nil
51
+ end
52
+ end
53
+
54
+ describe "#append" do
55
+ context "when key exists" do
56
+ context "and is a string" do
57
+ before do
58
+ lorentz.set("chunky", "bacon")
59
+ end
60
+ it "should tack value on to end of string" do
61
+ lorentz.append("chunky", " is yummy")
62
+ lorentz.get("chunky").should == "bacon is yummy"
63
+ end
64
+ it "should return length of value" do
65
+ lorentz.append("chunky", " is yummy").should eq("bacon is yummy".length)
66
+ end
67
+ end
68
+
69
+ context "and is not a string" do
70
+ before do
71
+ lorentz.set("chunky", 1)
72
+ end
73
+
74
+ it "should raise an error" do
75
+ expect do
76
+ lorentz.append("chunky", "bacon")
77
+ end.to raise_error(LorentzException)
78
+ end
79
+ end
80
+ end
81
+
82
+ context "when key doesn't exist" do
83
+ it "should return 'OK'" do
84
+ lorentz.append("chunky", "bacon").should == "OK"
85
+ end
86
+ it "should set the key to be an empty string" do
87
+ lorentz.append("chunky", "bacon")
88
+ lorentz.get("chunky").should be_empty
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "#strlen" do
94
+ context "when key exists" do
95
+ before do
96
+ lorentz.set("chunky", "baconz")
97
+ lorentz.set("foo", ["bar"])
98
+ end
99
+ it "should return length of string value" do
100
+ lorentz.strlen("chunky").should eq(6)
101
+ end
102
+
103
+ it "should raise an error if value isn't a string" do
104
+ expect do
105
+ lorentz.strlen("foo")
106
+ end.to raise_error(LorentzException)
107
+ end
108
+ end
109
+
110
+ context "when key doesn't exist" do
111
+ it "should return 0" do
112
+ lorentz.strlen("chunky").should eq(0)
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lorentz do
4
+ context "default" do
5
+ its(:db) { should be_empty }
6
+ its(:db) { should be_a(Hash) }
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.require(:default, :test)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'lorentz'
13
+ require 'rspec'
14
+
15
+ RSpec.configure do |config|
16
+ config.before(:each) do
17
+ ::Maglev.abort_transaction
18
+ ::Maglev::PERSISTENT_ROOT.delete_if do |key, val|
19
+ key.to_s =~ /^lorentz_db_.*$/
20
+ end
21
+ ::Maglev.commit_transaction
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lorentz
3
+ version: !ruby/object:Gem::Version
4
+ hash: 856480538658449761
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jesse Cooke
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-23 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 2489593565405618356
30
+ segments:
31
+ - 2
32
+ - 6
33
+ - 0
34
+ version: 2.6.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: You know, for _why day!
38
+ email:
39
+ - jesse@jc00ke.com
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - .rvmrc
49
+ - Gemfile
50
+ - README.md
51
+ - Rakefile
52
+ - lib/lorentz.rb
53
+ - lib/lorentz/exceptions.rb
54
+ - lib/lorentz/glob.rb
55
+ - lib/lorentz/keys.rb
56
+ - lib/lorentz/strings.rb
57
+ - lib/lorentz/version.rb
58
+ - lorentz.gemspec
59
+ - spec/lorentz/glob_spec.rb
60
+ - spec/lorentz/keys_spec.rb
61
+ - spec/lorentz/strings_spec.rb
62
+ - spec/lorentz_spec.rb
63
+ - spec/spec_helper.rb
64
+ has_rdoc: true
65
+ homepage: https://github.com/jc00ke/lorentz
66
+ licenses:
67
+ - MIT
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 2002549777813010636
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 2002549777813010636
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ requirements: []
92
+
93
+ rubyforge_project: lorentz
94
+ rubygems_version: 1.5.2
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: Take one Redis, stick it on MagLev
98
+ test_files: []
99
+