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
@@ -1,7 +0,0 @@
1
- Adrian Madrid <aemadrid@gmail.com>
2
- Aman Gupta <aman@tmm1.net>
3
- Claudio Perez Gamayo <crossblaim@gmail.com>
4
- elliottcable.name <strokedb@elliottcable.com>
5
- Joshua Miller <elefantstn@gmail.com>
6
- Oleg Dashevskii <be9@be9.ru>
7
- Michael Klishin (novemberain.com) <michael.s.klishin@gmail.com>
data/CREDITS DELETED
@@ -1,13 +0,0 @@
1
-
2
- MANY THANKS TO
3
- (for knowledge and aspiration)
4
-
5
- 1) Andrew S. Tanenbaum, for book "Distributed Systems".
6
- 2) William Pugh for skiplists.
7
- 3) Xin Dong & Alon Halevy for the great article "Indexing Dataspaces".
8
- 4) Linus Torvalds & Junio C. Hamano for the Git version control system.
9
- 5) Damien Katz for the CouchDB.
10
- 6) Yukihiro Matsumoto for the Ruby programming language.
11
- 7) Dr. Leslie Lamport for timestamps and signatures.
12
- 8) Victor Sovetov for years of talking with Yurii about databases and metaframes.
13
- 9) Konstantin Olenin for talks with Oleg about distributed systems and algorithms.
data/bin/sdbc DELETED
@@ -1,2 +0,0 @@
1
- #! /usr/bin/env ruby
2
- load File.dirname(__FILE__) + '/../script/console'
@@ -1,57 +0,0 @@
1
- module StrokeDB
2
- VERSION = '0.0.2.1' + (RUBY_PLATFORM =~ /java/ ? '-java' : '')
3
-
4
- # UUID regexp (like 1e3d02cc-0769-4bd8-9113-e033b246b013)
5
- UUID_RE = /([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/
6
-
7
- # document version regexp
8
- VERSION_RE = UUID_RE
9
-
10
- # following are special UUIDs used by StrokeDB
11
-
12
- # so called Nil UUID, should be used as special UUID for Meta meta
13
- NIL_UUID = "00000000-0000-0000-0000-000000000000"
14
-
15
- # UUID used for DeletedDocument meta
16
- DELETED_DOCUMENT_UUID = 'e5e0ef20-e10f-4269-bff3-3040a90e194e'
17
-
18
- # UUID used for StoreInfo meta
19
- STORE_INFO_UUID = "23e11d2e-e3d3-4c24-afd2-b3316403dd03"
20
-
21
- # UUID used for Diff meta
22
- DIFF_UUID = "5704bd39-4a01-405e-bc72-3650ddd89ca4"
23
-
24
- # UUID used for SynchronizationReport meta
25
- SYNCHRONIZATION_REPORT_UUID = "8dbaf160-addd-401a-9c29-06b03f70df93"
26
-
27
- # UUID used for SynchronizationConflict meta
28
- SYNCHRONIZATION_CONFLICT_UUID = "36fce59c-ee3d-4566-969b-7b152814a314"
29
-
30
- # UUID used for View meta
31
- VIEW_UUID = "ced0ad12-7419-4db1-a9f4-bc35e9b64112"
32
-
33
- # UUID used for ViewCut meta
34
- VIEWCUT_UUID = "2975630e-c877-4eab-b86c-732e1de1adf5"
35
-
36
- class <<self
37
- def default_store
38
- StrokeDB.default_config.stores[:default] rescue nil
39
- end
40
- def default_store=(store)
41
- cfg = Config.new
42
- cfg.stores[:default] = store
43
- StrokeDB.default_config = cfg
44
- end
45
- end
46
-
47
- if ENV['DEBUG'] || $DEBUG
48
- def DEBUG
49
- yield
50
- end
51
- else
52
- def DEBUG
53
- end
54
- end
55
-
56
- class NoDefaultStoreError < Exception ; end
57
- end
@@ -1,49 +0,0 @@
1
- module StrokeDB
2
- class InvertedListIndex
3
- attr_accessor :storage, :document_store
4
- def initialize(storage)
5
- @storage = storage
6
- @list = nil
7
- end
8
-
9
- def find_uuids(*args)
10
- list.find(*args)
11
- end
12
-
13
- def find(*args)
14
- find_uuids(*args).map do |uuid|
15
- @document_store.find(uuid)
16
- end
17
- end
18
-
19
- def insert(doc)
20
- slots = indexable_slots_for_doc(doc)
21
- q = PointQuery.new(slots)
22
- list.insert(q.slots, doc.uuid)
23
- end
24
-
25
- def delete(doc)
26
- slots = indexable_slots_for_doc(doc)
27
- q = PointQuery.new(slots)
28
- list.delete(q.slots, doc.uuid)
29
- end
30
-
31
- def save!
32
- @storage.save!(list)
33
- end
34
-
35
- private
36
-
37
- def indexable_slots_for_doc(doc)
38
- raw_slots = doc.to_raw
39
- nkeys = doc.meta['non_indexable_slots']
40
- nkeys.each{|nk| raw_slots.delete(nk) } if nkeys
41
- raw_slots
42
- end
43
-
44
- def list
45
- @list ||= @storage.find_list
46
- end
47
-
48
- end
49
- end
@@ -1,119 +0,0 @@
1
- module StrokeDB
2
- class Chunk
3
- attr_accessor :skiplist, :next_chunk, :prev_chunk, :uuid, :cut_level, :timestamp
4
- attr_accessor :next_chunk_uuid
5
- attr_accessor :store_uuid
6
- def initialize(cut_level)
7
- @skiplist, @cut_level = Skiplist.new({}, nil, cut_level), cut_level
8
- end
9
-
10
- def insert(uuid, raw_doc, __cheaters_level = nil, __timestamp = nil)
11
- @uuid ||= uuid
12
- __cheaters_level ||= $DEBUG_CHEATERS_LEVEL
13
- a, new_list = skiplist.insert(uuid, raw_doc, __cheaters_level, __timestamp)
14
- if new_list
15
- tmp = Chunk.new(@cut_level)
16
- tmp.skiplist = new_list
17
- tmp.next_chunk = @next_chunk if @next_chunk
18
- @next_chunk = tmp
19
- @next_chunk.uuid = uuid
20
- end
21
- [self, @next_chunk]
22
- end
23
-
24
- def delete(uuid)
25
- skiplist.delete(uuid)
26
- end
27
-
28
- def find(uuid, default = nil)
29
- skiplist.find(uuid, default)
30
- end
31
-
32
- def find_node(uuid)
33
- skiplist.find_node(uuid)
34
- end
35
-
36
- def find_nearest(uuid, default = nil)
37
- skiplist.find_nearest(uuid, default)
38
- end
39
-
40
- # Finds next node across separate chunks
41
- def find_next_node(node)
42
- chunk = self
43
- node2 = node.next
44
- if node2.is_a?(Skiplist::TailNode)
45
- chunk = chunk.next_chunk
46
- unless chunk.nil?
47
- node2 = chunk.first_node
48
- else
49
- node2 = nil
50
- end
51
- end
52
- node2
53
- end
54
-
55
-
56
- def first_uuid
57
- skiplist.first_node.key
58
- end
59
-
60
- def first_node
61
- skiplist.first_node
62
- end
63
-
64
- def size
65
- skiplist.size
66
- end
67
-
68
- def each(&block)
69
- skiplist.each &block
70
- end
71
-
72
- # Raw format
73
-
74
- # TODO: lazify
75
- def self.from_raw(raw)
76
- chunk = Chunk.new(raw['cut_level'])
77
- chunk.uuid = raw['uuid']
78
- chunk.next_chunk_uuid = raw['next_uuid']
79
- chunk.timestamp = raw['timestamp']
80
- chunk.store_uuid = raw['store_uuid']
81
- chunk.skiplist.raw_insert(raw['nodes']) do |rn|
82
- [rn['key'], rn['value'], rn['forward'].size, rn['timestamp']]
83
- end
84
- yield(chunk) if block_given?
85
- chunk
86
- end
87
-
88
- def to_raw
89
- # enumerate nodes
90
- skiplist.each_with_index do |node, i|
91
- node._serialized_index = i
92
- end
93
-
94
- # now we know keys' positions right in the nodes
95
- nodes = skiplist.map do |node|
96
- {
97
- 'key' => node.key,
98
- 'forward' => node.forward.map{|n| n._serialized_index || 0 },
99
- 'value' => node.value,
100
- 'timestamp' => node.timestamp
101
- }
102
- end
103
- {
104
- 'nodes' => nodes,
105
- 'cut_level' => @cut_level,
106
- 'uuid' => @uuid,
107
- # TODO: may not be needed
108
- 'next_uuid' => next_chunk ? next_chunk.uuid : nil,
109
- 'timestamp' => @timestamp,
110
- 'store_uuid' => @store_uuid
111
- }
112
- end
113
-
114
- def eql?(chunk)
115
- chunk.uuid == @uuid && chunk.skiplist.eql?(@skiplist)
116
- end
117
-
118
- end
119
- end
@@ -1,21 +0,0 @@
1
- module StrokeDB
2
- class ChunkStorage
3
- include ChainableStorage
4
-
5
- attr_accessor :authoritative_source
6
-
7
- def initialize(opts={})
8
- end
9
-
10
- def find(uuid)
11
- unless result = read(chunk_path(uuid))
12
- if authoritative_source
13
- result = authoritative_source.find(uuid)
14
- save!(result, authoritative_source) if result
15
- end
16
- end
17
- result
18
- end
19
-
20
- end
21
- end
@@ -1,44 +0,0 @@
1
- module StrokeDB
2
- class FileChunkStorage < ChunkStorage
3
- attr_accessor :path
4
-
5
- def initialize(opts={})
6
- opts = opts.stringify_keys
7
- @path = opts['path']
8
- end
9
-
10
- def delete!(chunk_uuid)
11
- FileUtils.rm_rf(chunk_path(chunk_uuid))
12
- end
13
-
14
- def clear!
15
- FileUtils.rm_rf @path
16
- end
17
-
18
- private
19
-
20
- def perform_save!(chunk)
21
- FileUtils.mkdir_p @path
22
- write(chunk_path(chunk.uuid), chunk)
23
- end
24
-
25
- def read(path)
26
- return nil unless File.exist?(path)
27
- raw_chunk = StrokeDB.deserialize(IO.read(path))
28
- Chunk.from_raw(raw_chunk) do |chunk|
29
- chunk.next_chunk = find(chunk.next_chunk_uuid) if chunk.next_chunk_uuid
30
- end
31
- end
32
-
33
- def write(path, chunk)
34
- File.open path, "w+" do |f|
35
- f.write StrokeDB.serialize(chunk.to_raw)
36
- end
37
- end
38
-
39
- def chunk_path(uuid)
40
- "#{@path}/#{uuid}"
41
- end
42
-
43
- end
44
- end
@@ -1,37 +0,0 @@
1
- module StrokeDB
2
- class MemoryChunkStorage < ChunkStorage
3
- attr_accessor :chunks_cache
4
-
5
- def initialize(opts={})
6
- @chunks_cache = {}
7
- end
8
-
9
- def delete!(chunk_uuid)
10
- write(chunk_path(chunk_uuid), nil)
11
- end
12
-
13
- def clear!
14
- @chunks_cache.clear
15
- end
16
-
17
- private
18
-
19
- def perform_save!(chunk)
20
- write(chunk_path(chunk.uuid), chunk)
21
- end
22
-
23
- def read(path)
24
- @chunks_cache[path]
25
- end
26
-
27
- def write(path, chunk)
28
- @chunks_cache[path] = chunk
29
- end
30
-
31
- def chunk_path(uuid)
32
- uuid
33
- end
34
-
35
-
36
- end
37
- end
@@ -1,217 +0,0 @@
1
- module StrokeDB
2
- class SkiplistStore < Store
3
- include Enumerable
4
- attr_accessor :chunk_storage, :cut_level, :index_store
5
-
6
- def initialize(opts={})
7
- opts = opts.stringify_keys
8
- @chunk_storage = opts['storage']
9
- @cut_level = opts['cut_level'] || 4
10
- @index_store = opts['index']
11
- autosync! unless opts['noautosync']
12
- raise "Missing chunk storage" unless @chunk_storage
13
- end
14
-
15
- def find(uuid, version=nil, opts = {})
16
- uuid_version = uuid + (version ? ".#{version}" : "")
17
- master_chunk = @chunk_storage.find('MASTER')
18
- return nil unless master_chunk # no master chunk yet
19
- chunk_uuid = master_chunk.find_nearest(uuid_version, nil)
20
- return nil unless chunk_uuid # no chunks in master chunk yet
21
- chunk = @chunk_storage.find(chunk_uuid)
22
- return nil unless chunk
23
-
24
- raw_doc = chunk.find(uuid_version)
25
-
26
- if raw_doc
27
- return raw_doc if opts[:no_instantiation]
28
- doc = Document.from_raw(self, raw_doc.freeze)
29
- doc.extend(VersionedDocument) if version
30
- return doc
31
- end
32
- nil
33
- end
34
-
35
- def search(*args)
36
- return [] unless @index_store
37
- @index_store.find(*args)
38
- end
39
-
40
- def exists?(uuid, version=nil)
41
- !!find(uuid, version, :no_instantiation => true)
42
- end
43
-
44
- def head_version(uuid)
45
- raw_doc = find(uuid, nil, :no_instantiation => true)
46
- return raw_doc['version'] if raw_doc
47
- nil
48
- end
49
-
50
- def save!(doc)
51
- master_chunk = find_or_create_master_chunk
52
- next_timestamp
53
-
54
- insert_with_cut(doc.uuid, doc, master_chunk) unless doc.is_a?(VersionedDocument)
55
- insert_with_cut("#{doc.uuid}.#{doc.version}", doc, master_chunk)
56
-
57
- update_master_chunk!(doc, master_chunk)
58
- end
59
-
60
- def save_as_head!(doc)
61
- master_chunk = find_or_create_master_chunk
62
- insert_with_cut(doc.uuid, doc, master_chunk)
63
- update_master_chunk!(doc, master_chunk)
64
- end
65
-
66
-
67
- def full_dump
68
- puts "Full storage dump:"
69
- m = @chunk_storage.find('MASTER')
70
- puts "No master!" unless m
71
- m.each do |node|
72
- puts "[chunk: #{node.key}]"
73
- chunk = @chunk_storage.find(node.value)
74
- if chunk
75
- chunk.each do |node|
76
- puts " [doc: #{node.key}] => {uuid: #{node.value['__uuid__']}, version: #{node.value['version']}, previous_version: #{node.value['previous_version']}"
77
- end
78
- else
79
- puts " nil! (but in MASTER somehow?...)"
80
- end
81
- end
82
- end
83
-
84
- def each(options = {})
85
- return nil unless m = @chunk_storage.find('MASTER') # no master chunk yet
86
- after = options[:after_timestamp]
87
- include_versions = options[:include_versions]
88
- m.each do |node|
89
- chunk = @chunk_storage.find(node.value)
90
- next unless chunk
91
- next if after && chunk.timestamp <= after
92
-
93
- chunk.each do |node|
94
- next if after && (node.timestamp <= after)
95
- if uuid_match = node.key.match(/^#{UUID_RE}$/) || (include_versions && uuid_match = node.key.match(/#{UUID_RE}./) )
96
- yield Document.from_raw(self, node.value)
97
- end
98
- end
99
- end
100
- end
101
-
102
- def timestamp
103
- @timestamp ||= (lts = find_or_create_master_chunk.timestamp) ? LTS.from_raw(lts) : LTS.zero(uuid)
104
- end
105
- def next_timestamp
106
- @timestamp = timestamp.next
107
- end
108
-
109
- def uuid
110
- return @uuid if @uuid
111
- master_chunk = @chunk_storage.find('MASTER')
112
- unless master_chunk
113
- @uuid = Util.random_uuid
114
- else
115
- @uuid = master_chunk.store_uuid
116
- end
117
- @uuid
118
- end
119
-
120
- def document
121
- find(uuid) || StoreInfo.create!(self,:kind => 'skiplist', :uuid => uuid)
122
- end
123
-
124
- def empty?
125
- !@chunk_storage.find('MASTER')
126
- end
127
-
128
- def inspect
129
- "#<Skiplist store #{uuid}#{empty? ? " (empty)" : ""}>"
130
- end
131
-
132
- def autosync!
133
- @autosync_mutex ||= Mutex.new
134
- @autosync = nil if @autosync && !@autosync.status
135
- at_exit { stop_autosync! }
136
- @autosync ||= Thread.new do
137
- until @stop_autosync
138
- @autosync_mutex.synchronize { chunk_storage.sync_chained_storages! }
139
- sleep(1)
140
- end
141
- end
142
- end
143
-
144
- def stop_autosync!
145
- if @autosync_mutex
146
- @autosync_mutex.synchronize { @stop_autosync = true; chunk_storage.sync_chained_storages! }
147
- end
148
- end
149
-
150
-
151
- private
152
-
153
- def insert_with_cut(uuid, doc, master_chunk)
154
- chunk_uuid = master_chunk.find_nearest(uuid)
155
- unless chunk_uuid && chunk = @chunk_storage.find(chunk_uuid)
156
- chunk = Chunk.new(@cut_level)
157
- end
158
- a, b = chunk.insert(uuid, doc.to_raw, nil, timestamp.counter)
159
- [a,b].compact.each do |chunk|
160
- chunk.store_uuid = self.uuid
161
- chunk.timestamp = timestamp.counter
162
- end
163
- # if split
164
- if b
165
- # rename chunk if the first chunk inconsistency detected
166
- if a.uuid != a.first_uuid
167
- old_uuid = a.uuid
168
- a.uuid = a.first_uuid
169
- @chunk_storage.save!(a)
170
- master_chunk.insert(a.uuid, a.uuid)
171
- # remove old chunk
172
- @chunk_storage.delete!(old_uuid)
173
- master_chunk.delete(old_uuid)
174
- else
175
- @chunk_storage.save!(a)
176
- master_chunk.insert(a.uuid, a.uuid)
177
- end
178
- @chunk_storage.save!(b)
179
- master_chunk.insert(b.uuid, b.uuid)
180
- else
181
- @chunk_storage.save!(a)
182
- master_chunk.insert(a.uuid, a.uuid)
183
- end
184
- end
185
-
186
- def find_or_create_master_chunk
187
- if master_chunk = @chunk_storage.find('MASTER')
188
- return master_chunk
189
- end
190
- master_chunk = Chunk.new(999)
191
- master_chunk.uuid = 'MASTER'
192
- master_chunk.store_uuid = uuid
193
- @chunk_storage.save!(master_chunk)
194
- master_chunk
195
- end
196
-
197
-
198
- def update_master_chunk!(doc, master_chunk)
199
- @chunk_storage.save!(master_chunk)
200
-
201
- # Update index
202
- if @index_store
203
- if doc.previous_version
204
- raw_pdoc = find(doc.uuid, doc.previous_version, :no_instantiation => true)
205
- pdoc = Document.from_raw(self, raw_pdoc.freeze, :skip_callbacks => true)
206
- pdoc.extend(VersionedDocument)
207
- @index_store.delete(pdoc)
208
- end
209
- @index_store.insert(doc)
210
- @index_store.save!
211
- end
212
- end
213
-
214
-
215
-
216
- end
217
- end