--- /dev/null
+class CachedValue {
+ constructor(refs, value, stale_count) {
+ this.refs = refs
+ this.value = value
+ this.stale_count = stale_count
+ }
+}
+
+export default CachedValue
import assert from 'assert'
import fsPromises from 'fs/promises'
+import CachedValue from './CachedValue.mjs'
import Mutex from './Mutex.mjs'
-
-class CachedValue {
- constructor(refs, value, stale_count) {
- this.refs = refs
- this.value = value
- this.stale_count = stale_count
- }
-}
+import Transaction from './Transaction.mjs'
let open_angle = Buffer.from('\n<', 'utf-8')
let close_angle = Buffer.from('>\n', 'utf-8')
}
}
-class Transaction {
- constructor(database, value) {
- assert(database instanceof Database)
- this.database = database
- this.dirty = false
- this.value = value
- }
-
- async read(ptr_len) {
- let value = await this.database.read(ptr_len)
- if (typeof value === 'object' && value !== null)
- value =
- value instanceof Array ?
- new LazyArray(this, ptr_len, value) :
- new LazyObject(this, ptr_len, value)
- return value
- }
-
- async get(default_value) {
- if (this.value === undefined) {
- if (default_value === undefined)
- return undefined
- set(default_value)
- }
-
- if (this.value instanceof Array)
- this.value = this.read(this.value)
- return this.value
- }
-
- set(value) {
- this.dirty = true
- assert(
- typeof value !== 'object' ||
- value === null ||
- (value instanceof Lazy && value.transaction === this)
- )
- this.value = value
- }
-
- async commit() {
- assert(this.value !== undefined)
-
- if (this.value instanceof Lazy) {
- if (await this.value.commit())
- this.dirty = true
- this.value = this.value.ptr_len
- }
-
- if (this.dirty) {
- this.database.write_root(this.value)
- this.database.value = this.value
- }
-
- if (
- this.database.eof1 > this.database.eof &&
- this.database.write_count === 0
- ) {
- if (this.database.write_timeout === 0)
- await this.database.flush()
- else
- this.database.write_count = this.database.write_timeout
- }
-
- this.database.mutex.release()
- }
-
- rollback() {
- this.database.mutex.release()
- }
-
- LazyArray(...args) {
- return new LazyArray(this, null, ...args)
- }
-
- LazyObject(...args) {
- return new LazyObject(this, null, ...args)
- }
-
- json_to_logjson(value) {
- if (typeof value === 'object' && value !== null) {
- let new_value
- if (value instanceof Array) {
- new_value = new LazyArray(this)
- for (let i = 0; i < value.length; ++i)
- new_value.push(this.json_to_logjson(value[i]))
- }
- else {
- new_value = new LazyObject(this)
- for (let i in value)
- new_value.set(i, this.json_to_logjson(value[i]))
- }
- value = new_value
- }
- return value
- }
-}
-
-// logjson array or object
-class Lazy {
- constructor(transaction, ptr_len) {
- assert(transaction instanceof Transaction)
- this.transaction = transaction
- this.ptr_len = ptr_len || null
- }
-
- has(key) {
- throw new Error('not implemented')
- }
-
- async get(key, default_value) {
- throw new Error('not implemented')
- }
-
- set(key, value) {
- throw new Error('not implemented')
- }
-
- delete(key) {
- throw new Error('not implemented')
- }
-
- async commit() {
- throw new Error('not implemented')
- }
-}
-
-class LazyArray extends Lazy {
- constructor(transaction, ptr_len, array) {
- super(transaction, ptr_len)
- this.array = array || []
- this.length = this.array.length
- }
-
- has(key) {
- assert(typeof key === 'number')
- return key >= 0 && key < this.length
- }
-
- async get(key, default_value) {
- assert(typeof key === 'number')
- 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) {
- value = this.transaction.read(value)
- this.array[key] = value
- }
- return value
- }
-
- set(key, value) {
- assert(typeof key === 'number')
- assert(
- typeof value !== 'object' ||
- value === null ||
- (value instanceof Lazy && value.transaction === this.transaction)
- )
- this.ptr_len = null // mark dirty
- this.array[key] = value
- this.length = this.array.length
- }
-
- delete(key) {
- delete this.array[key]
- }
-
- push(value) {
- this.set(this.length, value)
- }
-
- async pop() {
- assert(this.length)
- this.length -= 1
- let value = await this.get(this.length)
- this.delete(this.length)
- return value
- }
-
- async commit() {
- for (let i = 0; i < this.length; ++i) {
- let value = this.array[i]
- if (value instanceof Lazy) {
- if (await value.commit())
- this.ptr_len = null // mark dirty
- this.array[i] = value.ptr_len
- }
- }
-
- if (this.ptr_len === null) {
- this.ptr_len = this.transaction.database.write(this.array)
- return true
- }
- return false
- }
-}
-
-class LazyObject extends Lazy {
- constructor(transaction, ptr_len, object) {
- super(transaction, ptr_len)
- this.object = object || {}
- }
-
- has(key) {
- assert(typeof key === 'string')
- return Object.prototype.hasOwnProperty.call(this.object, key)
- }
-
- async get(key, default_value) {
- assert(typeof key === 'string')
- 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) {
- value = this.transaction.read(value)
- this.object[key] = value
- }
- return value
- }
-
- set(key, value) {
- assert(typeof key === 'string')
- assert(
- typeof value !== 'object' ||
- value === null ||
- (value instanceof Lazy && value.transaction === this.transaction)
- )
- this.ptr_len = null // mark dirty
- this.object[key] = value
- }
-
- delete(key) {
- delete this.object[key]
- }
-
- keys() {
- let keys = []
- for (let i in this.object)
- keys.push(i)
- return keys
- }
-
- async commit() {
- for (let i in this.object) {
- let value = this.object[i]
- if (value instanceof Lazy) {
- if (await value.commit())
- this.ptr_len = null // mark dirty
- this.object[i] = value.ptr_len
- }
- }
-
- if (this.ptr_len === null) {
- this.ptr_len = this.transaction.database.write(this.object)
- return true
- }
- return false
- }
-}
-
-let logjson_to_json = async value => {
- if (value instanceof Lazy) {
- let new_value
- if (value instanceof LazyArray) {
- new_value = []
- for (let i = 0; i < value.length; ++i)
- new_value.push(await logjson_to_json(await value.get(i)))
- }
- else {
- new_value = {}
- let keys = value.keys()
- for (let i = 0; i < keys.length; ++i) {
- let key = keys[i]
- new_value[key] = await logjson_to_json(await value.get(key))
- }
- }
- value = new_value
- }
- return value
-}
-
-export default {
- Database,
- Lazy,
- LazyArray,
- LazyObject,
- logjson_to_json
-}
+export default Database
--- /dev/null
+import assert from 'assert'
+import Transaction from './Transaction.mjs'
+
+class Lazy {
+ constructor(transaction, ptr_len) {
+ assert(transaction instanceof Transaction)
+ this.transaction = transaction
+ this.ptr_len = ptr_len || null
+ }
+
+ has(key) {
+ throw new Error('not implemented')
+ }
+
+ async get(key, default_value) {
+ throw new Error('not implemented')
+ }
+
+ set(key, value) {
+ throw new Error('not implemented')
+ }
+
+ delete(key) {
+ throw new Error('not implemented')
+ }
+
+ async commit() {
+ throw new Error('not implemented')
+ }
+}
+
+export default Lazy
--- /dev/null
+import assert from 'assert'
+import Lazy from './Lazy.mjs'
+
+class LazyArray extends Lazy {
+ constructor(transaction, ptr_len, array) {
+ super(transaction, ptr_len)
+ this.array = array || []
+ this.length = this.array.length
+ }
+
+ has(key) {
+ assert(typeof key === 'number')
+ return key >= 0 && key < this.length
+ }
+
+ async get(key, default_value) {
+ assert(typeof key === 'number')
+ 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) {
+ value = this.transaction.read(value)
+ this.array[key] = value
+ }
+ return value
+ }
+
+ set(key, value) {
+ assert(typeof key === 'number')
+ assert(
+ typeof value !== 'object' ||
+ value === null ||
+ (value instanceof Lazy && value.transaction === this.transaction)
+ )
+ this.ptr_len = null // mark dirty
+ this.array[key] = value
+ this.length = this.array.length
+ }
+
+ delete(key) {
+ delete this.array[key]
+ }
+
+ push(value) {
+ this.set(this.length, value)
+ }
+
+ async pop() {
+ assert(this.length)
+ this.length -= 1
+ let value = await this.get(this.length)
+ this.delete(this.length)
+ return value
+ }
+
+ async commit() {
+ for (let i = 0; i < this.length; ++i) {
+ let value = this.array[i]
+ if (value instanceof Lazy) {
+ if (await value.commit())
+ this.ptr_len = null // mark dirty
+ this.array[i] = value.ptr_len
+ }
+ }
+
+ if (this.ptr_len === null) {
+ this.ptr_len = this.transaction.database.write(this.array)
+ return true
+ }
+ return false
+ }
+}
+
+export default LazyArray
--- /dev/null
+import assert from 'assert'
+import Lazy from './Lazy.mjs'
+
+class LazyObject extends Lazy {
+ constructor(transaction, ptr_len, object) {
+ super(transaction, ptr_len)
+ this.object = object || {}
+ }
+
+ has(key) {
+ assert(typeof key === 'string')
+ return Object.prototype.hasOwnProperty.call(this.object, key)
+ }
+
+ async get(key, default_value) {
+ assert(typeof key === 'string')
+ 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) {
+ value = this.transaction.read(value)
+ this.object[key] = value
+ }
+ return value
+ }
+
+ set(key, value) {
+ assert(typeof key === 'string')
+ assert(
+ typeof value !== 'object' ||
+ value === null ||
+ (value instanceof Lazy && value.transaction === this.transaction)
+ )
+ this.ptr_len = null // mark dirty
+ this.object[key] = value
+ }
+
+ delete(key) {
+ delete this.object[key]
+ }
+
+ keys() {
+ let keys = []
+ for (let i in this.object)
+ keys.push(i)
+ return keys
+ }
+
+ async commit() {
+ for (let i in this.object) {
+ let value = this.object[i]
+ if (value instanceof Lazy) {
+ if (await value.commit())
+ this.ptr_len = null // mark dirty
+ this.object[i] = value.ptr_len
+ }
+ }
+
+ if (this.ptr_len === null) {
+ this.ptr_len = this.transaction.database.write(this.object)
+ return true
+ }
+ return false
+ }
+}
+
+export default LazyObject
--- /dev/null
+import assert from 'assert'
+import fsPromises from 'fs/promises'
+import Database from './Database.mjs'
+import Lazy from './Lazy.mjs'
+import LazyArray from './LazyArray.mjs'
+import LazyObject from './LazyObject.mjs'
+
+class Transaction {
+ constructor(database, value) {
+ assert(database instanceof Database)
+ this.database = database
+ this.dirty = false
+ this.value = value
+ }
+
+ async read(ptr_len) {
+ let value = await this.database.read(ptr_len)
+ if (typeof value === 'object' && value !== null)
+ value =
+ value instanceof Array ?
+ new LazyArray(this, ptr_len, value) :
+ new LazyObject(this, ptr_len, value)
+ return value
+ }
+
+ async get(default_value) {
+ if (this.value === undefined) {
+ if (default_value === undefined)
+ return undefined
+ set(default_value)
+ }
+
+ if (this.value instanceof Array)
+ this.value = this.read(this.value)
+ return this.value
+ }
+
+ set(value) {
+ this.dirty = true
+ assert(
+ typeof value !== 'object' ||
+ value === null ||
+ (value instanceof Lazy && value.transaction === this)
+ )
+ this.value = value
+ }
+
+ async commit() {
+ assert(this.value !== undefined)
+
+ if (this.value instanceof Lazy) {
+ if (await this.value.commit())
+ this.dirty = true
+ this.value = this.value.ptr_len
+ }
+
+ if (this.dirty) {
+ this.database.write_root(this.value)
+ this.database.value = this.value
+ }
+
+ if (
+ this.database.eof1 > this.database.eof &&
+ this.database.write_count === 0
+ ) {
+ if (this.database.write_timeout === 0)
+ await this.database.flush()
+ else
+ this.database.write_count = this.database.write_timeout
+ }
+
+ this.database.mutex.release()
+ }
+
+ rollback() {
+ this.database.mutex.release()
+ }
+
+ LazyArray(...args) {
+ return new LazyArray(this, null, ...args)
+ }
+
+ LazyObject(...args) {
+ return new LazyObject(this, null, ...args)
+ }
+
+ json_to_logjson(value) {
+ if (typeof value === 'object' && value !== null) {
+ let new_value
+ if (value instanceof Array) {
+ new_value = new LazyArray(this)
+ for (let i = 0; i < value.length; ++i)
+ new_value.push(this.json_to_logjson(value[i]))
+ }
+ else {
+ new_value = new LazyObject(this)
+ for (let i in value)
+ new_value.set(i, this.json_to_logjson(value[i]))
+ }
+ value = new_value
+ }
+ return value
+ }
+}
+
+export default Transaction
--- /dev/null
+import Database from './Database.mjs'
+import Lazy from './Lazy.mjs'
+import LazyArray from './LazyArray.mjs'
+import LazyObject from './LazyObject.mjs'
+
+let logjson_to_json = async value => {
+ if (value instanceof Lazy) {
+ let new_value
+ if (value instanceof LazyArray) {
+ new_value = []
+ for (let i = 0; i < value.length; ++i)
+ new_value.push(await logjson_to_json(await value.get(i)))
+ }
+ else {
+ new_value = {}
+ let keys = value.keys()
+ for (let i = 0; i < keys.length; ++i) {
+ let key = keys[i]
+ new_value[key] = await logjson_to_json(await value.get(key))
+ }
+ }
+ value = new_value
+ }
+ return value
+}
+
+export default {
+ Database,
+ Lazy,
+ LazyArray,
+ LazyObject,
+ logjson_to_json
+}
#!/usr/bin/env node
-import logjson from '../logjson.mjs'
+import logjson from '../index.mjs'
import fsPromises from 'fs/promises'
let database = new logjson.Database(5, 1)
#!/usr/bin/env node
-import logjson from '../logjson.mjs'
+import logjson from '../index.mjs'
import fsPromises from 'fs/promises'
let database = new logjson.Database()