let open_angle = Buffer.from('\n<', 'utf-8')
let close_angle = Buffer.from('>\n', 'utf-8')
class Database {
- constructor(read_timeout, write_timeout) {
+ constructor(read_timeout, write_timeout, block_size) {
this.read_timeout = read_timeout || 3600
this.write_timeout = write_timeout || 5
+ this.block_size = block_size || 0x1000
this.mutex = new Mutex()
this.log = null
- this.eof = 0 // before write_list
- this.eof1 = 0 // after write_list
+ this.eof = 0
this.value = undefined
this.read_cache = {}
this.write_list = []
+ this.write_list_len = 0
this.write_count = 0
}
assert(this.log === null)
this.eof = 0 // before write_list
- this.eof1 = 0 // after write_list
this.value = undefined
this.read_cache = {}
this.write_list = []
+ this.write_list_len = 0
this.write_count = 0
try {
return
}
- this.eof = this.eof1 = (await this.log.stat()).size
+ this.eof = (await this.log.stat()).size
let eof_buffer
try {
eof_buffer = await (
async () => {
- let ptr = this.eof & ~0xfff
- let count = this.eof & 0xfff
- let buffer = Buffer.alloc(0x1001)
+ let ptr = this.eof & ~(this.block_size - 1)
+ let count = this.eof & (this.block_size - 1)
+ let buffer = Buffer.alloc(this.block_size + 1)
assert(
(await this.log.read(buffer, 0, count, ptr)).bytesRead === count
)
if (ptr === 0)
break
- ptr -= 0x1000
+ ptr -= this.block_size
if (count) {
- buffer[0x1000] = buffer[0]
- count = 0x1001
+ buffer[this.block_size] = buffer[0]
+ count = this.block_size + 1
}
else
- count = 0x1000
+ count = this.block_size
assert(
- (await this.log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000
+ (await this.log.read(buffer, 0, this.block_size, ptr)).bytesRead === this.block_size
)
- blocks.push(buffer.slice(0, 0x1000))
+ blocks.push(buffer.slice(0, this.block_size))
}
// special case for < at start of database
if (ptr === 0)
break
- ptr -= 0x1000
+ ptr -= this.block_size
if (count) {
- buffer[0x1000] = buffer[0]
- count = 0x1001
+ buffer[this.block_size] = buffer[0]
+ count = this.block_size + 1
}
else
- count = 0x1000
+ count = this.block_size
assert(
- (await this.log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000
+ (await this.log.read(buffer, 0, this.block_size, ptr)).bytesRead === this.block_size
)
}
console.log('warning: garbage after root, truncating database file')
await this.log.truncate(eof)
this.eof = eof
- this.eof1 = eof
}
this.mutex.release()
'utf-8'
)
- let ptr = this.eof1
+ let ptr = this.eof + this.write_list_len
let len = buffer.length
//console.log('addw', ptr)
this.read_cache[ptr] = new CachedValue(1, value, this.read_timeout)
this.write_list.push(buffer)
- this.eof1 += len
+ this.write_list_len += len
return [ptr, len - 1]
}
'utf-8'
)
this.write_list.push(buffer)
- this.eof1 += buffer.length
+ this.write_list_len += buffer.length
}
async flush() {
// hold mutex whilst calling this function
let ptr = this.eof, len = 0, i = 0, j = 0
for (; j < this.write_list.length; ++j) {
- if (len >= 0x1000) {
+ if (len >= this.block_size) {
let buffer = Buffer.concat(this.write_list.slice(i, j))
assert(buffer.length === len)
assert(
(await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
)
ptr += len
- assert(ptr === this.eof1)
+ assert(ptr === this.eof + this.write_list_len)
// each block in write list is also pinned in read cache, unpin
// note: do this afterwards as needs to be on disk when unpinned
}
ptr += this.write_list[i].length
}
- assert(ptr === this.eof1)
+ assert(ptr === this.eof + this.write_list_len)
this.eof = ptr
this.write_list = []
+ this.write_list_len = 0
}
Transaction() {