strokedb 0.0.2.1 → 0.0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +18 -20
- data/bench.html +4001 -0
- data/bin/strokedb +14 -0
- data/examples/movies.rb +105 -0
- data/examples/movies2.rb +97 -0
- data/examples/strokewiki/README +28 -0
- data/examples/strokewiki/view/edit.xhtml +27 -0
- data/examples/strokewiki/view/new.xhtml +26 -0
- data/examples/strokewiki/view/pages.xhtml +27 -0
- data/examples/strokewiki/view/show.xhtml +40 -0
- data/examples/strokewiki/view/versions.xhtml +25 -0
- data/examples/strokewiki/wiki.rb +106 -0
- data/examples/todo.rb +92 -0
- data/lib/strokedb.rb +85 -0
- data/lib/{config → strokedb}/config.rb +14 -9
- data/lib/strokedb/console.rb +87 -0
- data/lib/strokedb/core_ext.rb +10 -0
- data/lib/{util/ext → strokedb/core_ext}/blank.rb +1 -1
- data/lib/{util/ext → strokedb/core_ext}/enumerable.rb +0 -0
- data/lib/{util/ext → strokedb/core_ext}/fixnum.rb +0 -0
- data/lib/strokedb/core_ext/float.rb +4 -0
- data/lib/{util/ext → strokedb/core_ext}/hash.rb +0 -0
- data/lib/strokedb/core_ext/infinity.rb +33 -0
- data/lib/strokedb/core_ext/kernel.rb +41 -0
- data/lib/strokedb/core_ext/object.rb +16 -0
- data/lib/{util/ext → strokedb/core_ext}/string.rb +28 -1
- data/lib/strokedb/core_ext/symbol.rb +13 -0
- data/lib/strokedb/data_structures.rb +5 -0
- data/lib/strokedb/data_structures/chunked_skiplist.rb +123 -0
- data/lib/{data_structures → strokedb/data_structures}/inverted_list.rb +0 -0
- data/lib/{data_structures → strokedb/data_structures}/point_query.rb +0 -0
- data/lib/strokedb/data_structures/simple_skiplist.rb +350 -0
- data/lib/{data_structures → strokedb/data_structures}/skiplist.rb +1 -1
- data/lib/{document → strokedb}/document.rb +180 -71
- data/lib/{document → strokedb/document}/callback.rb +0 -0
- data/lib/{document → strokedb/document}/delete.rb +2 -2
- data/lib/strokedb/document/dsl.rb +4 -0
- data/lib/{document → strokedb/document/dsl}/associations.rb +0 -0
- data/lib/{document → strokedb/document/dsl}/coercions.rb +0 -0
- data/lib/strokedb/document/dsl/meta_dsl.rb +7 -0
- data/lib/{document → strokedb/document/dsl}/validations.rb +26 -21
- data/lib/{document → strokedb/document/dsl}/virtualize.rb +0 -0
- data/lib/{document → strokedb/document}/meta.rb +92 -29
- data/lib/{document → strokedb/document}/slot.rb +17 -5
- data/lib/{document → strokedb/document}/util.rb +0 -0
- data/lib/{document → strokedb/document}/versions.rb +2 -2
- data/lib/strokedb/index.rb +2 -0
- data/lib/strokedb/nsurl.rb +24 -0
- data/lib/strokedb/store.rb +149 -0
- data/lib/strokedb/stores.rb +6 -0
- data/lib/{stores → strokedb/stores}/chainable_storage.rb +20 -14
- data/lib/strokedb/stores/file_storage.rb +118 -0
- data/lib/{stores/inverted_list_index → strokedb/stores}/inverted_list_file_storage.rb +50 -0
- data/lib/strokedb/stores/memory_storage.rb +80 -0
- data/lib/{stores → strokedb/stores}/remote_store.rb +10 -4
- data/lib/strokedb/sync.rb +4 -0
- data/lib/{sync → strokedb/sync}/chain_sync.rb +0 -0
- data/lib/{sync → strokedb/sync}/diff.rb +12 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/array.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/default.rb +0 -0
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/hash.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/string.rb +1 -1
- data/lib/{sync → strokedb/sync}/lamport_timestamp.rb +0 -0
- data/lib/{sync → strokedb/sync}/store_sync.rb +15 -7
- data/lib/strokedb/transaction.rb +78 -0
- data/lib/{util → strokedb}/util.rb +14 -7
- data/lib/strokedb/util/attach_dsl.rb +29 -0
- data/lib/{util → strokedb/util}/blankslate.rb +0 -0
- data/lib/strokedb/util/class_optimization.rb +93 -0
- data/lib/{util → strokedb/util}/inflect.rb +0 -0
- data/lib/strokedb/util/java_util.rb +13 -0
- data/lib/{util → strokedb/util}/lazy_array.rb +0 -0
- data/lib/{util → strokedb/util}/lazy_mapping_array.rb +4 -0
- data/lib/{util → strokedb/util}/lazy_mapping_hash.rb +0 -0
- data/lib/{util → strokedb/util}/serialization.rb +21 -0
- data/lib/strokedb/util/uuid.rb +159 -0
- data/lib/{util → strokedb/util}/xml.rb +0 -0
- data/lib/{view → strokedb}/view.rb +2 -2
- data/lib/strokedb/volumes.rb +5 -0
- data/lib/strokedb/volumes/archive_volume.rb +165 -0
- data/lib/strokedb/volumes/block_volume.rb +169 -0
- data/lib/strokedb/volumes/distributed_pointer.rb +43 -0
- data/lib/strokedb/volumes/fixed_length_skiplist_volume.rb +109 -0
- data/lib/strokedb/volumes/map_volume.rb +268 -0
- data/meta/MANIFEST +175 -0
- data/script/console +2 -70
- data/spec/integration/remote_store_spec.rb +70 -0
- data/spec/integration/search_spec.rb +76 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/lib/spec_helper.rb +1 -0
- data/spec/lib/strokedb/config_spec.rb +250 -0
- data/spec/lib/strokedb/core_ext/blank_spec.rb +20 -0
- data/spec/lib/strokedb/core_ext/extract_spec.rb +42 -0
- data/spec/lib/strokedb/core_ext/float_spec.rb +62 -0
- data/spec/lib/strokedb/core_ext/infinity_spec.rb +40 -0
- data/spec/lib/strokedb/core_ext/spec_helper.rb +1 -0
- data/spec/lib/strokedb/core_ext/string_spec.rb +25 -0
- data/spec/lib/strokedb/core_ext/symbol_spec.rb +8 -0
- data/spec/lib/strokedb/data_structures/chunked_skiplist_spec.rb +144 -0
- data/spec/lib/strokedb/data_structures/inverted_list_spec.rb +172 -0
- data/spec/lib/strokedb/data_structures/simple_skiplist_spec.rb +200 -0
- data/spec/lib/strokedb/data_structures/skiplist_spec.rb +253 -0
- data/spec/lib/strokedb/data_structures/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/associations_spec.rb +319 -0
- data/spec/lib/strokedb/document/callbacks_spec.rb +134 -0
- data/spec/lib/strokedb/document/coercions_spec.rb +110 -0
- data/spec/lib/strokedb/document/document_spec.rb +1063 -0
- data/spec/lib/strokedb/document/meta_meta_spec.rb +30 -0
- data/spec/lib/strokedb/document/meta_spec.rb +435 -0
- data/spec/lib/strokedb/document/metaslot_spec.rb +43 -0
- data/spec/lib/strokedb/document/slot_spec.rb +130 -0
- data/spec/lib/strokedb/document/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/validations_spec.rb +1081 -0
- data/spec/lib/strokedb/document/virtualize_spec.rb +80 -0
- data/spec/lib/strokedb/nsurl_spec.rb +73 -0
- data/spec/lib/strokedb/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/chained_storages_spec.rb +116 -0
- data/spec/lib/strokedb/stores/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/store_spec.rb +201 -0
- data/spec/lib/strokedb/stores/transaction_spec.rb +107 -0
- data/spec/lib/strokedb/sync/chain_sync_spec.rb +43 -0
- data/spec/lib/strokedb/sync/diff_spec.rb +111 -0
- data/spec/lib/strokedb/sync/lamport_timestamp_spec.rb +174 -0
- data/spec/lib/strokedb/sync/slot_diff_spec.rb +164 -0
- data/spec/lib/strokedb/sync/spec_helper.rb +1 -0
- data/spec/lib/strokedb/sync/store_sync_spec.rb +181 -0
- data/spec/lib/strokedb/sync/stroke_diff/array_spec.rb +97 -0
- data/spec/lib/strokedb/sync/stroke_diff/complex_spec.rb +58 -0
- data/spec/lib/strokedb/sync/stroke_diff/hash_spec.rb +144 -0
- data/spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb +23 -0
- data/spec/lib/strokedb/sync/stroke_diff/spec_helper.rb +25 -0
- data/spec/lib/strokedb/sync/stroke_diff/string_spec.rb +61 -0
- data/spec/lib/strokedb/util/attach_dsl_spec.rb +45 -0
- data/spec/lib/strokedb/util/inflect_spec.rb +14 -0
- data/spec/lib/strokedb/util/lazy_array_spec.rb +157 -0
- data/spec/lib/strokedb/util/lazy_mapping_array_spec.rb +174 -0
- data/spec/lib/strokedb/util/lazy_mapping_hash_spec.rb +92 -0
- data/spec/lib/strokedb/util/spec_helper.rb +1 -0
- data/spec/lib/strokedb/util/uuid_spec.rb +46 -0
- data/spec/lib/strokedb/view_spec.rb +228 -0
- data/spec/lib/strokedb/volumes/archive_volume_spec.rb +105 -0
- data/spec/lib/strokedb/volumes/block_volume_spec.rb +100 -0
- data/spec/lib/strokedb/volumes/distributed_pointer_spec.rb +14 -0
- data/spec/lib/strokedb/volumes/fixed_length_skiplist_volume_spec.rb +177 -0
- data/spec/lib/strokedb/volumes/map_volume_spec.rb +172 -0
- data/spec/lib/strokedb/volumes/spec_helper.rb +1 -0
- data/spec/regression/docref_spec.rb +94 -0
- data/spec/regression/meta_spec.rb +23 -0
- data/spec/regression/spec_helper.rb +1 -0
- data/spec/regression/sync_spec.rb +36 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/temp/storages/TIMESTAMP +1 -0
- data/spec/temp/storages/UUID +1 -0
- data/spec/temp/storages/database-sync/TIMESTAMP +1 -0
- data/spec/temp/storages/database-sync/UUID +1 -0
- data/spec/temp/storages/database-sync/config +1 -0
- data/spec/temp/storages/database-sync/file/LAST +1 -0
- data/spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av +0 -0
- data/spec/temp/storages/database-sync/file/uindex.wal +0 -0
- data/spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX +1 -0
- data/spec/temp/storages/inverted_list_storage/INVERTED_INDEX +0 -0
- data/strokedb.gemspec +120 -0
- data/task/benchmark.task +9 -0
- data/task/ditz.task +30 -0
- data/task/echoe.rb +17 -0
- data/task/rcov.task +50 -0
- data/task/rdoc.task +10 -0
- data/task/rspec.task +0 -0
- data/vendor/java_inline.rb +106 -0
- data/vendor/rbmodexcl/mrimodexcl.rb +82 -0
- data/vendor/rbmodexcl/rbmodexcl.rb +5 -0
- data/vendor/rbmodexcl/rbxmodexcl.rb +48 -0
- data/vendor/rbmodexcl/spec/unextend_spec.rb +50 -0
- data/vendor/rbmodexcl/spec/uninclude_spec.rb +26 -0
- metadata +271 -79
- data/CONTRIBUTORS +0 -7
- data/CREDITS +0 -13
- data/bin/sdbc +0 -2
- data/lib/init.rb +0 -57
- data/lib/stores/inverted_list_index/inverted_list_index.rb +0 -49
- data/lib/stores/skiplist_store/chunk.rb +0 -119
- data/lib/stores/skiplist_store/chunk_storage.rb +0 -21
- data/lib/stores/skiplist_store/file_chunk_storage.rb +0 -44
- data/lib/stores/skiplist_store/memory_chunk_storage.rb +0 -37
- data/lib/stores/skiplist_store/skiplist_store.rb +0 -217
- data/lib/stores/store.rb +0 -5
- data/lib/sync/stroke_diff/stroke_diff.rb +0 -9
- data/lib/util/ext/object.rb +0 -8
- data/lib/util/java_util.rb +0 -9
- data/lib/util/trigger_partition.rb +0 -136
- data/strokedb.rb +0 -75
@@ -0,0 +1,149 @@
|
|
1
|
+
module StrokeDB
|
2
|
+
|
3
|
+
StoreInfo = Meta.new
|
4
|
+
|
5
|
+
class Store
|
6
|
+
include Enumerable
|
7
|
+
attr_accessor :storage, :index_store, :uuid
|
8
|
+
attr_reader :timestamp
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
@options = options.stringify_keys
|
12
|
+
@storage = @options['storage']
|
13
|
+
@index_store = @options['index']
|
14
|
+
initialize_files
|
15
|
+
autosync! unless @options['noautosync']
|
16
|
+
raise "Missing chunk storage" unless @storage
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(uuid, version=nil, opts = {}, &block)
|
20
|
+
@storage.find(uuid,version,opts.merge(:store => self),&block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def search(*args)
|
24
|
+
return [] unless @index_store
|
25
|
+
@index_store.find(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def include?(uuid,version=nil)
|
29
|
+
@storage.include?(uuid,version)
|
30
|
+
end
|
31
|
+
alias_method :contains?, :include?
|
32
|
+
|
33
|
+
def head_version(uuid)
|
34
|
+
@storage.head_version(uuid,{ :store => self })
|
35
|
+
end
|
36
|
+
|
37
|
+
def save!(doc)
|
38
|
+
next_timestamp!
|
39
|
+
storage.save!(doc, timestamp)
|
40
|
+
#
|
41
|
+
if @index_store
|
42
|
+
if doc.previous_version
|
43
|
+
raw_pdoc = find(doc.uuid,doc.previous_version,:no_instantiation => true)
|
44
|
+
pdoc = Document.from_raw(self,raw_pdoc.freeze,:skip_callbacks => true)
|
45
|
+
pdoc.extend(VersionedDocument)
|
46
|
+
@index_store.delete(pdoc)
|
47
|
+
end
|
48
|
+
@index_store.insert(doc)
|
49
|
+
@index_store.save!
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def save_as_head!(doc)
|
54
|
+
@storage.save_as_head!(doc,timestamp)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
def each(options = {},&block)
|
60
|
+
@storage.each(options.merge(:store => self),&block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def next_timestamp!
|
64
|
+
@timestamp = timestamp.next
|
65
|
+
update_timestamp!
|
66
|
+
@timestamp
|
67
|
+
end
|
68
|
+
|
69
|
+
def uuid
|
70
|
+
return @uuid if @uuid
|
71
|
+
@uuid = Util.random_uuid
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def document
|
76
|
+
find(uuid) || StoreInfo.create!(self, :uuid => uuid)
|
77
|
+
end
|
78
|
+
|
79
|
+
def inspect
|
80
|
+
"#<Store #{uuid}>"
|
81
|
+
end
|
82
|
+
|
83
|
+
def autosync!
|
84
|
+
@autosync_mutex ||= Mutex.new
|
85
|
+
@autosync = nil if @autosync && !@autosync.status
|
86
|
+
at_exit { stop_autosync! }
|
87
|
+
@autosync ||= Thread.new do
|
88
|
+
until @stop_autosync
|
89
|
+
@autosync_mutex.synchronize { storage.sync_chained_storages! }
|
90
|
+
sleep(1)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def stop_autosync!
|
96
|
+
if @autosync_mutex
|
97
|
+
@autosync_mutex.synchronize { @stop_autosync = true; storage.sync_chained_storages! }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def path
|
102
|
+
@options['path']
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def initialize_files
|
109
|
+
FileUtils.mkdir_p(path)
|
110
|
+
uuid_file = File.join(path,'UUID')
|
111
|
+
timestamp_file = File.join(path,'TIMESTAMP')
|
112
|
+
|
113
|
+
if File.exists?(uuid_file)
|
114
|
+
@uuid = IO.read(uuid_file)
|
115
|
+
else
|
116
|
+
File.open(uuid_file,'w') do |f|
|
117
|
+
f.write(uuid)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
if File.exists?(timestamp_file)
|
121
|
+
@timestamp = LTS.new(IO.read(timestamp_file).to_i,uuid)
|
122
|
+
else
|
123
|
+
@timestamp = LTS.zero(uuid)
|
124
|
+
update_timestamp!
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def update_timestamp!
|
129
|
+
timestamp_file = File.join(path,'TIMESTAMP')
|
130
|
+
File.open(timestamp_file,'w') do |f|
|
131
|
+
f.write(timestamp.counter)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
require 'stores/chainable_storage'
|
139
|
+
module StrokeDB
|
140
|
+
class Storage
|
141
|
+
include ChainableStorage
|
142
|
+
|
143
|
+
attr_accessor :authoritative_source
|
144
|
+
|
145
|
+
def initialize(opts={})
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
@@ -2,7 +2,7 @@ module StrokeDB
|
|
2
2
|
module ChainableStorage
|
3
3
|
def add_chained_storage!(storage)
|
4
4
|
@chained_storages ||= {}
|
5
|
-
@chained_storages[storage] = []
|
5
|
+
@chained_storages[storage] = [{},[]]
|
6
6
|
class <<self
|
7
7
|
alias :save! :save_with_chained_storages!
|
8
8
|
end
|
@@ -13,7 +13,7 @@ module StrokeDB
|
|
13
13
|
@chained_storages.delete(storage)
|
14
14
|
storage.remove_chained_storage!(self) if storage.has_chained_storage?(self)
|
15
15
|
if @chained_storages.keys.empty?
|
16
|
-
class <<self
|
16
|
+
class << self
|
17
17
|
alias :save! :save_without_chained_storages!
|
18
18
|
end
|
19
19
|
end
|
@@ -27,28 +27,34 @@ module StrokeDB
|
|
27
27
|
return unless @chained_storages.is_a?(Hash)
|
28
28
|
@chained_storages.each_pair do |storage, savings|
|
29
29
|
next if storage == origin
|
30
|
-
savings.each {|saving| storage.save!(saving, self)}
|
30
|
+
savings.last.each {|saving| storage.save!(saving[0], saving[1], saving[2], self)}
|
31
31
|
storage.sync_chained_storages!(self)
|
32
|
-
@chained_storages[storage] =
|
32
|
+
@chained_storages[storage] = [{},[]]
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def sync_chained_storage!(storage)
|
37
37
|
return unless @chained_storages.is_a?(Hash)
|
38
|
-
(@chained_storages[storage]||[]).each do |saving|
|
39
|
-
storage.save!(saving, self)
|
38
|
+
((@chained_storages[storage]||[]).last||[]).each do |saving|
|
39
|
+
storage.save!(saving[0], saving[1], saving[2], self)
|
40
40
|
end
|
41
|
-
@chained_storages[storage] = []
|
41
|
+
@chained_storages[storage] = [{},[]]
|
42
42
|
end
|
43
43
|
|
44
|
-
def save_without_chained_storages!(
|
45
|
-
perform_save!(
|
44
|
+
def save_without_chained_storages!(document, timestamp, options = {},source=nil)
|
45
|
+
perform_save!(document, timestamp, options)
|
46
46
|
end
|
47
47
|
|
48
|
-
def save_with_chained_storages!(
|
49
|
-
perform_save!(
|
50
|
-
(@chained_storages||{}).each_pair do |storage,
|
51
|
-
|
48
|
+
def save_with_chained_storages!(document, timestamp, options = {},source=nil)
|
49
|
+
perform_save!(document, timestamp, options)
|
50
|
+
(@chained_storages||{}).each_pair do |storage, accumulator|
|
51
|
+
next if storage == source
|
52
|
+
hsh = [document,timestamp,options].hash
|
53
|
+
hashes, savings = accumulator
|
54
|
+
unless hashes.has_key?(hsh) # TODO: here we had a bug (storage == document), spec it
|
55
|
+
hashes[hsh] = true
|
56
|
+
savings << [document,timestamp,options]
|
57
|
+
end
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module StrokeDB
|
2
|
+
class FileStorage < Storage
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
@options = options.stringify_keys
|
6
|
+
initialize_files
|
7
|
+
end
|
8
|
+
|
9
|
+
def save_as_head!(document, timestamp)
|
10
|
+
write(document.uuid, document, timestamp)
|
11
|
+
end
|
12
|
+
|
13
|
+
def find(uuid, version=nil, opts = {}, &block)
|
14
|
+
uuid_version = uuid + (version ? ".#{version}" : "")
|
15
|
+
key = uuid.to_raw_uuid + (version ? version.to_raw_uuid : RAW_FULL_UUID)
|
16
|
+
if (ptr = @uindex.find(key)) && (ptr != "\x00" * 20) # no way ptr will be zero
|
17
|
+
raw_doc = StrokeDB::deserialize(read_at_ptr(ptr))[0]
|
18
|
+
unless opts[:no_instantiation]
|
19
|
+
doc = Document.from_raw(opts[:store], raw_doc.freeze, &block) # FIXME: there should be a better source for store (probably)
|
20
|
+
doc.extend(VersionedDocument) if version
|
21
|
+
doc
|
22
|
+
else
|
23
|
+
raw_doc
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def include?(uuid,version=nil)
|
29
|
+
!!find(uuid,version,:no_instantiation => true)
|
30
|
+
end
|
31
|
+
# using #include? to match with Array, but #contains sounds much nicer
|
32
|
+
alias_method :contains?, :include?
|
33
|
+
|
34
|
+
def head_version(uuid, opts = {})
|
35
|
+
if doc = find(uuid,nil,opts.merge({ :no_instantiation => true }))
|
36
|
+
doc['version']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def each(options = {})
|
41
|
+
after = options[:after_timestamp]
|
42
|
+
include_versions = options[:include_versions]
|
43
|
+
@container.each do |key, value|
|
44
|
+
next if after && (value[1] <= after)
|
45
|
+
if uuid_match = key.match(/^#{UUID_RE}$/) || (include_versions && uuid_match = key.match(/#{UUID_RE}./) )
|
46
|
+
yield Document.from_raw(options[:store],value[0])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def perform_save!(document, timestamp, options = {})
|
52
|
+
position = @archive.insert(StrokeDB::serialize([document,timestamp.counter]))
|
53
|
+
ptr = DistributedPointer.pack(@archive.raw_uuid,position)
|
54
|
+
uuid = document.raw_uuid
|
55
|
+
@uindex.insert(uuid + RAW_FULL_UUID, ptr) if options[:head] || !document.is_a?(VersionedDocument)
|
56
|
+
@uindex.insert(uuid + document.version.to_raw_uuid, ptr) unless options[:head]
|
57
|
+
rescue ArchiveVolume::VolumeCapacityExceeded
|
58
|
+
create_new_archive!
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_new_archive!
|
62
|
+
@archive = ArchiveVolume.new(:path => @options['path'])
|
63
|
+
File.open(File.join(@options['path'],'LAST'),'w') do |f|
|
64
|
+
f.write(@archive.uuid)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def last_archive_uuid
|
69
|
+
last_filename = File.join(@options['path'],'LAST')
|
70
|
+
if File.exists?(last_filename)
|
71
|
+
IO.read(last_filename)
|
72
|
+
else
|
73
|
+
uuid = Util.random_uuid
|
74
|
+
File.open(last_filename,'w') do |f|
|
75
|
+
f.write(uuid)
|
76
|
+
end
|
77
|
+
uuid
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def read_at_ptr(ptr)
|
82
|
+
dptr = DistributedPointer.unpack(ptr)
|
83
|
+
volume_uuid = dptr.volume_uuid
|
84
|
+
if volume_uuid == @archive.uuid.to_raw_uuid
|
85
|
+
@archive.read(dptr.offset)
|
86
|
+
else
|
87
|
+
archive = ArchiveVolume.new(:path => @options['path'], :uuid => volume_uuid)
|
88
|
+
result = archive.read(dptr.offset)
|
89
|
+
archive.close!
|
90
|
+
result
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def path
|
95
|
+
@options['path']
|
96
|
+
end
|
97
|
+
|
98
|
+
def clear!
|
99
|
+
FileUtils.rm_rf(@options['path'])
|
100
|
+
initialize_files
|
101
|
+
end
|
102
|
+
|
103
|
+
def close!
|
104
|
+
@archive.close!
|
105
|
+
@uindex.close!
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def initialize_files
|
112
|
+
FileUtils.mkdir_p(@options['path'])
|
113
|
+
@archive = ArchiveVolume.new(:path => @options['path'], :uuid => last_archive_uuid)
|
114
|
+
@uindex = FixedLengthSkiplistVolume.new(:path => File.join(@options['path'],'uindex'), :key_length => 32 , :value_length => 20)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
@@ -53,4 +53,54 @@ module StrokeDB
|
|
53
53
|
"#{@path}/INVERTED_INDEX"
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
class InvertedListIndex
|
60
|
+
attr_accessor :storage, :document_store
|
61
|
+
def initialize(storage)
|
62
|
+
@storage = storage
|
63
|
+
@list = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_uuids(*args)
|
67
|
+
list.find(*args)
|
68
|
+
end
|
69
|
+
|
70
|
+
def find(*args)
|
71
|
+
find_uuids(*args).map do |uuid|
|
72
|
+
@document_store.find(uuid)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def insert(doc)
|
77
|
+
slots = indexable_slots_for_doc(doc)
|
78
|
+
q = PointQuery.new(slots)
|
79
|
+
list.insert(q.slots, doc.uuid)
|
80
|
+
end
|
81
|
+
|
82
|
+
def delete(doc)
|
83
|
+
slots = indexable_slots_for_doc(doc)
|
84
|
+
q = PointQuery.new(slots)
|
85
|
+
list.delete(q.slots, doc.uuid)
|
86
|
+
end
|
87
|
+
|
88
|
+
def save!
|
89
|
+
@storage.save!(list)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def indexable_slots_for_doc(doc)
|
95
|
+
raw_slots = doc.to_raw
|
96
|
+
nkeys = doc.meta['non_indexable_slots']
|
97
|
+
nkeys.each{|nk| raw_slots.delete(nk) } if nkeys
|
98
|
+
raw_slots
|
99
|
+
end
|
100
|
+
|
101
|
+
def list
|
102
|
+
@list ||= @storage.find_list
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
56
106
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module StrokeDB
|
2
|
+
class MemoryStorage < Storage
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
@options = options.stringify_keys
|
6
|
+
clear!
|
7
|
+
end
|
8
|
+
|
9
|
+
def save_as_head!(document, timestamp)
|
10
|
+
save!(document,timestamp, :head => true)
|
11
|
+
end
|
12
|
+
|
13
|
+
def find(uuid, version=nil, opts = {},&block)
|
14
|
+
uuid_version = uuid + (version ? ".#{version}" : "")
|
15
|
+
unless raw_doc = read(uuid_version)
|
16
|
+
authoritative_source.find(uuid,version,opts,&block) if authoritative_source
|
17
|
+
else
|
18
|
+
unless opts[:no_instantiation]
|
19
|
+
doc = Document.from_raw(opts[:store], raw_doc.freeze, &block) # FIXME: there should be a better source for store (probably)
|
20
|
+
doc.extend(VersionedDocument) if version
|
21
|
+
doc
|
22
|
+
else
|
23
|
+
raw_doc
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def include?(uuid,version=nil)
|
29
|
+
uuid_version = uuid + (version ? ".#{version}" : "")
|
30
|
+
!@container.find(uuid_version).nil?
|
31
|
+
end
|
32
|
+
alias_method :contains?, :include?
|
33
|
+
|
34
|
+
def head_version(uuid, opts = {})
|
35
|
+
if doc = find(uuid,nil, opts)
|
36
|
+
doc.version
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def each(options = {})
|
41
|
+
after = options[:after_timestamp]
|
42
|
+
include_versions = options[:include_versions]
|
43
|
+
@container.each do |key, value|
|
44
|
+
next if after && (value[1] <= after)
|
45
|
+
if uuid_match = key.match(/^#{UUID_RE}$/) || (include_versions && uuid_match = key.match(/#{UUID_RE}./) )
|
46
|
+
yield Document.from_raw(options[:store],value[0])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def perform_save!(document, timestamp, options = {})
|
52
|
+
uuid = document.uuid
|
53
|
+
version = document.version
|
54
|
+
raw_document = document.to_raw
|
55
|
+
uuid_version = uuid + (version ? ".#{version}" : "")
|
56
|
+
write(uuid, raw_document, timestamp) if options[:head] || !document.is_a?(VersionedDocument)
|
57
|
+
write(uuid_version, raw_document, timestamp) unless options[:head]
|
58
|
+
end
|
59
|
+
|
60
|
+
def clear!
|
61
|
+
@container = SimpleSkiplist.new
|
62
|
+
end
|
63
|
+
|
64
|
+
def close!
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def read(key)
|
70
|
+
if record = @container.find(key)
|
71
|
+
record.first
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def write(key, document, timestamp)
|
76
|
+
@container.insert(key, [document, timestamp.counter])
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|