strokedb 0.0.2.1 → 0.0.2.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.
Files changed (192) hide show
  1. data/README +18 -20
  2. data/bench.html +4001 -0
  3. data/bin/strokedb +14 -0
  4. data/examples/movies.rb +105 -0
  5. data/examples/movies2.rb +97 -0
  6. data/examples/strokewiki/README +28 -0
  7. data/examples/strokewiki/view/edit.xhtml +27 -0
  8. data/examples/strokewiki/view/new.xhtml +26 -0
  9. data/examples/strokewiki/view/pages.xhtml +27 -0
  10. data/examples/strokewiki/view/show.xhtml +40 -0
  11. data/examples/strokewiki/view/versions.xhtml +25 -0
  12. data/examples/strokewiki/wiki.rb +106 -0
  13. data/examples/todo.rb +92 -0
  14. data/lib/strokedb.rb +85 -0
  15. data/lib/{config → strokedb}/config.rb +14 -9
  16. data/lib/strokedb/console.rb +87 -0
  17. data/lib/strokedb/core_ext.rb +10 -0
  18. data/lib/{util/ext → strokedb/core_ext}/blank.rb +1 -1
  19. data/lib/{util/ext → strokedb/core_ext}/enumerable.rb +0 -0
  20. data/lib/{util/ext → strokedb/core_ext}/fixnum.rb +0 -0
  21. data/lib/strokedb/core_ext/float.rb +4 -0
  22. data/lib/{util/ext → strokedb/core_ext}/hash.rb +0 -0
  23. data/lib/strokedb/core_ext/infinity.rb +33 -0
  24. data/lib/strokedb/core_ext/kernel.rb +41 -0
  25. data/lib/strokedb/core_ext/object.rb +16 -0
  26. data/lib/{util/ext → strokedb/core_ext}/string.rb +28 -1
  27. data/lib/strokedb/core_ext/symbol.rb +13 -0
  28. data/lib/strokedb/data_structures.rb +5 -0
  29. data/lib/strokedb/data_structures/chunked_skiplist.rb +123 -0
  30. data/lib/{data_structures → strokedb/data_structures}/inverted_list.rb +0 -0
  31. data/lib/{data_structures → strokedb/data_structures}/point_query.rb +0 -0
  32. data/lib/strokedb/data_structures/simple_skiplist.rb +350 -0
  33. data/lib/{data_structures → strokedb/data_structures}/skiplist.rb +1 -1
  34. data/lib/{document → strokedb}/document.rb +180 -71
  35. data/lib/{document → strokedb/document}/callback.rb +0 -0
  36. data/lib/{document → strokedb/document}/delete.rb +2 -2
  37. data/lib/strokedb/document/dsl.rb +4 -0
  38. data/lib/{document → strokedb/document/dsl}/associations.rb +0 -0
  39. data/lib/{document → strokedb/document/dsl}/coercions.rb +0 -0
  40. data/lib/strokedb/document/dsl/meta_dsl.rb +7 -0
  41. data/lib/{document → strokedb/document/dsl}/validations.rb +26 -21
  42. data/lib/{document → strokedb/document/dsl}/virtualize.rb +0 -0
  43. data/lib/{document → strokedb/document}/meta.rb +92 -29
  44. data/lib/{document → strokedb/document}/slot.rb +17 -5
  45. data/lib/{document → strokedb/document}/util.rb +0 -0
  46. data/lib/{document → strokedb/document}/versions.rb +2 -2
  47. data/lib/strokedb/index.rb +2 -0
  48. data/lib/strokedb/nsurl.rb +24 -0
  49. data/lib/strokedb/store.rb +149 -0
  50. data/lib/strokedb/stores.rb +6 -0
  51. data/lib/{stores → strokedb/stores}/chainable_storage.rb +20 -14
  52. data/lib/strokedb/stores/file_storage.rb +118 -0
  53. data/lib/{stores/inverted_list_index → strokedb/stores}/inverted_list_file_storage.rb +50 -0
  54. data/lib/strokedb/stores/memory_storage.rb +80 -0
  55. data/lib/{stores → strokedb/stores}/remote_store.rb +10 -4
  56. data/lib/strokedb/sync.rb +4 -0
  57. data/lib/{sync → strokedb/sync}/chain_sync.rb +0 -0
  58. data/lib/{sync → strokedb/sync}/diff.rb +12 -1
  59. data/lib/{sync/stroke_diff → strokedb/sync/diff}/array.rb +1 -1
  60. data/lib/{sync/stroke_diff → strokedb/sync/diff}/default.rb +0 -0
  61. data/lib/{sync/stroke_diff → strokedb/sync/diff}/hash.rb +1 -1
  62. data/lib/{sync/stroke_diff → strokedb/sync/diff}/string.rb +1 -1
  63. data/lib/{sync → strokedb/sync}/lamport_timestamp.rb +0 -0
  64. data/lib/{sync → strokedb/sync}/store_sync.rb +15 -7
  65. data/lib/strokedb/transaction.rb +78 -0
  66. data/lib/{util → strokedb}/util.rb +14 -7
  67. data/lib/strokedb/util/attach_dsl.rb +29 -0
  68. data/lib/{util → strokedb/util}/blankslate.rb +0 -0
  69. data/lib/strokedb/util/class_optimization.rb +93 -0
  70. data/lib/{util → strokedb/util}/inflect.rb +0 -0
  71. data/lib/strokedb/util/java_util.rb +13 -0
  72. data/lib/{util → strokedb/util}/lazy_array.rb +0 -0
  73. data/lib/{util → strokedb/util}/lazy_mapping_array.rb +4 -0
  74. data/lib/{util → strokedb/util}/lazy_mapping_hash.rb +0 -0
  75. data/lib/{util → strokedb/util}/serialization.rb +21 -0
  76. data/lib/strokedb/util/uuid.rb +159 -0
  77. data/lib/{util → strokedb/util}/xml.rb +0 -0
  78. data/lib/{view → strokedb}/view.rb +2 -2
  79. data/lib/strokedb/volumes.rb +5 -0
  80. data/lib/strokedb/volumes/archive_volume.rb +165 -0
  81. data/lib/strokedb/volumes/block_volume.rb +169 -0
  82. data/lib/strokedb/volumes/distributed_pointer.rb +43 -0
  83. data/lib/strokedb/volumes/fixed_length_skiplist_volume.rb +109 -0
  84. data/lib/strokedb/volumes/map_volume.rb +268 -0
  85. data/meta/MANIFEST +175 -0
  86. data/script/console +2 -70
  87. data/spec/integration/remote_store_spec.rb +70 -0
  88. data/spec/integration/search_spec.rb +76 -0
  89. data/spec/integration/spec_helper.rb +1 -0
  90. data/spec/lib/spec_helper.rb +1 -0
  91. data/spec/lib/strokedb/config_spec.rb +250 -0
  92. data/spec/lib/strokedb/core_ext/blank_spec.rb +20 -0
  93. data/spec/lib/strokedb/core_ext/extract_spec.rb +42 -0
  94. data/spec/lib/strokedb/core_ext/float_spec.rb +62 -0
  95. data/spec/lib/strokedb/core_ext/infinity_spec.rb +40 -0
  96. data/spec/lib/strokedb/core_ext/spec_helper.rb +1 -0
  97. data/spec/lib/strokedb/core_ext/string_spec.rb +25 -0
  98. data/spec/lib/strokedb/core_ext/symbol_spec.rb +8 -0
  99. data/spec/lib/strokedb/data_structures/chunked_skiplist_spec.rb +144 -0
  100. data/spec/lib/strokedb/data_structures/inverted_list_spec.rb +172 -0
  101. data/spec/lib/strokedb/data_structures/simple_skiplist_spec.rb +200 -0
  102. data/spec/lib/strokedb/data_structures/skiplist_spec.rb +253 -0
  103. data/spec/lib/strokedb/data_structures/spec_helper.rb +1 -0
  104. data/spec/lib/strokedb/document/associations_spec.rb +319 -0
  105. data/spec/lib/strokedb/document/callbacks_spec.rb +134 -0
  106. data/spec/lib/strokedb/document/coercions_spec.rb +110 -0
  107. data/spec/lib/strokedb/document/document_spec.rb +1063 -0
  108. data/spec/lib/strokedb/document/meta_meta_spec.rb +30 -0
  109. data/spec/lib/strokedb/document/meta_spec.rb +435 -0
  110. data/spec/lib/strokedb/document/metaslot_spec.rb +43 -0
  111. data/spec/lib/strokedb/document/slot_spec.rb +130 -0
  112. data/spec/lib/strokedb/document/spec_helper.rb +1 -0
  113. data/spec/lib/strokedb/document/validations_spec.rb +1081 -0
  114. data/spec/lib/strokedb/document/virtualize_spec.rb +80 -0
  115. data/spec/lib/strokedb/nsurl_spec.rb +73 -0
  116. data/spec/lib/strokedb/spec_helper.rb +1 -0
  117. data/spec/lib/strokedb/stores/chained_storages_spec.rb +116 -0
  118. data/spec/lib/strokedb/stores/spec_helper.rb +1 -0
  119. data/spec/lib/strokedb/stores/store_spec.rb +201 -0
  120. data/spec/lib/strokedb/stores/transaction_spec.rb +107 -0
  121. data/spec/lib/strokedb/sync/chain_sync_spec.rb +43 -0
  122. data/spec/lib/strokedb/sync/diff_spec.rb +111 -0
  123. data/spec/lib/strokedb/sync/lamport_timestamp_spec.rb +174 -0
  124. data/spec/lib/strokedb/sync/slot_diff_spec.rb +164 -0
  125. data/spec/lib/strokedb/sync/spec_helper.rb +1 -0
  126. data/spec/lib/strokedb/sync/store_sync_spec.rb +181 -0
  127. data/spec/lib/strokedb/sync/stroke_diff/array_spec.rb +97 -0
  128. data/spec/lib/strokedb/sync/stroke_diff/complex_spec.rb +58 -0
  129. data/spec/lib/strokedb/sync/stroke_diff/hash_spec.rb +144 -0
  130. data/spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb +23 -0
  131. data/spec/lib/strokedb/sync/stroke_diff/spec_helper.rb +25 -0
  132. data/spec/lib/strokedb/sync/stroke_diff/string_spec.rb +61 -0
  133. data/spec/lib/strokedb/util/attach_dsl_spec.rb +45 -0
  134. data/spec/lib/strokedb/util/inflect_spec.rb +14 -0
  135. data/spec/lib/strokedb/util/lazy_array_spec.rb +157 -0
  136. data/spec/lib/strokedb/util/lazy_mapping_array_spec.rb +174 -0
  137. data/spec/lib/strokedb/util/lazy_mapping_hash_spec.rb +92 -0
  138. data/spec/lib/strokedb/util/spec_helper.rb +1 -0
  139. data/spec/lib/strokedb/util/uuid_spec.rb +46 -0
  140. data/spec/lib/strokedb/view_spec.rb +228 -0
  141. data/spec/lib/strokedb/volumes/archive_volume_spec.rb +105 -0
  142. data/spec/lib/strokedb/volumes/block_volume_spec.rb +100 -0
  143. data/spec/lib/strokedb/volumes/distributed_pointer_spec.rb +14 -0
  144. data/spec/lib/strokedb/volumes/fixed_length_skiplist_volume_spec.rb +177 -0
  145. data/spec/lib/strokedb/volumes/map_volume_spec.rb +172 -0
  146. data/spec/lib/strokedb/volumes/spec_helper.rb +1 -0
  147. data/spec/regression/docref_spec.rb +94 -0
  148. data/spec/regression/meta_spec.rb +23 -0
  149. data/spec/regression/spec_helper.rb +1 -0
  150. data/spec/regression/sync_spec.rb +36 -0
  151. data/spec/spec.opts +7 -0
  152. data/spec/spec_helper.rb +37 -0
  153. data/spec/temp/storages/TIMESTAMP +1 -0
  154. data/spec/temp/storages/UUID +1 -0
  155. data/spec/temp/storages/database-sync/TIMESTAMP +1 -0
  156. data/spec/temp/storages/database-sync/UUID +1 -0
  157. data/spec/temp/storages/database-sync/config +1 -0
  158. data/spec/temp/storages/database-sync/file/LAST +1 -0
  159. data/spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av +0 -0
  160. data/spec/temp/storages/database-sync/file/uindex.wal +0 -0
  161. data/spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX +1 -0
  162. data/spec/temp/storages/inverted_list_storage/INVERTED_INDEX +0 -0
  163. data/strokedb.gemspec +120 -0
  164. data/task/benchmark.task +9 -0
  165. data/task/ditz.task +30 -0
  166. data/task/echoe.rb +17 -0
  167. data/task/rcov.task +50 -0
  168. data/task/rdoc.task +10 -0
  169. data/task/rspec.task +0 -0
  170. data/vendor/java_inline.rb +106 -0
  171. data/vendor/rbmodexcl/mrimodexcl.rb +82 -0
  172. data/vendor/rbmodexcl/rbmodexcl.rb +5 -0
  173. data/vendor/rbmodexcl/rbxmodexcl.rb +48 -0
  174. data/vendor/rbmodexcl/spec/unextend_spec.rb +50 -0
  175. data/vendor/rbmodexcl/spec/uninclude_spec.rb +26 -0
  176. metadata +271 -79
  177. data/CONTRIBUTORS +0 -7
  178. data/CREDITS +0 -13
  179. data/bin/sdbc +0 -2
  180. data/lib/init.rb +0 -57
  181. data/lib/stores/inverted_list_index/inverted_list_index.rb +0 -49
  182. data/lib/stores/skiplist_store/chunk.rb +0 -119
  183. data/lib/stores/skiplist_store/chunk_storage.rb +0 -21
  184. data/lib/stores/skiplist_store/file_chunk_storage.rb +0 -44
  185. data/lib/stores/skiplist_store/memory_chunk_storage.rb +0 -37
  186. data/lib/stores/skiplist_store/skiplist_store.rb +0 -217
  187. data/lib/stores/store.rb +0 -5
  188. data/lib/sync/stroke_diff/stroke_diff.rb +0 -9
  189. data/lib/util/ext/object.rb +0 -8
  190. data/lib/util/java_util.rb +0 -9
  191. data/lib/util/trigger_partition.rb +0 -136
  192. 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
@@ -0,0 +1,6 @@
1
+ require 'store'
2
+ require 'stores/chainable_storage'
3
+ require 'stores/file_storage'
4
+ require 'stores/memory_storage'
5
+ require 'stores/remote_store'
6
+ require 'stores/inverted_list_file_storage'
@@ -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!(chunk, source=nil)
45
- perform_save!(chunk)
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!(chunk, source=nil)
49
- perform_save!(chunk)
50
- (@chained_storages||{}).each_pair do |storage, savings|
51
- savings << chunk unless storage == source || savings.include?(chunk) # TODO: here we had a bug (storage == document), spec it
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