Skip to content

Commit 0fc66d3

Browse files
committed
tree: Ensure directory exists and lock works across nurkel/urkel.
1 parent fb42a3e commit 0fc66d3

11 files changed

Lines changed: 147 additions & 63 deletions

lib/tree.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88
const assert = require('bsert');
99
const fs = require('bfile');
10+
const {BufferMap} = require('buffer-map');
11+
const LockFile = require('urkel/lib/lockfile');
1012
const nurkel = require('./nurkel');
1113
const Proof = require('./proof');
1214
const {randomPath} = require('./util');
13-
const {BufferMap} = require('buffer-map');
1415
const {
1516
asyncIterator,
1617
syncIterator,
@@ -52,6 +53,8 @@ class Tree {
5253

5354
this.isOpen = false;
5455
this.tree = null;
56+
// This is used to lock the tree for urkel as well.
57+
this.lockFile = new LockFile(fs, this.prefix);
5558

5659
this.init();
5760
}
@@ -123,6 +126,16 @@ class Tree {
123126
return this;
124127
}
125128

129+
/**
130+
* Ensure we have the directory.
131+
* @returns {Promise}
132+
*/
133+
134+
async ensure() {
135+
assert(!this.isOpen, ERR_OPEN);
136+
await fs.mkdirp(this.prefix, 0o750);
137+
}
138+
126139
/**
127140
* Open tree.
128141
* @param {Hash} [rootHash=null]
@@ -132,6 +145,9 @@ class Tree {
132145
async open(rootHash) {
133146
assert(!this.isOpen, ERR_OPEN);
134147

148+
await this.ensure();
149+
await this.lockFile.open();
150+
135151
await nurkel.tree_open(this.tree, this.prefix);
136152
this.isOpen = true;
137153

@@ -149,6 +165,7 @@ class Tree {
149165
assert(this.isOpen, ERR_CLOSED);
150166

151167
await nurkel.tree_close(this.tree);
168+
await this.lockFile.close();
152169
this.isOpen = false;
153170
}
154171

lib/urkel.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class WrappedTree {
119119

120120
async open(rootHash) {
121121
assert(!this.isOpen, ERR_OPEN);
122+
122123
try {
123124
await this._tree.open(rootHash);
124125
} catch (e) {

test/iterator-test.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
'use strict';
22

33
const assert = require('bsert');
4-
const fs = require('fs');
5-
const {testdir, rmTreeDir} = require('./util/common');
4+
const {testdir, rmTreeDir, isTreeDir} = require('./util/common');
65
const nurkel = require('..');
76

87
const keys = {
@@ -15,8 +14,20 @@ const keys = {
1514
0: Buffer.alloc(32, 0x00)
1615
};
1716

18-
for (const memory of [false, true]) {
19-
describe(`Urkel Iterator (${memory ? 'MemTree' : 'Tree'})`, function () {
17+
const treeCreateOptions = {
18+
'nurkel': {},
19+
// use legacy tree
20+
'urkel': {
21+
urkel: true
22+
},
23+
// legacy tree as in memory tree
24+
'memory': {
25+
memory: true
26+
}
27+
};
28+
29+
for (const [name, treeTestOptions] of Object.entries(treeCreateOptions)) {
30+
describe(`Urkel Iterator (${name})`, function () {
2031
let prefix, tree;
2132

2233
const addEntries = async () => {
@@ -35,10 +46,7 @@ describe(`Urkel Iterator (${memory ? 'MemTree' : 'Tree'})`, function () {
3546
beforeEach(async () => {
3647
prefix = testdir('tx');
3748

38-
if (!memory)
39-
fs.mkdirSync(prefix);
40-
41-
tree = nurkel.create({ memory, prefix });
49+
tree = nurkel.create({ prefix, ...treeTestOptions });
4250
await tree.open();
4351

4452
await addEntries();
@@ -47,7 +55,7 @@ describe(`Urkel Iterator (${memory ? 'MemTree' : 'Tree'})`, function () {
4755
afterEach(async () => {
4856
await tree.close();
4957

50-
if (fs.existsSync(prefix))
58+
if (isTreeDir(prefix))
5159
rmTreeDir(prefix);
5260
});
5361

test/proof-test.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const assert = require('bsert');
4-
const fs = require('fs');
54
const {testdir, rmTreeDir, isTreeDir} = require('./util/common');
65
const nurkel = require('..');
76
const {BLAKE2b, proofTypes, statusCodes} = nurkel;
@@ -38,9 +37,21 @@ async function populateTree(tree, roots) {
3837
await txn.close();
3938
}
4039

41-
for (const memory of [false, true]) {
42-
describe(`Urkel Proof (${memory ? 'MemTree' : 'Tree'})`, function () {
43-
const Tree = memory ? nurkel.MemTree : nurkel.Tree;
40+
const treeCreateOptions = {
41+
'nurkel': {},
42+
// use legacy tree
43+
'urkel': {
44+
urkel: true
45+
},
46+
// legacy tree as in memory tree
47+
'memory': {
48+
memory: true
49+
}
50+
};
51+
52+
for (const [name, treeTestOptions] of Object.entries(treeCreateOptions)) {
53+
describe(`Urkel Proof (${name})`, function () {
54+
const Tree = name !== 'nurkel' ? nurkel.UrkelTree : nurkel.Tree;
4455
let prefix, tree, rootEntries, checkMatrix;
4556

4657
const withSnap = (snap) => {
@@ -54,10 +65,7 @@ describe(`Urkel Proof (${memory ? 'MemTree' : 'Tree'})`, function () {
5465
beforeEach(async () => {
5566
prefix = testdir('tree');
5667

57-
if (!memory)
58-
fs.mkdirSync(prefix);
59-
60-
tree = nurkel.create({ memory, prefix });
68+
tree = nurkel.create({ prefix, ...treeTestOptions });
6169
await tree.open();
6270
rootEntries = {};
6371
await populateTree(tree, rootEntries);
@@ -73,7 +81,7 @@ describe(`Urkel Proof (${memory ? 'MemTree' : 'Tree'})`, function () {
7381
afterEach(async () => {
7482
await tree.close();
7583

76-
if (!memory && isTreeDir(prefix))
84+
if (isTreeDir(prefix))
7785
rmTreeDir(prefix);
7886
});
7987

test/transaction-segfault-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
const fs = require('fs');
4-
const {testdir, rmTreeDir} = require('./util/common');
4+
const {testdir, rmTreeDir, isTreeDir} = require('./util/common');
55
const {Tree} = require('../lib/tree');
66

77
// Tests for the segfaults that were encountered.
@@ -20,7 +20,7 @@ describe('Urkel Transaction (segfault)', function () {
2020
if (tree.isOpen)
2121
await tree.close();
2222

23-
if (fs.existsSync(prefix))
23+
if (isTreeDir(prefix))
2424
rmTreeDir(prefix);
2525
});
2626

test/transaction-test.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,26 @@ const {Proof} = nurkel;
88

99
const NULL_HASH = Buffer.alloc(32, 0);
1010

11-
for (const memory of [false, true]) {
12-
describe(`Urkel Transaction (${memory ? 'MemTree' : 'Tree'})`, function () {
11+
const treeCreateOptions = {
12+
'nurkel': {},
13+
// use legacy tree
14+
'urkel': {
15+
urkel: true
16+
},
17+
// legacy tree as in memory tree
18+
'memory': {
19+
memory: true
20+
}
21+
};
22+
23+
for (const [name, treeTestOptions] of Object.entries(treeCreateOptions)) {
24+
describe(`Urkel Transaction (${name})`, function () {
1325
let prefix, tree;
1426

1527
beforeEach(async () => {
1628
prefix = testdir('tx');
1729

18-
if (!memory)
19-
fs.mkdirSync(prefix);
20-
21-
tree = nurkel.create({ memory, prefix });
30+
tree = nurkel.create({ prefix, ...treeTestOptions });
2231
await tree.open();
2332
});
2433

test/tree-debug-test.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const assert = require('assert');
4-
const fs = require('fs');
54
const {testdir, rmTreeDir, isTreeDir, sleep} = require('./util/common');
65
const {Tree} = require('..');
76

@@ -35,8 +34,6 @@ describe('Nurkel debug state', function() {
3534

3635
const before = () => {
3736
prefix = testdir('tree-gc');
38-
fs.mkdirSync(prefix);
39-
4037
tree = new Tree({ prefix });
4138
};
4239

@@ -54,7 +51,18 @@ describe('Nurkel debug state', function() {
5451
});
5552

5653
it('should open tree', async () => {
54+
const afterLock = new Promise((r) => {
55+
// mock ensure and open.
56+
tree.ensure = () => {};
57+
tree.lockFile.open = () => {
58+
setImmediate(r);
59+
return;
60+
};
61+
});
62+
5763
const open = tree.open();
64+
await afterLock;
65+
5866
assert.deepStrictEqual(tree.debugInfoSync(), {
5967
...CLOSED_TREE,
6068
workers: 1,

test/tree-gc-test.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const assert = require('bsert');
4-
const fs = require('fs');
54
const {testdir, rmTreeDir, isTreeDir} = require('./util/common');
65
const {Tree} = require('..');
76

@@ -13,7 +12,6 @@ describe('Urkel Tree (GC)', function () {
1312

1413
beforeEach(() => {
1514
prefix = testdir('tree-gc');
16-
fs.mkdirSync(prefix);
1715
});
1816

1917
afterEach(() => {

0 commit comments

Comments
 (0)