Class: PEROBS::SpaceTreeNodeCache
- Inherits:
-
Object
- Object
- PEROBS::SpaceTreeNodeCache
- Defined in:
- lib/perobs/SpaceTreeNodeCache.rb
Instance Method Summary collapse
-
#_collect(address) ⇒ Object
Remove a node from the in-memory list.
-
#clear ⇒ Object
Remove all entries from the cache.
-
#delete(address) ⇒ Object
Remove a node from the cache.
-
#flush ⇒ Object
Write all modified objects into the backing store.
-
#get(address) ⇒ Object
Retrieve a node reference from the cache.
-
#initialize(tree, size) ⇒ SpaceTreeNodeCache
constructor
Simple cache that can hold up to size SpaceTreeNode entries.
-
#insert_modified(node) ⇒ Object
Insert a modified node into the cache.
-
#insert_unmodified(node) ⇒ Object
Insert an unmodified node into the cache.
Constructor Details
#initialize(tree, size) ⇒ SpaceTreeNodeCache
Simple cache that can hold up to size SpaceTreeNode entries. Entries are hashed with a simple node_address % size function. This keeps the overhead for managing the cache extremely low yet giving an OK probability to have cache hits. The cache also keeps track if a node is still in memory or needs to be reloaded from the file. All node accesses must always go through this cache to avoid having duplicate in-memory nodes for the same on-disk node.
42 43 44 45 46 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 42 def initialize(tree, size) @tree = tree @size = size clear end |
Instance Method Details
#_collect(address) ⇒ Object
Remove a node from the in-memory list. This is an internal method and should never be called from user code. It will be called from a finalizer, so many restrictions apply!
128 129 130 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 128 def _collect(address) @in_memory_nodes.delete(address) end |
#clear ⇒ Object
Remove all entries from the cache.
139 140 141 142 143 144 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 139 def clear # A hash that stores all objects by ID that are currently in memory. @in_memory_nodes = {} @unmodified_nodess = ::Array.new(@size) @modified_nodes = ::Array.new(@size) end |
#delete(address) ⇒ Object
Remove a node from the cache.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 108 def delete(address) # The object is likely still in memory, but we really don't want to # access it anymore. @in_memory_nodes.delete(address) index = address % @size if (node = @unmodified_nodess[index]) && node.node_address == address @unmodified_nodess[index] = nil end if (node = @modified_nodes[index]) && node.node_address == address @modified_nodes[index] = nil end end |
#flush ⇒ Object
Write all modified objects into the backing store.
133 134 135 136 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 133 def flush @modified_nodes.each { |node| node.save if node } @modified_nodes = ::Array.new(@size) end |
#get(address) ⇒ Object
Retrieve a node reference from the cache.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 75 def get(address) node = @unmodified_nodess[address % @size] # We can have collisions. Check if the cached node really matches the # requested address. return node if node && node.node_address == address node = @modified_nodes[address % @size] # We can have collisions. Check if the cached node really matches the # requested address. return node if node && node.node_address == address if (obj_id = @in_memory_nodes[address]) # We have the node in memory so we can just return it. begin node = ObjectSpace._id2ref(obj_id) unless node.node_address == address raise RuntimeError, "In memory list is corrupted" end insert_unmodified(node) return node rescue RangeError # Due to a race condition the object can still be in the # @in_memory_nodes list but has been collected already by the Ruby # GC. In that case we need to load it again. @in_memory_nodes.delete(address) end end SpaceTreeNode::load(@tree, address) end |
#insert_modified(node) ⇒ Object
Insert a modified node into the cache.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 58 def insert_modified(node) @in_memory_nodes[node.node_address] = node.object_id index = node.node_address % @size if (old_node = @modified_nodes[index]) # If the object is already in the modified object list, we don't have # to do anything. return if old_node.node_address == node.node_address # If the new object will replace an existing entry in the cash we have # to save the object first. old_node.save end @modified_nodes[index] = node end |
#insert_unmodified(node) ⇒ Object
Insert an unmodified node into the cache.
50 51 52 53 |
# File 'lib/perobs/SpaceTreeNodeCache.rb', line 50 def insert_unmodified(node) @in_memory_nodes[node.node_address] = node.object_id @unmodified_nodess[node.node_address % @size] = node end |