Fix bug with modifying the cache values causing Transaction.rollback() to fail
authorNick Downing <nick@ndcode.org>
Thu, 13 Jan 2022 04:14:53 +0000 (15:14 +1100)
committerNick Downing <nick@ndcode.org>
Thu, 13 Jan 2022 04:19:08 +0000 (15:19 +1100)
Database.mjs
Transaction.mjs

index 01db430..471fe16 100644 (file)
@@ -21,6 +21,7 @@ class Database {
     this.write_list = []
     this.write_list_len = 0
     this.write_count = 0
+    //this.serial = 0
   }
 
   async open(path) {
@@ -155,25 +156,40 @@ class Database {
     // hold mutex whilst calling this function
     let [ptr, len] = ptr_len
 
+    let value
     if (Object.prototype.hasOwnProperty.call(this.read_cache, ptr)) {
       //console.log('hit', ptr)
       let cached_value = this.read_cache[ptr]
       cached_value.stale_count = this.read_timeout
-      return cached_value.value
+      value = cached_value.value
     }
-
-    let buffer = Buffer.alloc(len)
-    assert(
-      (await this.log.read(buffer, 0, len, ptr)).bytesRead === len
-    )
-    let value = JSON.parse(buffer.toString('utf-8'))
-
-    if (this.read_timeout) //{
+    else {
+      let buffer = Buffer.alloc(len)
+      assert(
+        (await this.log.read(buffer, 0, len, ptr)).bytesRead === len
+      )
+      value = JSON.parse(buffer.toString('utf-8'))
+
+      if (!this.read_timeout)
+        return value
       //console.log('add', ptr)
       this.read_cache[ptr] = new CachedValue(0, value, this.read_timeout)
-    //}
+    }
 
-    return value
+    // value is from cache, copy it
+    assert(typeof value === 'object' && value !== null)
+    let new_value
+    if (value instanceof Array) {
+      new_value = []
+      for (let i = 0; i < value.length; ++i)
+        new_value.push(value[i])
+    }
+    else {
+      new_value = {}
+      for (let i in value)
+        new_value[i] = value[i]
+    }
+    return new_value
   }
 
   async write(value) {
@@ -243,6 +259,11 @@ class Database {
 
   async Transaction() {
     await this.mutex.acquire()
+    //let transaction = new Transaction(this, this.value)
+    //transaction.serial = this.serial
+    //this.serial += 1
+    //console.log('create transaction', transaction.serial)
+    //return transaction
     return new Transaction(this, this.value)
   }
 
index ad5e497..9edfeae 100644 (file)
@@ -46,6 +46,7 @@ class Transaction {
   }
 
   async commit() {
+    //console.log('commit transaction', this.serial)
     assert(this.value !== undefined)
 
     if (this.value instanceof LazyValue) {
@@ -70,6 +71,7 @@ class Transaction {
   }
 
   rollback() {
+    //console.log('rollback transaction', this.serial)
     this.database.mutex.release()
   }