this.mutex = new Mutex()
this.log = null
this.eof = 0
- this.value = [-1, 0]
+ this.value = undefined
}
- async open(path, default_value) {
+ async open(path) {
await this.mutex.acquire()
assert(this.log === null)
if (error.code !== 'ENOENT')
throw error
+ console.log('warning: can\'t find database file, creating')
+
this.log = await fsPromises.open(path, 'w+')
this.eof = 0
+ this.value = undefined
- this.value = await this.write(default_value, true)
+ this.mutex.release()
return
}
this.eof = (await this.log.stat()).size
- this.value = await this.find_root()
+ try {
+ this.value = await this.find_root()
+ }
+ catch (error) {
+ console.log('warning: can\'t find root, truncating database file')
+
+ await this.log.truncate(0)
+ this.eof = 0
+ this.value = undefined
+
+ this.mutex.release()
+ return
+ }
// optional: trim any garbage off the end of the file
let [ptr, len] = this.value
- this.eof = ptr + len + 2
- await this.log.truncate(this.eof)
+ let eof = ptr + len + 2
+ if (eof < this.eof) {
+ console.log('warning: garbage after root, truncating database file')
+
+ await this.log.truncate(eof)
+ this.eof = eof
+ }
this.mutex.release()
}
throw new Error('can\'t find logjson end marker')
}
- async write(value, is_root) {
- if (typeof value === 'object' && value !== null)
- if (value instanceof Array) {
- let new_value = []
- for (let i = 0; i < value.length; ++i) {
- let item = value[i]
- //if (typeof item === 'object' && item !== null)
- item = await this.write(item, false)
- new_value.push(item)
- }
- value = new_value
- }
- else {
- let new_value = {}
- for (let i in value) {
- let item = value[i]
- //if (typeof item === 'object' && item !== null)
- item = await this.write(item, false)
- new_value[i] = item
- }
- value = new_value
- }
-
- let data = JSON.stringify(value, null, 2)
- if (is_root) {
- let buffer = Buffer.from(`<${data}>\n`, 'utf-8')
- let ptr = this.eof
- let len = buffer.length
- assert(
- (await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
- )
- this.eof += len
- return [ptr + 1, len - 3] // ptr, len
+ async get(default_value) {
+ if (this.value === undefined) {
+ if (default_value === undefined)
+ return undefined
+ set(default_value)
}
- let buffer = Buffer.from(`${data}\n`, 'utf-8')
- let ptr = this.eof
- let len = buffer.length
- assert(
- (await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
- )
- this.eof += len
- return [ptr, len - 1] // ptr, len
- }
-
- async get() {
let value = this.value
//if (value instanceof Array) {
}
async flush() {
+ if (this.value === undefined)
+ return
+
//if (this.value instanceof Array) {
let [ptr, len, value] = this.value
if (
async get(key, default_value) {
assert(typeof key === 'number')
- if (key < 0 || key >= this.length)
- return default_value
+ if (key < 0 || key >= this.length) {
+ if (default_value === undefined)
+ return undefined
+ set(key, default_value)
+ }
let value = this.array[key]
//if (value instanceof Array) {
async get(key, default_value) {
assert(typeof key === 'string')
- if (!Object.prototype.hasOwnProperty.call(this.object, key))
- return default_value
+ if (!Object.prototype.hasOwnProperty.call(this.object, key)) {
+ if (default_value === undefined)
+ return undefined
+ set(key, default_value)
+ }
let value = this.object[key]
//if (value instanceof Array) {