1
1
import { Trie as BaseTrie } from './baseTrie'
2
- import { ScratchReadStream } from './scratchReadStream'
3
- import { ScratchDB } from './scratch'
4
- import { DB } from './db'
5
- const WriteStream = require ( 'level-ws' )
6
2
7
3
/**
8
4
* Adds checkpointing to the {@link BaseTrie}
9
5
*/
10
6
export class CheckpointTrie extends BaseTrie {
11
- _mainDB : DB
12
- _scratch : ScratchDB | null
13
- _checkpoints : Buffer [ ]
14
-
15
7
constructor ( ...args : any ) {
16
8
super ( ...args )
17
- // Reference to main DB instance
18
- this . _mainDB = this . db
19
- // DB instance used for checkpoints
20
- this . _scratch = null
21
- // Roots of trie at the moment of checkpoint
22
- this . _checkpoints = [ ]
23
9
}
24
10
25
11
/**
26
12
* Is the trie during a checkpoint phase?
27
13
*/
28
14
get isCheckpoint ( ) {
29
- return this . _checkpoints . length > 0
15
+ return this . db . checkpoints . length > 0
30
16
}
31
17
32
18
/**
33
19
* Creates a checkpoint that can later be reverted to or committed.
34
- * After this is called, no changes to the trie will be permanently saved until `commit` is called.
35
- * To override the checkpointing mechanism use `_maindb.put` to write directly write to db.
20
+ * After this is called, all changes can be reverted until `commit` is called.
36
21
*/
37
22
checkpoint ( ) {
38
- const wasCheckpoint = this . isCheckpoint
39
- this . _checkpoints . push ( this . root )
40
-
41
- // Entering checkpoint mode is not necessary for nested checkpoints
42
- if ( ! wasCheckpoint && this . isCheckpoint ) {
43
- this . _enterCpMode ( )
44
- }
23
+ this . db . checkpoint ( this . root )
45
24
}
46
25
47
26
/**
@@ -55,13 +34,7 @@ export class CheckpointTrie extends BaseTrie {
55
34
}
56
35
57
36
await this . lock . wait ( )
58
-
59
- this . _checkpoints . pop ( )
60
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
61
- if ( ! this . isCheckpoint ) {
62
- await this . _exitCpMode ( true )
63
- }
64
-
37
+ this . db . commit ( )
65
38
this . lock . signal ( )
66
39
}
67
40
@@ -71,15 +44,12 @@ export class CheckpointTrie extends BaseTrie {
71
44
* parent checkpoint as current.
72
45
*/
73
46
async revert ( ) : Promise < void > {
74
- await this . lock . wait ( )
75
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
76
- if ( this . isCheckpoint ) {
77
- this . root = this . _checkpoints . pop ( ) !
78
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
79
- if ( ! this . isCheckpoint ) {
80
- await this . _exitCpMode ( false )
81
- }
47
+ if ( ! this . isCheckpoint ) {
48
+ throw new Error ( 'trying to revert when not checkpointed' )
82
49
}
50
+
51
+ await this . lock . wait ( )
52
+ this . root = await this . db . revert ( )
83
53
this . lock . signal ( )
84
54
}
85
55
@@ -88,57 +58,11 @@ export class CheckpointTrie extends BaseTrie {
88
58
* @param includeCheckpoints - If true and during a checkpoint, the copy will contain the checkpointing metadata and will use the same scratch as underlying db.
89
59
*/
90
60
copy ( includeCheckpoints = true ) : CheckpointTrie {
91
- const db = this . _mainDB . copy ( )
61
+ const db = this . db . copy ( )
92
62
const trie = new CheckpointTrie ( db . _leveldb , this . root )
93
63
if ( includeCheckpoints && this . isCheckpoint ) {
94
- trie . _checkpoints = this . _checkpoints . slice ( )
95
- trie . _scratch = this . _scratch ! . copy ( )
96
- trie . db = trie . _scratch
64
+ trie . db . checkpoints = this . db . checkpoints . slice ( )
97
65
}
98
66
return trie
99
67
}
100
-
101
- /**
102
- * Enter into checkpoint mode.
103
- * @private
104
- */
105
- _enterCpMode ( ) {
106
- this . _scratch = new ScratchDB ( this . _mainDB )
107
- this . db = this . _scratch
108
- }
109
-
110
- /**
111
- * Exit from checkpoint mode.
112
- * @private
113
- */
114
- async _exitCpMode ( commitState : boolean ) : Promise < void > {
115
- return new Promise ( ( resolve ) => {
116
- const scratch = this . _scratch as ScratchDB
117
- this . _scratch = null
118
- this . db = this . _mainDB
119
-
120
- if ( commitState ) {
121
- this . _createScratchReadStream ( scratch )
122
- . pipe ( WriteStream ( this . db . _leveldb ) )
123
- . on ( 'close' , resolve )
124
- } else {
125
- process . nextTick ( resolve )
126
- }
127
- } )
128
- }
129
-
130
- /**
131
- * Returns a `ScratchReadStream` based on the state updates
132
- * since checkpoint.
133
- * @private
134
- */
135
- _createScratchReadStream ( scratchDb ?: ScratchDB ) {
136
- const scratch = scratchDb || this . _scratch
137
- if ( ! scratch ) {
138
- throw new Error ( 'No scratch found to use' )
139
- }
140
- const trie = new BaseTrie ( scratch . _leveldb , this . root )
141
- trie . db = scratch
142
- return new ScratchReadStream ( trie )
143
- }
144
68
}
0 commit comments