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.
data/test/perobs_spec.rb CHANGED
@@ -28,7 +28,7 @@ require 'perobs'
28
28
 
29
29
  class Person < PEROBS::Object
30
30
 
31
- po_attr :name, :zip, :bmi, :married, :related, :relatives
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.sync
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.sync
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: 3.0.2
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-10-07 00:00:00.000000000 Z
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
-