perobs 3.0.2 → 4.0.0
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.
- checksums.yaml +4 -4
- data/README.md +18 -17
- data/lib/perobs/BTree.rb +9 -44
- data/lib/perobs/BTreeNode.rb +116 -88
- data/lib/perobs/BTreeNodeCache.rb +10 -8
- data/lib/perobs/BTreeNodeLink.rb +1 -1
- data/lib/perobs/Cache.rb +14 -14
- data/lib/perobs/DynamoDB.rb +1 -1
- data/lib/perobs/EquiBlobsFile.rb +7 -2
- data/lib/perobs/FlatFile.rb +28 -49
- data/lib/perobs/FlatFileBlobHeader.rb +1 -19
- data/lib/perobs/FlatFileDB.rb +5 -0
- data/lib/perobs/LockFile.rb +3 -0
- data/lib/perobs/Object.rb +8 -3
- data/lib/perobs/ObjectBase.rb +6 -4
- data/lib/perobs/PersistentObjectCache.rb +153 -0
- data/lib/perobs/PersistentObjectCacheLine.rb +87 -0
- data/lib/perobs/SpaceTree.rb +5 -3
- data/lib/perobs/SpaceTreeNode.rb +15 -8
- data/lib/perobs/Store.rb +41 -13
- data/lib/perobs/version.rb +1 -1
- data/test/Array_spec.rb +38 -38
- data/test/BTree_spec.rb +45 -0
- data/test/EquiBlobsFile_spec.rb +0 -4
- data/test/FlatFileDB_spec.rb +1 -1
- data/test/Hash_spec.rb +14 -13
- data/test/Object_spec.rb +5 -5
- data/test/Store_spec.rb +62 -19
- data/test/perobs_spec.rb +7 -3
- metadata +4 -3
- data/lib/perobs/SpaceTreeNodeCache.rb +0 -149
data/test/perobs_spec.rb
CHANGED
@@ -28,7 +28,7 @@ require 'perobs'
|
|
28
28
|
|
29
29
|
class Person < PEROBS::Object
|
30
30
|
|
31
|
-
|
31
|
+
attr_persist :name, :zip, :bmi, :married, :related, :relatives
|
32
32
|
|
33
33
|
def initialize(store)
|
34
34
|
super
|
@@ -84,7 +84,7 @@ describe PEROBS::Store do
|
|
84
84
|
jane.married = true
|
85
85
|
jane.relatives = 'test'
|
86
86
|
|
87
|
-
store.
|
87
|
+
store.exit
|
88
88
|
|
89
89
|
store = PEROBS::Store.new(@db_name)
|
90
90
|
john = store['john']
|
@@ -114,6 +114,7 @@ describe PEROBS::Store do
|
|
114
114
|
0.upto(20) do |i|
|
115
115
|
expect(store["person#{i}"].name).to eq("Person #{i}")
|
116
116
|
end
|
117
|
+
store.exit
|
117
118
|
end
|
118
119
|
|
119
120
|
it 'should detect modification to non-working objects' do
|
@@ -125,11 +126,12 @@ describe PEROBS::Store do
|
|
125
126
|
0.upto(20) do |i|
|
126
127
|
store["person#{i}"].name = "New Person #{i}"
|
127
128
|
end
|
128
|
-
store.
|
129
|
+
store.exit
|
129
130
|
store = PEROBS::Store.new(@db_name)
|
130
131
|
0.upto(20) do |i|
|
131
132
|
expect(store["person#{i}"].name).to eq("New Person #{i}")
|
132
133
|
end
|
134
|
+
store.exit
|
133
135
|
end
|
134
136
|
|
135
137
|
it 'should garbage collect unlinked objects' do
|
@@ -143,10 +145,12 @@ describe PEROBS::Store do
|
|
143
145
|
store.sync
|
144
146
|
store['person1'] = nil
|
145
147
|
store.gc
|
148
|
+
store.exit
|
146
149
|
store = PEROBS::Store.new(@db_name)
|
147
150
|
expect(store.object_by_id(id1)).to be_nil
|
148
151
|
expect(store['person2']._id).to eq(id2)
|
149
152
|
expect(store['person2'].related._id).to eq(id3)
|
153
|
+
store.exit
|
150
154
|
end
|
151
155
|
|
152
156
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perobs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Schlaeger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -86,10 +86,11 @@ files:
|
|
86
86
|
- lib/perobs/Log.rb
|
87
87
|
- lib/perobs/Object.rb
|
88
88
|
- lib/perobs/ObjectBase.rb
|
89
|
+
- lib/perobs/PersistentObjectCache.rb
|
90
|
+
- lib/perobs/PersistentObjectCacheLine.rb
|
89
91
|
- lib/perobs/RobustFile.rb
|
90
92
|
- lib/perobs/SpaceTree.rb
|
91
93
|
- lib/perobs/SpaceTreeNode.rb
|
92
|
-
- lib/perobs/SpaceTreeNodeCache.rb
|
93
94
|
- lib/perobs/SpaceTreeNodeLink.rb
|
94
95
|
- lib/perobs/StackFile.rb
|
95
96
|
- lib/perobs/Store.rb
|
@@ -1,149 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
#
|
3
|
-
# = SpaceTree.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/SpaceTreeNode'
|
29
|
-
|
30
|
-
module PEROBS
|
31
|
-
|
32
|
-
class SpaceTreeNodeCache
|
33
|
-
|
34
|
-
# Simple cache that can hold up to size SpaceTreeNode entries. Entries are
|
35
|
-
# hashed with a simple node_address % size function. This keeps the
|
36
|
-
# overhead for managing the cache extremely low yet giving an OK
|
37
|
-
# probability to have cache hits. The cache also keeps track if a node is
|
38
|
-
# still in memory or needs to be reloaded from the file. All node accesses
|
39
|
-
# must always go through this cache to avoid having duplicate in-memory
|
40
|
-
# nodes for the same on-disk node.
|
41
|
-
# @param size [Integer] maximum number of cache entries
|
42
|
-
def initialize(tree, size)
|
43
|
-
@tree = tree
|
44
|
-
@size = size
|
45
|
-
clear
|
46
|
-
end
|
47
|
-
|
48
|
-
# Insert an unmodified node into the cache.
|
49
|
-
# @param node [SpaceTreeNode] Unmodified SpaceTreeNode
|
50
|
-
def insert_unmodified(node)
|
51
|
-
@in_memory_nodes[node.node_address] = node.object_id
|
52
|
-
@unmodified_nodess[node.node_address % @size] = node
|
53
|
-
end
|
54
|
-
|
55
|
-
# Insert a modified node into the cache.
|
56
|
-
# @param node [SpaceTreeNode] Modified SpaceTreeNode
|
57
|
-
# @param address [Integer] Address of the node in the file
|
58
|
-
def insert_modified(node)
|
59
|
-
@in_memory_nodes[node.node_address] = node.object_id
|
60
|
-
index = node.node_address % @size
|
61
|
-
if (old_node = @modified_nodes[index])
|
62
|
-
# If the object is already in the modified object list, we don't have
|
63
|
-
# to do anything.
|
64
|
-
return if old_node.node_address == node.node_address
|
65
|
-
# If the new object will replace an existing entry in the cash we have
|
66
|
-
# to save the object first.
|
67
|
-
old_node.save
|
68
|
-
end
|
69
|
-
|
70
|
-
@modified_nodes[index] = node
|
71
|
-
end
|
72
|
-
|
73
|
-
# Retrieve a node reference from the cache.
|
74
|
-
# @param address [Integer] address of the node to retrieve.
|
75
|
-
def get(address)
|
76
|
-
node = @unmodified_nodess[address % @size]
|
77
|
-
# We can have collisions. Check if the cached node really matches the
|
78
|
-
# requested address.
|
79
|
-
return node if node && node.node_address == address
|
80
|
-
|
81
|
-
node = @modified_nodes[address % @size]
|
82
|
-
# We can have collisions. Check if the cached node really matches the
|
83
|
-
# requested address.
|
84
|
-
return node if node && node.node_address == address
|
85
|
-
|
86
|
-
if (obj_id = @in_memory_nodes[address])
|
87
|
-
# We have the node in memory so we can just return it.
|
88
|
-
begin
|
89
|
-
node = ObjectSpace._id2ref(obj_id)
|
90
|
-
unless node.node_address == address
|
91
|
-
raise RuntimeError, "In memory list is corrupted"
|
92
|
-
end
|
93
|
-
insert_unmodified(node)
|
94
|
-
return node
|
95
|
-
rescue RangeError
|
96
|
-
# Due to a race condition the object can still be in the
|
97
|
-
# @in_memory_nodes list but has been collected already by the Ruby
|
98
|
-
# GC. In that case we need to load it again.
|
99
|
-
@in_memory_nodes.delete(address)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
SpaceTreeNode::load(@tree, address)
|
104
|
-
end
|
105
|
-
|
106
|
-
# Remove a node from the cache.
|
107
|
-
# @param address [Integer] address of node to remove.
|
108
|
-
def delete(address)
|
109
|
-
# The object is likely still in memory, but we really don't want to
|
110
|
-
# access it anymore.
|
111
|
-
@in_memory_nodes.delete(address)
|
112
|
-
|
113
|
-
index = address % @size
|
114
|
-
if (node = @unmodified_nodess[index]) && node.node_address == address
|
115
|
-
@unmodified_nodess[index] = nil
|
116
|
-
end
|
117
|
-
|
118
|
-
if (node = @modified_nodes[index]) && node.node_address == address
|
119
|
-
@modified_nodes[index] = nil
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# Remove a node from the in-memory list. This is an internal method
|
124
|
-
# and should never be called from user code. It will be called from a
|
125
|
-
# finalizer, so many restrictions apply!
|
126
|
-
# @param node_address [Integer] Node address of the node to remove from
|
127
|
-
# the list
|
128
|
-
def _collect(address)
|
129
|
-
@in_memory_nodes.delete(address)
|
130
|
-
end
|
131
|
-
|
132
|
-
# Write all modified objects into the backing store.
|
133
|
-
def flush
|
134
|
-
@modified_nodes.each { |node| node.save if node }
|
135
|
-
@modified_nodes = ::Array.new(@size)
|
136
|
-
end
|
137
|
-
|
138
|
-
# Remove all entries from the cache.
|
139
|
-
def clear
|
140
|
-
# A hash that stores all objects by ID that are currently in memory.
|
141
|
-
@in_memory_nodes = {}
|
142
|
-
@unmodified_nodess = ::Array.new(@size)
|
143
|
-
@modified_nodes = ::Array.new(@size)
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
149
|
-
|