rod 0.6.0
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/Gemfile +2 -0
- data/README +144 -0
- data/Rakefile +58 -0
- data/changelog.txt +99 -0
- data/lib/rod.rb +21 -0
- data/lib/rod/abstract_database.rb +369 -0
- data/lib/rod/collection_proxy.rb +72 -0
- data/lib/rod/constants.rb +32 -0
- data/lib/rod/database.rb +598 -0
- data/lib/rod/exception.rb +56 -0
- data/lib/rod/join_element.rb +63 -0
- data/lib/rod/model.rb +926 -0
- data/lib/rod/segmented_index.rb +85 -0
- data/lib/rod/string_element.rb +37 -0
- data/lib/rod/string_ex.rb +14 -0
- data/rod.gemspec +28 -0
- metadata +167 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
module Rod
|
2
|
+
# Class implementing segmented index, i.e. an index which allows for
|
3
|
+
# lazy loading of its pieces.
|
4
|
+
class SegmentedIndex
|
5
|
+
# Creats the index with given +path+ and number of buckets (+buckets_count+).
|
6
|
+
def initialize(path,buckets_count=1001)
|
7
|
+
@path = path
|
8
|
+
@buckets_count = buckets_count
|
9
|
+
@buckets_ceil = Math::log2(buckets_count).ceil
|
10
|
+
@buckets = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Stores the index at @path. Assumes the path exists.
|
14
|
+
def save
|
15
|
+
unless File.exist?(@path)
|
16
|
+
Dir.mkdir(@path)
|
17
|
+
end
|
18
|
+
@buckets.each do |bucket_number,hash|
|
19
|
+
File.open(path_for(bucket_number),"w") do |out|
|
20
|
+
out.puts(Marshal.dump(hash))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return value for the key.
|
26
|
+
def [](key)
|
27
|
+
bucket_number = bucket_for(key)
|
28
|
+
load_bucket(bucket_number) unless @buckets[bucket_number]
|
29
|
+
@buckets[bucket_number][key]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Set the value for the key.
|
33
|
+
def []=(key,value)
|
34
|
+
bucket_number = bucket_for(key)
|
35
|
+
load_bucket(bucket_number) unless @buckets[bucket_number]
|
36
|
+
@buckets[bucket_number][key] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
def each
|
40
|
+
if block_given?
|
41
|
+
@buckets.each do |bucket_number,hash|
|
42
|
+
hash.each do |key,value|
|
43
|
+
yield key, value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
else
|
47
|
+
enum_for(:each)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
def bucket_for(key)
|
53
|
+
case key
|
54
|
+
when NilClass
|
55
|
+
1 % @buckets_count
|
56
|
+
when TrueClass
|
57
|
+
2 % @buckets_count
|
58
|
+
when FalseClass
|
59
|
+
3 % @buckets_count
|
60
|
+
when String
|
61
|
+
key.sum(@buckets_ceil) % @buckets_count
|
62
|
+
when Integer
|
63
|
+
key % @buckets_count
|
64
|
+
when Float
|
65
|
+
(key.numerator - key.denominator) % @buckets_count
|
66
|
+
else
|
67
|
+
raise RodException.new("Object of type '#{key.class}' not supported as a key of segmented index!")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def path_for(bucket_number)
|
72
|
+
"#{@path}#{bucket_number}.idx"
|
73
|
+
end
|
74
|
+
|
75
|
+
def load_bucket(bucket_number)
|
76
|
+
if File.exist?(path_for(bucket_number))
|
77
|
+
File.open(path_for(bucket_number)) do |input|
|
78
|
+
@buckets[bucket_number] = Marshal.load(input)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
@buckets[bucket_number] = {}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rod
|
2
|
+
class StringElement
|
3
|
+
def self.page_offsets
|
4
|
+
@page_offsets ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.typedef_struct
|
8
|
+
#"typedef struct {char value;} _string_element;"
|
9
|
+
""
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.struct_name
|
13
|
+
#"_string_element"
|
14
|
+
"char"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.path_for_data(path)
|
18
|
+
"#{path}#{self.struct_name}.dat"
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def self.layout
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.fields
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.build_structure
|
30
|
+
# does nothing, the structure is not needed
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.cache
|
34
|
+
@cache ||= SimpleWeakHash.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class String
|
2
|
+
def margin(n=0)
|
3
|
+
#d = /\A.*\n\s*(.)/.match( self )[1]
|
4
|
+
#d = /\A\s*(.)/.match( self)[1] unless d
|
5
|
+
d = ((/\A.*\n\s*(.)/.match(self)) ||
|
6
|
+
(/\A\s*(.)/.match(self)))[1]
|
7
|
+
return '' unless d
|
8
|
+
if n == 0
|
9
|
+
gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, '')
|
10
|
+
else
|
11
|
+
gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, ' ' * n)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/rod.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
$:.unshift "lib"
|
2
|
+
require 'rod/constants'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "rod"
|
6
|
+
s.version = Rod::VERSION
|
7
|
+
s.date = "#{Time.now}"
|
8
|
+
s.summary = "Ruby object database"
|
9
|
+
s.email = "apohllo@o2.pl"
|
10
|
+
#s.homepage = "http://wierzba.wzks.uj.edu.pl/~mag/dilp"
|
11
|
+
s.description = "Ruby object database is designed for large amount of data, whose structure rarely changes."
|
12
|
+
s.require_path = "lib"
|
13
|
+
s.has_rdoc = true
|
14
|
+
s.authors = ['Aleksander Pohl', 'Piotr Gurgul', 'Marcin Sieniek']
|
15
|
+
s.files = ["Rakefile", "rod.gemspec", 'lib/rod.rb', 'README',
|
16
|
+
'changelog.txt', 'Gemfile'] + Dir.glob("lib/**/*")
|
17
|
+
#s.test_files = Dir.glob("{test,spect}/**/*")
|
18
|
+
#s.rdoc_options = ["--main", "README.txt"]
|
19
|
+
#s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
20
|
+
s.add_dependency("RubyInline", [">= 3.8.3","< 4.0.0"])
|
21
|
+
s.add_dependency("english", [">= 0.5.0","< 0.6.0"])
|
22
|
+
s.add_dependency("activemodel", [">= 3.0.7","< 3.1.0"])
|
23
|
+
s.add_dependency("weak_hash", ["= 1.0.1"])
|
24
|
+
s.add_development_dependency("mocha", [">= 0.9.8","< 1.0.0"])
|
25
|
+
s.add_development_dependency("cucumber", [">= 0.9.4","< 0.10.0"])
|
26
|
+
s.add_development_dependency("rspec", [">= 2.2.0","< 2.3.0"])
|
27
|
+
end
|
28
|
+
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rod
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.6.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Aleksander Pohl
|
9
|
+
- Piotr Gurgul
|
10
|
+
- Marcin Sieniek
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
|
15
|
+
date: 2011-06-09 12:09:42 +02:00
|
16
|
+
default_executable:
|
17
|
+
dependencies:
|
18
|
+
- !ruby/object:Gem::Dependency
|
19
|
+
name: RubyInline
|
20
|
+
prerelease: false
|
21
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
22
|
+
none: false
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.8.3
|
27
|
+
- - <
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 4.0.0
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: english
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.5.0
|
41
|
+
- - <
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.6.0
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: activemodel
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.7
|
55
|
+
- - <
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 3.1.0
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id003
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: weak_hash
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - "="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.1
|
69
|
+
type: :runtime
|
70
|
+
version_requirements: *id004
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: mocha
|
73
|
+
prerelease: false
|
74
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 0.9.8
|
80
|
+
- - <
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.0
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id005
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: cucumber
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.9.4
|
94
|
+
- - <
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.10.0
|
97
|
+
type: :development
|
98
|
+
version_requirements: *id006
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: rspec
|
101
|
+
prerelease: false
|
102
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 2.2.0
|
108
|
+
- - <
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.3.0
|
111
|
+
type: :development
|
112
|
+
version_requirements: *id007
|
113
|
+
description: Ruby object database is designed for large amount of data, whose structure rarely changes.
|
114
|
+
email: apohllo@o2.pl
|
115
|
+
executables: []
|
116
|
+
|
117
|
+
extensions: []
|
118
|
+
|
119
|
+
extra_rdoc_files: []
|
120
|
+
|
121
|
+
files:
|
122
|
+
- Rakefile
|
123
|
+
- rod.gemspec
|
124
|
+
- lib/rod.rb
|
125
|
+
- README
|
126
|
+
- changelog.txt
|
127
|
+
- Gemfile
|
128
|
+
- lib/rod/segmented_index.rb
|
129
|
+
- lib/rod/model.rb
|
130
|
+
- lib/rod/database.rb
|
131
|
+
- lib/rod/abstract_database.rb
|
132
|
+
- lib/rod/join_element.rb
|
133
|
+
- lib/rod/constants.rb
|
134
|
+
- lib/rod/string_ex.rb
|
135
|
+
- lib/rod/exception.rb
|
136
|
+
- lib/rod/collection_proxy.rb
|
137
|
+
- lib/rod/string_element.rb
|
138
|
+
has_rdoc: true
|
139
|
+
homepage:
|
140
|
+
licenses: []
|
141
|
+
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: "0"
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: "0"
|
159
|
+
requirements: []
|
160
|
+
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 1.5.2
|
163
|
+
signing_key:
|
164
|
+
specification_version: 3
|
165
|
+
summary: Ruby object database
|
166
|
+
test_files: []
|
167
|
+
|