Class: Ethereum::DB::RefcountDB
- Includes:
- BaseDB
- Defined in:
- lib/ethereum/db/refcount_db.rb
Constant Summary collapse
- DEATH_ROW_OFFSET =
2**62
- ZERO_ENCODED =
Utils.encode_int(0)
- ONE_ENCODED =
Utils.encode_int(1)
Instance Attribute Summary collapse
-
#ttl ⇒ Object
Returns the value of attribute ttl.
Attributes included from BaseDB
Instance Method Summary collapse
-
#cleanup(epoch) ⇒ Object
Kill nodes that are eligible to be killed, and remove the associated deathrow record.
- #commit ⇒ Object
-
#commit_refcount_changes(epoch) ⇒ Object
Commit changes to the journal and death row to the database.
-
#dec_refcount(k) ⇒ Object
(also: #delete)
Decrease the reference count associated with a key.
- #get(k) ⇒ Object
- #get_refcount(k) ⇒ Object
- #has_key?(k) ⇒ Boolean (also: #include?)
-
#inc_refcount(k, v) ⇒ Object
(also: #put)
Increase the reference count associated with a key.
-
#initialize(db) ⇒ RefcountDB
constructor
A new instance of RefcountDB.
- #put_temporarily(k, v) ⇒ Object
- #ref_get(k) ⇒ Object
- #ref_key(k) ⇒ Object
- #ref_put(k, v) ⇒ Object
-
#revert_refcount_changes(epoch) ⇒ Object
Revert changes made during an epoch.
Constructor Details
#initialize(db) ⇒ RefcountDB
Returns a new instance of RefcountDB.
15 16 17 18 19 20 21 22 |
# File 'lib/ethereum/db/refcount_db.rb', line 15 def initialize(db) @db = db @journal = [] @death_row = [] @kv = @db.respond_to?(:kv) ? @db.kv : nil self.ttl = 500 end |
Instance Attribute Details
#ttl ⇒ Object
Returns the value of attribute ttl.
13 14 15 |
# File 'lib/ethereum/db/refcount_db.rb', line 13 def ttl @ttl end |
Instance Method Details
#cleanup(epoch) ⇒ Object
Kill nodes that are eligible to be killed, and remove the associated deathrow record. Also delete old journals.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/ethereum/db/refcount_db.rb', line 86 def cleanup(epoch) rlp_nodes = @db.get("deathrow:#{epoch}") rescue RLP.encode([]) death_row_nodes = RLP.decode rlp_nodes pruned = 0 offset = DEATH_ROW_OFFSET + epoch death_row_nodes.each do |node_key| begin refcount, val = RLP.decode ref_get(node_key) if Utils.decode_int(refcount) == offset @db.delete ref_key(node_key) pruned += 1 end rescue logger.debug "in cleanup: #{$!}" end end logger.debug "#{pruned} nodes successfully pruned" @db.delete "deathrow:#{epoch}" rescue nil @db.delete "journal:#{epoch - ttl}" rescue nil end |
#commit ⇒ Object
168 169 170 |
# File 'lib/ethereum/db/refcount_db.rb', line 168 def commit @db.commit end |
#commit_refcount_changes(epoch) ⇒ Object
Commit changes to the journal and death row to the database.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/ethereum/db/refcount_db.rb', line 113 def commit_refcount_changes(epoch) timeout_epoch = epoch + ttl death_row_nodes = RLP.decode(@db.get("deathrow:#{timeout_epoch}")) rescue [] @death_row.each do |node_key| refcount, val = RLP.decode ref_get(node_key) if refcount == ZERO_ENCODED new_refcount = Utils.encode_int(DEATH_ROW_OFFSET + timeout_epoch) ref_put node_key, RLP.encode([new_refcount, val]) end end unless @death_row.empty? logger.debug "#{@death_row.size} nodes marked for pruning during block #{timeout_epoch}" end death_row_nodes.concat @death_row @death_row = [] @db.put "deathrow:#{timeout_epoch}", RLP.encode(death_row_nodes) journal = RLP.decode(@db.get("journal:#{epoch}")) rescue [] journal.concat @journal @journal = [] @db.put "journal:#{epoch}", RLP.encode(journal) end |
#dec_refcount(k) ⇒ Object Also known as: delete
Decrease the reference count associated with a key.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/ethereum/db/refcount_db.rb', line 53 def dec_refcount(k) node_object = RLP.decode ref_get(k) refcount = Utils.decode_int node_object[0] if logger.trace? logger.trace "decreasing #{Utils.encode_hex(k)} to #{refcount-1}" end raise AssertError, "refcount must be greater than zero!" unless refcount > 0 @journal.push [node_object[0], k] new_refcount = Utils.encode_int(refcount-1) ref_put k, RLP.encode([new_refcount, node_object[1]]) @death_row.push k if new_refcount == ZERO_ENCODED end |
#get(k) ⇒ Object
78 79 80 |
# File 'lib/ethereum/db/refcount_db.rb', line 78 def get(k) RLP.decode(ref_get(k))[1] end |
#get_refcount(k) ⇒ Object
71 72 73 74 75 76 |
# File 'lib/ethereum/db/refcount_db.rb', line 71 def get_refcount(k) o = Utils.decode_int RLP.decode(ref_get(k))[0] o >= DEATH_ROW_OFFSET ? 0 : o rescue 0 end |
#has_key?(k) ⇒ Boolean Also known as: include?
158 159 160 |
# File 'lib/ethereum/db/refcount_db.rb', line 158 def has_key?(k) @db.has_key? ref_key(k) end |
#inc_refcount(k, v) ⇒ Object Also known as: put
Increase the reference count associated with a key.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ethereum/db/refcount_db.rb', line 27 def inc_refcount(k, v) node_object = RLP.decode ref_get(k) refcount = Utils.decode_int node_object[0] @journal.push [node_object[0], k] refcount = 0 if refcount >= DEATH_ROW_OFFSET new_refcount = Utils.encode_int(refcount+1) ref_put k, RLP.encode([new_refcount, v]) if logger.trace? logger.trace "increasing #{Utils.encode_hex(k)}=#{v} to #{refcount+1}" end rescue ref_put k, RLP.encode([ONE_ENCODED, v]) @journal.push [ZERO_ENCODED, k] if logger.trace? logger.trace "increasing #{Utils.encode_hex(k)}=#{v} to 1" end end |
#put_temporarily(k, v) ⇒ Object
163 164 165 166 |
# File 'lib/ethereum/db/refcount_db.rb', line 163 def put_temporarily(k, v) inc_refcount k, v dec_refcount k end |
#ref_get(k) ⇒ Object
172 173 174 175 176 177 178 |
# File 'lib/ethereum/db/refcount_db.rb', line 172 def ref_get(k) if has_key?(k) @db.get ref_key(k) else raise KeyError, k.inspect end end |
#ref_key(k) ⇒ Object
184 185 186 |
# File 'lib/ethereum/db/refcount_db.rb', line 184 def ref_key(k) "r:#{k}" end |
#ref_put(k, v) ⇒ Object
180 181 182 |
# File 'lib/ethereum/db/refcount_db.rb', line 180 def ref_put(k, v) @db.put ref_key(k), v end |
#revert_refcount_changes(epoch) ⇒ Object
Revert changes made during an epoch
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/ethereum/db/refcount_db.rb', line 142 def revert_refcount_changes(epoch) timeout_epoch = epoch + ttl @db.delete("deathrow:#{timeout_epoch}") rescue nil begin journal = RLP.decode @db.get("journal:#{epoch}") journal.reverse.each do |(new_refcount, key)| node_object = RLP.decode ref_get(key) ref_put key, RLP.encode([new_refcount, node_object[1]]) end rescue # do nothing end end |