Skip to content

Commit 8d6ec92

Browse files
authored
Merge pull request ethereumjs#427 from ethereumjs/test/fix-cache
Add unit tests for cache, convert it to es6 class
2 parents 0d965b1 + 1482946 commit 8d6ec92

File tree

4 files changed

+270
-215
lines changed

4 files changed

+270
-215
lines changed

lib/cache.js

+162-115
Original file line numberDiff line numberDiff line change
@@ -3,144 +3,191 @@ const Tree = require('functional-red-black-tree')
33
const Account = require('ethereumjs-account')
44
const async = require('async')
55

6-
var Cache = module.exports = function (trie) {
7-
this._cache = Tree()
8-
this._checkpoints = []
9-
this._trie = trie
10-
}
11-
12-
Cache.prototype.put = function (key, val, fromTrie) {
13-
var modified = !fromTrie
14-
this._update(key, val, modified, false)
15-
}
16-
17-
// returns the queried account or an empty account
18-
Cache.prototype.get = function (key) {
19-
var account = this.lookup(key)
20-
if (!account) {
21-
account = new Account()
6+
module.exports = class Cache {
7+
constructor (trie) {
8+
this._cache = Tree()
9+
this._checkpoints = []
10+
this._trie = trie
2211
}
23-
return account
24-
}
2512

26-
// returns the queried account or undefined
27-
Cache.prototype.lookup = function (key) {
28-
key = key.toString('hex')
13+
/**
14+
* Puts account to cache under its address.
15+
* @param {Buffer} key - Address of account
16+
* @param {Account} val - Account
17+
* @param {bool} [fromTrie]
18+
*/
19+
put (key, val, fromTrie = false) {
20+
const modified = !fromTrie
21+
this._update(key, val, modified, false)
22+
}
2923

30-
var it = this._cache.find(key)
31-
if (it.node) {
32-
var account = new Account(it.value.val)
24+
/**
25+
* Returns the queried account or an empty account.
26+
* @param {Buffer} key - Address of account
27+
*/
28+
get (key) {
29+
let account = this.lookup(key)
30+
if (!account) {
31+
account = new Account()
32+
}
3333
return account
3434
}
35-
}
3635

37-
Cache.prototype._lookupAccount = function (address, cb) {
38-
var self = this
39-
self._trie.get(address, function (err, raw) {
40-
if (err) return cb(err)
41-
var account = new Account(raw)
42-
cb(null, account)
43-
})
44-
}
36+
/**
37+
* Returns the queried account or undefined.
38+
* @param {buffer} key - Address of account
39+
*/
40+
lookup (key) {
41+
key = key.toString('hex')
42+
43+
const it = this._cache.find(key)
44+
if (it.node) {
45+
const account = new Account(it.value.val)
46+
return account
47+
}
48+
}
4549

46-
Cache.prototype.getOrLoad = function (key, cb) {
47-
var self = this
48-
var account = this.lookup(key)
49-
if (account) {
50-
async.nextTick(cb, null, account)
51-
} else {
52-
self._lookupAccount(key, function (err, account) {
50+
/**
51+
* Looks up address in underlying trie.
52+
* @param {Buffer} address - Address of account
53+
* @param {Function} cb - Callback with params (err, account)
54+
*/
55+
_lookupAccount (address, cb) {
56+
this._trie.get(address, (err, raw) => {
5357
if (err) return cb(err)
54-
self._update(key, account, false, false)
58+
var account = new Account(raw)
5559
cb(null, account)
5660
})
5761
}
58-
}
5962

60-
Cache.prototype.warm = function (addresses, cb) {
61-
var self = this
62-
// shim till async supports iterators
63-
var accountArr = []
64-
addresses.forEach(function (val) {
65-
if (val) accountArr.push(val)
66-
})
67-
68-
async.eachSeries(accountArr, function (addressHex, done) {
69-
var address = Buffer.from(addressHex, 'hex')
70-
self._lookupAccount(address, function (err, account) {
71-
if (err) return done(err)
72-
self._update(address, account, false, false)
73-
done()
63+
/**
64+
* Looks up address in cache, if not found, looks it up
65+
* in the underlying trie.
66+
* @param {Buffer} key - Address of account
67+
* @param {Function} cb - Callback with params (err, account)
68+
*/
69+
getOrLoad (key, cb) {
70+
const account = this.lookup(key)
71+
if (account) {
72+
async.nextTick(cb, null, account)
73+
} else {
74+
this._lookupAccount(key, (err, account) => {
75+
if (err) return cb(err)
76+
this._update(key, account, false, false)
77+
cb(null, account)
78+
})
79+
}
80+
}
81+
82+
/**
83+
* Warms cache by loading their respective account from trie
84+
* and putting them in cache.
85+
* @param {Array} addresses - Array of addresses
86+
* @param {Function} cb - Callback
87+
*/
88+
warm (addresses, cb) {
89+
// shim till async supports iterators
90+
var accountArr = []
91+
addresses.forEach((val) => {
92+
if (val) accountArr.push(val)
7493
})
75-
}, cb)
76-
}
7794

78-
Cache.prototype.flush = function (cb) {
79-
var it = this._cache.begin
80-
var self = this
81-
var next = true
82-
async.whilst(function () {
83-
return next
84-
}, function (done) {
85-
if (it.value && it.value.modified) {
86-
it.value.modified = false
87-
it.value.val = it.value.val.serialize()
88-
self._trie.put(Buffer.from(it.key, 'hex'), it.value.val, function () {
89-
next = it.hasNext
90-
it.next()
95+
async.eachSeries(accountArr, (addressHex, done) => {
96+
var address = Buffer.from(addressHex, 'hex')
97+
this._lookupAccount(address, (err, account) => {
98+
if (err) return done(err)
99+
this._update(address, account, false, false)
91100
done()
92101
})
93-
} else if (it.value && it.value.deleted) {
94-
it.value.modified = false
95-
it.value.deleted = false
96-
it.value.val = (new Account()).serialize()
97-
self._trie.del(Buffer.from(it.key, 'hex'), function () {
102+
}, cb)
103+
}
104+
105+
/**
106+
* Flushes cache by updating accounts that have been modified
107+
* and removing accounts that have been deleted.
108+
* @param {function} cb - Callback
109+
*/
110+
flush (cb) {
111+
const it = this._cache.begin
112+
let next = true
113+
async.whilst(() => next, (done) => {
114+
if (it.value && it.value.modified) {
115+
it.value.modified = false
116+
it.value.val = it.value.val.serialize()
117+
this._trie.put(Buffer.from(it.key, 'hex'), it.value.val, () => {
118+
next = it.hasNext
119+
it.next()
120+
done()
121+
})
122+
} else if (it.value && it.value.deleted) {
123+
it.value.modified = false
124+
it.value.deleted = false
125+
it.value.val = (new Account()).serialize()
126+
this._trie.del(Buffer.from(it.key, 'hex'), () => {
127+
next = it.hasNext
128+
it.next()
129+
done()
130+
})
131+
} else {
98132
next = it.hasNext
99133
it.next()
100-
done()
101-
})
102-
} else {
103-
next = it.hasNext
104-
it.next()
105-
async.nextTick(done)
106-
}
107-
}, cb)
108-
}
134+
async.nextTick(done)
135+
}
136+
}, cb)
137+
}
109138

110-
Cache.prototype.checkpoint = function () {
111-
this._checkpoints.push(this._cache)
112-
}
139+
/**
140+
* Marks current state of cache as checkpoint, which can
141+
* later on be reverted or commited.
142+
*/
143+
checkpoint () {
144+
this._checkpoints.push(this._cache)
145+
}
113146

114-
Cache.prototype.revert = function () {
115-
this._cache = this._checkpoints.pop(this._cache)
116-
}
147+
/**
148+
* Revert changes to cache last checkpoint (no effect on trie).
149+
*/
150+
revert () {
151+
this._cache = this._checkpoints.pop()
152+
}
117153

118-
Cache.prototype.commit = function () {
119-
this._checkpoints.pop()
120-
}
154+
/**
155+
* Commits to current state of cache (no effect on trie).
156+
*/
157+
commit () {
158+
this._checkpoints.pop()
159+
}
121160

122-
Cache.prototype.clear = function () {
123-
this._cache = Tree()
124-
}
161+
/**
162+
* Clears cache.
163+
*/
164+
clear () {
165+
this._cache = Tree()
166+
}
125167

126-
Cache.prototype.del = function (key) {
127-
this._update(key, new Account(), false, true)
128-
}
168+
/**
169+
* Marks address as deleted in cache.
170+
* @params {Buffer} key - Address
171+
*/
172+
del (key) {
173+
this._update(key, new Account(), false, true)
174+
}
129175

130-
Cache.prototype._update = function (key, val, modified, deleted) {
131-
key = key.toString('hex')
132-
var it = this._cache.find(key)
133-
if (it.node) {
134-
this._cache = it.update({
135-
val: val,
136-
modified: modified,
137-
deleted: deleted
138-
})
139-
} else {
140-
this._cache = this._cache.insert(key, {
141-
val: val,
142-
modified: modified,
143-
deleted: deleted
144-
})
176+
_update (key, val, modified, deleted) {
177+
key = key.toString('hex')
178+
const it = this._cache.find(key)
179+
if (it.node) {
180+
this._cache = it.update({
181+
val: val,
182+
modified: modified,
183+
deleted: deleted
184+
})
185+
} else {
186+
this._cache = this._cache.insert(key, {
187+
val: val,
188+
modified: modified,
189+
deleted: deleted
190+
})
191+
}
145192
}
146193
}

0 commit comments

Comments
 (0)