Make a Transaction object, temporarily removes caching ability (Transaction object...
authorNick Downing <nick@ndcode.org>
Thu, 6 Jan 2022 01:44:17 +0000 (12:44 +1100)
committerNick Downing <nick@ndcode.org>
Thu, 6 Jan 2022 08:43:24 +0000 (19:43 +1100)
a.mjs
b.mjs
logjson.mjs

diff --git a/a.mjs b/a.mjs
index 8855713..bdebdf2 100755 (executable)
--- a/a.mjs
+++ b/a.mjs
@@ -5,10 +5,11 @@ import fsPromises from 'fs/promises'
 
 let database = new logjson.Database()
 await database.open('a.logjson')
-database.set(
-  database.json_to_logjson(
+let transaction = database.Transaction()
+transaction.set(
+  transaction.json_to_logjson(
     JSON.parse(await fsPromises.readFile('random.json', 'utf-8'))
   )
 )
-await database.flush()
+await transaction.commit()
 await database.close()
diff --git a/b.mjs b/b.mjs
index 41883ba..b47c9aa 100755 (executable)
--- a/b.mjs
+++ b/b.mjs
@@ -5,15 +5,17 @@ import fsPromises from 'fs/promises'
 
 let database = new logjson.Database()
 await database.open('a.logjson')
+let transaction = database.Transaction()
 await fsPromises.writeFile(
   'a.json',
   Buffer.from(
     JSON.stringify(
-      await logjson.logjson_to_json(await database.get()),
+      await logjson.logjson_to_json(await transaction.get()),
       null,
       2
     ) + '\n',
     'utf-8'
   )
 )
+transaction.rollback()
 await database.close()
index f51049e..aaf1726 100644 (file)
@@ -9,7 +9,6 @@ class Database {
     this.mutex = new Mutex()
     this.log = null
     this.eof = 0
-    this.dirty = false
     this.value = undefined
   }
 
@@ -28,7 +27,6 @@ class Database {
 
       this.log = await fsPromises.open(path, 'w+')
       this.eof = 0
-      this.dirty = false
       this.value = undefined
 
       this.mutex.release()
@@ -36,7 +34,6 @@ class Database {
     }
 
     this.eof = (await this.log.stat()).size
-    this.dirty = false
     try {
       this.value = await this.find_root()
     }
@@ -65,8 +62,6 @@ class Database {
   }
 
   async close() {
-    this.flush()
-
     await this.mutex.acquire()
     assert(this.log !== null)
 
@@ -133,6 +128,19 @@ class Database {
     throw new Error('can\'t find logjson end marker')
   }
 
+  Transaction() {
+    this.mutex.acquire()
+    return new Transaction(this, this.value)
+  }
+}
+
+class Transaction {
+  constructor(database, value) {
+    this.database = database
+    this.dirty = false
+    this.value = value
+  }
+
   async get(default_value) {
     if (this.value === undefined) {
       if (default_value === undefined)
@@ -146,7 +154,7 @@ class Database {
       if (new_value === undefined) {
         let buffer = Buffer.alloc(len)
         assert(
-          (await this.log.read(buffer, 0, len, ptr)).bytesRead === len
+          (await this.database.log.read(buffer, 0, len, ptr)).bytesRead === len
         )
         new_value = JSON.parse(buffer.toString('utf-8'))
         if (typeof new_value === 'object' && new_value !== null)
@@ -165,23 +173,18 @@ class Database {
     //assert(
     //  typeof value !== 'object' ||
     //  value === null ||
-    //  (value instanceof Lazy && value.database === this)
+    //  (value instanceof Lazy && value.transaction === this)
     //)
     this.dirty = true
     if (typeof value === 'object' && value !== null) {
-      assert(value instanceof Lazy && value.database === this)
+      assert(value instanceof Lazy && value.transaction === this)
       value = [-1, 0, value]
     }
     this.value = value
   }
 
-  async flush() {
-    await this.mutex.acquire()
-
-    if (this.value === undefined) {
-      await this.mutex.release()
-      return
-    }
+  async commit() {
+    assert(this.value !== undefined)
 
     if (this.value instanceof Array) {
       let [ptr, len, value] = this.value
@@ -193,16 +196,14 @@ class Database {
           'utf-8'
         )
 
-        ptr = this.eof
+        ptr = this.database.eof
         len = buffer.length
         assert(
-          (await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
+          (await this.database.log.write(buffer, 0, len, ptr)).bytesWritten === len
         )
-        this.eof += len
+        this.database.eof += len
   
-        this.value[0] = ptr + 1
-        this.value[1] = len - 3
-        //this.dirty = true
+        this.database.value = [ptr + 1, len - 3]
       }
     }
     else if (this.dirty) {
@@ -211,16 +212,21 @@ class Database {
         'utf-8'
       )
 
-      ptr = this.eof
+      ptr = this.database.eof
       len = buffer.length
       assert(
-        (await this.log.write(buffer, 0, len, ptr)).bytesWritten === len
+        (await this.database.log.write(buffer, 0, len, ptr)).bytesWritten === len
       )
-      this.eof += len
+      this.database.eof += len
+
+      this.database.value = this.value
     }
 
-    this.dirty = false
-    this.mutex.release()
+    this.database.mutex.release()
+  }
+
+  rollback() {
+    this.database.mutex.release()
   }
 
   LazyArray(...args) {
@@ -252,8 +258,8 @@ class Database {
 
 // logjson array or object
 class Lazy {
-  constructor(database) {
-    this.database = database
+  constructor(transaction) {
+    this.transaction = transaction
     this.dirty = false
   }
 
@@ -283,8 +289,8 @@ class Lazy {
 }
 
 class LazyArray extends Lazy {
-  constructor(database, array) {
-    super(database)
+  constructor(transaction, array) {
+    super(transaction)
     this.array = array || []
     this.length = this.array.length
   }
@@ -308,14 +314,14 @@ class LazyArray extends Lazy {
       if (new_value === undefined) {
         let buffer = Buffer.alloc(len)
         assert(
-          (await this.database.log.read(buffer, 0, len, ptr)).bytesRead === len
+          (await this.transaction.database.log.read(buffer, 0, len, ptr)).bytesRead === len
         )
         new_value = JSON.parse(buffer.toString('utf-8'))
         if (typeof new_value === 'object' && new_value !== null)
           new_value =
             new_value instanceof Array ?
-              new LazyArray(this.database, new_value) :
-              new LazyObject(this.database, new_value)
+              new LazyArray(this.transaction, new_value) :
+              new LazyObject(this.transaction, new_value)
         value[2] = new_value
       }
       value = new_value
@@ -328,11 +334,11 @@ class LazyArray extends Lazy {
     //assert(
     //  typeof value !== 'object' ||
     //  value === null ||
-    //  (value instanceof Lazy && value.database === this.database)
+    //  (value instanceof Lazy && value.transaction === this.transaction)
     //)
     this.dirty = true
     if (typeof value === 'object' && value !== null) {
-      assert(value instanceof Lazy && value.database === this.database)
+      assert(value instanceof Lazy && value.transaction === this.transaction)
       value = [-1, 0, value]
     }
     this.array[key] = value
@@ -369,13 +375,13 @@ class LazyArray extends Lazy {
             'utf-8'
           )
 
-          ptr = this.database.eof
+          ptr = this.transaction.database.eof
           len = buffer.length
           assert(
-            (await this.database.log.write(buffer, 0, len, ptr)).bytesWritten ===
+            (await this.transaction.database.log.write(buffer, 0, len, ptr)).bytesWritten ===
               len
           )
-          this.database.eof += len
+          this.transaction.database.eof += len
 
           item[0] = ptr
           item[1] = len - 1
@@ -401,8 +407,8 @@ class LazyArray extends Lazy {
 }
 
 class LazyObject extends Lazy {
-  constructor(database, object) {
-    super(database)
+  constructor(transaction, object) {
+    super(transaction)
     this.object = object || {}
   }
 
@@ -425,14 +431,14 @@ class LazyObject extends Lazy {
       if (new_value === undefined) {
         let buffer = Buffer.alloc(len)
         assert(
-          (await this.database.log.read(buffer, 0, len, ptr)).bytesRead === len
+          (await this.transaction.database.log.read(buffer, 0, len, ptr)).bytesRead === len
         )
         new_value = JSON.parse(buffer.toString('utf-8'))
         if (typeof new_value === 'object' && new_value !== null)
           new_value =
             new_value instanceof Array ?
-              new LazyArray(this.database, new_value) :
-              new LazyObject(this.database, new_value)
+              new LazyArray(this.transaction, new_value) :
+              new LazyObject(this.transaction, new_value)
         value[2] = new_value
       }
       value = new_value
@@ -445,11 +451,11 @@ class LazyObject extends Lazy {
     //assert(
     //  typeof value !== 'object' ||
     //  value === null ||
-    //  (value instanceof Lazy && value.database === this.database)
+    //  (value instanceof Lazy && value.transaction === this.transaction)
     //)
     this.dirty = true
     if (typeof value === 'object' && value !== null) {
-      assert(value instanceof Lazy && value.database === this.database)
+      assert(value instanceof Lazy && value.transaction === this.transaction)
       value = [-1, 0, value]
     }
     this.object[key] = value
@@ -479,13 +485,13 @@ class LazyObject extends Lazy {
             'utf-8'
           )
 
-          ptr = this.database.eof
+          ptr = this.transaction.database.eof
           len = buffer.length
           assert(
-            (await this.database.log.write(buffer, 0, len, ptr)).bytesWritten ===
+            (await this.transaction.database.log.write(buffer, 0, len, ptr)).bytesWritten ===
               len
           )
-          this.database.eof += len
+          this.transaction.database.eof += len
 
           item[0] = ptr
           item[1] = len