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.
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