perobs 3.0.2 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
-