1
1
import { LevelUp } from 'levelup'
2
- import { DB } from './db'
3
- const level = require ( 'level-mem' )
2
+ import { DB , BatchDBOp } from './db'
4
3
5
4
export const ENCODING_OPTS = { keyEncoding : 'binary' , valueEncoding : 'binary' }
6
5
7
6
export type Checkpoint = {
8
- keyValueMap : Map < Buffer , Buffer | null > ,
7
+ // We cannot use a Buffer => Buffer map directly. If you create two Buffers with the same internal value,
8
+ // then when setting a value on the Map, it actually creates two indices.
9
+ keyValueMap : Map < string , Buffer | null >
9
10
root : Buffer
10
11
}
11
12
12
- export type BatchDBOp = PutBatch | DelBatch
13
- export interface PutBatch {
14
- type : 'put'
15
- key : Buffer
16
- value : Buffer
17
- }
18
- export interface DelBatch {
19
- type : 'del'
20
- key : Buffer
21
- }
22
-
23
13
/**
24
14
* DB is a thin wrapper around the underlying levelup db,
25
15
* which validates inputs and sets encoding type.
@@ -50,7 +40,7 @@ export class CheckpointDB extends DB {
50
40
* @param root
51
41
*/
52
42
checkpoint ( root : Buffer ) {
53
- this . checkpoints . push ( { keyValueMap : new Map < Buffer , Buffer > ( ) , root } )
43
+ this . checkpoints . push ( { keyValueMap : new Map < string , Buffer > ( ) , root } )
54
44
}
55
45
56
46
/**
@@ -61,38 +51,36 @@ export class CheckpointDB extends DB {
61
51
if ( ! this . isCheckpoint ) {
62
52
// This was the final checkpoint, we should now commit and flush everything to disk
63
53
const batchOp : BatchDBOp [ ] = [ ]
64
- keyValueMap . forEach ( function ( value , key ) {
54
+ keyValueMap . forEach ( function ( value , key ) {
65
55
if ( value === null ) {
66
56
batchOp . push ( {
67
57
type : 'del' ,
68
- key
58
+ key : Buffer . from ( key ) ,
69
59
} )
70
60
} else {
71
61
batchOp . push ( {
72
62
type : 'put' ,
73
- key,
74
- value
63
+ key : Buffer . from ( key ) ,
64
+ value,
75
65
} )
76
66
}
77
67
} )
78
68
await this . batch ( batchOp )
79
69
} else {
80
70
// dump everything into the current (higher level) cache
81
71
const currentKeyValueMap = this . checkpoints [ this . checkpoints . length - 1 ] . keyValueMap
82
- keyValueMap . forEach ( function ( value , key ) {
72
+ keyValueMap . forEach ( function ( value , key ) {
83
73
currentKeyValueMap . set ( key , value )
84
74
} )
85
-
86
75
}
87
-
88
76
}
89
77
90
78
/**
91
79
* Reverts the latest checkpoint
92
80
*/
93
81
async revert ( ) {
94
- const { root } = this . checkpoints . pop ( ) !
95
- return root
82
+ const { root } = this . checkpoints . pop ( ) !
83
+ return root
96
84
}
97
85
98
86
/**
@@ -102,14 +90,14 @@ export class CheckpointDB extends DB {
102
90
*/
103
91
async get ( key : Buffer ) : Promise < Buffer | null > {
104
92
// Lookup the value in our cache. We return the latest checkpointed value (which should be the value on disk)
105
- for ( let index = this . checkpoints . length ; index >= 0 ; index -- ) {
106
- const value = this . checkpoints [ index ] . keyValueMap . get ( key )
107
- if ( value != undefined ) {
93
+ for ( let index = this . checkpoints . length - 1 ; index >= 0 ; index -- ) {
94
+ const value = this . checkpoints [ index ] . keyValueMap . get ( key . toString ( ) )
95
+ if ( value !== undefined ) {
108
96
return value
109
97
}
110
98
}
111
99
// Nothing has been found in cache, look up from disk
112
- // TODO: put value in cache.
100
+ // TODO: put value in cache if we are a checkpoint .
113
101
return await super . get ( key )
114
102
}
115
103
@@ -120,9 +108,9 @@ export class CheckpointDB extends DB {
120
108
*/
121
109
async put ( key : Buffer , val : Buffer ) : Promise < void > {
122
110
if ( this . isCheckpoint ) {
123
- // put value in cache
124
- this . checkpoints [ this . checkpoints . length - 1 ] . keyValueMap . set ( key , val )
125
- } else {
111
+ // put value in cache
112
+ this . checkpoints [ this . checkpoints . length - 1 ] . keyValueMap . set ( key . toString ( ) , val )
113
+ } else {
126
114
await super . put ( key , val )
127
115
}
128
116
}
@@ -134,7 +122,7 @@ export class CheckpointDB extends DB {
134
122
async del ( key : Buffer ) : Promise < void > {
135
123
if ( this . isCheckpoint ) {
136
124
// delete the value in the current cache
137
- this . checkpoints [ this . checkpoints . length - 1 ] . keyValueMap . set ( key , null )
125
+ this . checkpoints [ this . checkpoints . length - 1 ] . keyValueMap . set ( key . toString ( ) , null )
138
126
} else {
139
127
// delete the value on disk
140
128
await this . _leveldb . del ( key , ENCODING_OPTS )
0 commit comments