perobs 2.5.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/perobs/Array.rb +1 -1
- data/lib/perobs/BTree.rb +233 -0
- data/lib/perobs/BTreeDB.rb +2 -0
- data/lib/perobs/BTreeNode.rb +706 -0
- data/lib/perobs/BTreeNodeCache.rb +107 -0
- data/lib/perobs/BTreeNodeLink.rb +141 -0
- data/lib/perobs/EquiBlobsFile.rb +570 -0
- data/lib/perobs/FlatFile.rb +179 -78
- data/lib/perobs/FlatFileBlobHeader.rb +92 -17
- data/lib/perobs/FlatFileDB.rb +16 -7
- data/lib/perobs/LockFile.rb +181 -0
- data/lib/perobs/Object.rb +2 -1
- data/lib/perobs/SpaceTree.rb +181 -0
- data/lib/perobs/SpaceTreeNode.rb +672 -0
- data/lib/perobs/SpaceTreeNodeCache.rb +76 -0
- data/lib/perobs/SpaceTreeNodeLink.rb +103 -0
- data/lib/perobs/Store.rb +27 -13
- data/lib/perobs/version.rb +1 -1
- data/test/BTree_spec.rb +128 -0
- data/test/EquiBlobsFile_spec.rb +199 -0
- data/test/FlatFileDB_spec.rb +63 -9
- data/test/LockFile_spec.rb +133 -0
- data/test/SpaceTree_spec.rb +245 -0
- data/test/Store_spec.rb +3 -0
- data/test/spec_helper.rb +13 -0
- metadata +21 -13
- data/lib/perobs/FixedSizeBlobFile.rb +0 -193
- data/lib/perobs/FreeSpaceManager.rb +0 -204
- data/lib/perobs/IndexTree.rb +0 -145
- data/lib/perobs/IndexTreeNode.rb +0 -316
- data/test/FixedSizeBlobFile_spec.rb +0 -91
- data/test/FreeSpaceManager_spec.rb +0 -91
- data/test/IndexTree_spec.rb +0 -118
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# = BTree.rb -- Persistent Ruby Object Store
|
4
|
+
#
|
5
|
+
# Copyright (c) 2016, 2017 by Chris Schlaeger <chris@taskjuggler.org>
|
6
|
+
#
|
7
|
+
# MIT License
|
8
|
+
#
|
9
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
10
|
+
# a copy of this software and associated documentation files (the
|
11
|
+
# "Software"), to deal in the Software without restriction, including
|
12
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
13
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
14
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
15
|
+
# the following conditions:
|
16
|
+
#
|
17
|
+
# The above copyright notice and this permission notice shall be
|
18
|
+
# included in all copies or substantial portions of the Software.
|
19
|
+
#
|
20
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
21
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
23
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
24
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
25
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
|
+
|
28
|
+
require 'perobs/BTreeNode'
|
29
|
+
|
30
|
+
module PEROBS
|
31
|
+
|
32
|
+
class BTreeNodeCache
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
clear
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](address)
|
39
|
+
if (node = @modified_nodes[address])
|
40
|
+
return node
|
41
|
+
end
|
42
|
+
|
43
|
+
if (node = @top_nodes[address])
|
44
|
+
return node
|
45
|
+
end
|
46
|
+
|
47
|
+
if (node = @ephemeral_nodes[address])
|
48
|
+
return node
|
49
|
+
end
|
50
|
+
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_root(node)
|
55
|
+
node = node.get_node if node.is_a?(BTreeNodeLink)
|
56
|
+
|
57
|
+
@top_nodes = {}
|
58
|
+
@top_nodes[node.node_address] = node
|
59
|
+
end
|
60
|
+
|
61
|
+
def insert(node)
|
62
|
+
unless node
|
63
|
+
PEROBS.log.fatal "nil cannot be cached"
|
64
|
+
end
|
65
|
+
node = node.get_node if node.is_a?(BTreeNodeLink)
|
66
|
+
|
67
|
+
@ephemeral_nodes[node.node_address] = node
|
68
|
+
|
69
|
+
if !@top_nodes.include?(node) && node.is_top?
|
70
|
+
@top_nodes[node.node_address] = node
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def mark_as_modified(node)
|
75
|
+
node = node.get_node if node.is_a?(BTreeNodeLink)
|
76
|
+
@modified_nodes[node.node_address] = node
|
77
|
+
insert(node)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Remove a node from the cache.
|
81
|
+
# @param address [Integer] address of node to remove.
|
82
|
+
def delete(address)
|
83
|
+
@ephemeral_nodes.delete(address)
|
84
|
+
@top_nodes.delete(address)
|
85
|
+
@modified_nodes.delete(address)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Flush all dirty nodes into the backing store.
|
89
|
+
def flush(now = false)
|
90
|
+
if now || @modified_nodes.size > 1024
|
91
|
+
@modified_nodes.each_value { |node| node.write_node }
|
92
|
+
@modified_nodes = {}
|
93
|
+
end
|
94
|
+
@ephemeral_nodes = {}
|
95
|
+
end
|
96
|
+
|
97
|
+
# Remove all nodes from the cache.
|
98
|
+
def clear
|
99
|
+
@top_nodes = {}
|
100
|
+
@ephemeral_nodes = {}
|
101
|
+
@modified_nodes = {}
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# = BTreeNodeLink.rb -- Persistent Ruby Object Store
|
4
|
+
#
|
5
|
+
# Copyright (c) 2016, 2017 by Chris Schlaeger <chris@taskjuggler.org>
|
6
|
+
#
|
7
|
+
# MIT License
|
8
|
+
#
|
9
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
10
|
+
# a copy of this software and associated documentation files (the
|
11
|
+
# "Software"), to deal in the Software without restriction, including
|
12
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
13
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
14
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
15
|
+
# the following conditions:
|
16
|
+
#
|
17
|
+
# The above copyright notice and this permission notice shall be
|
18
|
+
# included in all copies or substantial portions of the Software.
|
19
|
+
#
|
20
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
21
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
23
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
24
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
25
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
|
+
|
28
|
+
module PEROBS
|
29
|
+
|
30
|
+
# This class is used to form the links between the in-memory BTreeNode
|
31
|
+
# objects. The link is based on the address of the node in the file. The
|
32
|
+
# class objects transparently convert the address into a corresponding
|
33
|
+
# BTreeNode object and pass on all method calls.
|
34
|
+
class BTreeNodeLink
|
35
|
+
|
36
|
+
attr_reader :node_address
|
37
|
+
|
38
|
+
# Create a new BTreeNodeLink object.
|
39
|
+
# @param tree [BTree] The BTree that holds the nodes.
|
40
|
+
# @param node_or_address [BTreeNode or BTreeNodeLink or Integer] a
|
41
|
+
# BTreeNode, BTreeNodeLink reference or the node
|
42
|
+
# address in the file.
|
43
|
+
def initialize(tree, node_or_address)
|
44
|
+
@tree = tree
|
45
|
+
if node_or_address.is_a?(BTreeNode) ||
|
46
|
+
node_or_address.is_a?(BTreeNodeLink)
|
47
|
+
@node_address = node_or_address.node_address
|
48
|
+
elsif node_or_address.is_a?(Integer)
|
49
|
+
@node_address = node_or_address
|
50
|
+
else
|
51
|
+
PEROBS.log.fatal "Unsupported argument type #{node_or_address.class}"
|
52
|
+
end
|
53
|
+
if @node_address == 0
|
54
|
+
PEROBS.log.fatal "Node address may not be 0"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# All calls to a BTreeNodeLink object will be forwarded to the
|
59
|
+
# corresponding BTreeNode object. If that
|
60
|
+
def method_missing(method, *args, &block)
|
61
|
+
#$stderr.puts "Method missing: #{method}"
|
62
|
+
get_node.send(method, *args, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Make it properly introspectable.
|
66
|
+
def respond_to?(method, include_private = false)
|
67
|
+
get_node.respond_to?(method)
|
68
|
+
end
|
69
|
+
|
70
|
+
def is_leaf
|
71
|
+
get_node.is_leaf
|
72
|
+
end
|
73
|
+
|
74
|
+
def keys
|
75
|
+
get_node.keys
|
76
|
+
end
|
77
|
+
|
78
|
+
def values
|
79
|
+
get_node.values
|
80
|
+
end
|
81
|
+
|
82
|
+
def children
|
83
|
+
get_node.children
|
84
|
+
end
|
85
|
+
|
86
|
+
def get(key)
|
87
|
+
get_node.get(key)
|
88
|
+
end
|
89
|
+
|
90
|
+
def search_key_index(key)
|
91
|
+
get_node.search_key_index(key)
|
92
|
+
end
|
93
|
+
|
94
|
+
def insert_element(key, voc)
|
95
|
+
get_node.insert_element(key, voc)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Compare this node to another node.
|
99
|
+
# @return [Boolean] true if node address is identical, false otherwise
|
100
|
+
def ==(node)
|
101
|
+
@node_address == node.node_address
|
102
|
+
end
|
103
|
+
|
104
|
+
# Compare this node to another node.
|
105
|
+
# @return [Boolean] true if node address is not identical, false otherwise
|
106
|
+
def !=(node)
|
107
|
+
if node.nil?
|
108
|
+
return !@node_address.nil?
|
109
|
+
end
|
110
|
+
|
111
|
+
@node_address != node.node_address
|
112
|
+
end
|
113
|
+
|
114
|
+
def is_top?
|
115
|
+
get_node.is_top?
|
116
|
+
end
|
117
|
+
|
118
|
+
# Check the link to a sub-node. This method silently ignores all errors if
|
119
|
+
# the sub-node does not exist.
|
120
|
+
# @return [Boolean] True if link is OK, false otherweise
|
121
|
+
def check_node_link(branch, stack)
|
122
|
+
begin
|
123
|
+
return get_node.check_node_link(branch, stack)
|
124
|
+
rescue
|
125
|
+
return false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# @return Textual version of the BTreeNode
|
130
|
+
def to_s
|
131
|
+
get_node.to_s
|
132
|
+
end
|
133
|
+
|
134
|
+
def get_node
|
135
|
+
@tree.get_node(@node_address)
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|