From 82e2254302fc6ea30561b15239028fdf80d4fb35 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Mon, 5 Oct 2015 14:24:11 +0200 Subject: [PATCH] fixed some inconsistency bugs with DS --- src/Connector.js | 1 + src/Helper.spec.js | 20 ++++++++++++-------- src/OperationStore.js | 28 ++++++++++++++++++---------- src/OperationStores/Memory.js | 12 ++++++++++-- src/Struct.js | 3 ++- src/y.js | 2 +- 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/Connector.js b/src/Connector.js index 88ca708d..b787d55c 100644 --- a/src/Connector.js +++ b/src/Connector.js @@ -40,6 +40,7 @@ class AbstractConnector { this.broadcastedHB = false this.syncingClients = [] this.whenSyncedListeners = [] + this.y.db.stopGarbageCollector() } setUserId (userId) { this.userId = userId diff --git a/src/Helper.spec.js b/src/Helper.spec.js index 95d9f234..cda3b4b0 100644 --- a/src/Helper.spec.js +++ b/src/Helper.spec.js @@ -36,7 +36,7 @@ function wait (t) { return new Promise(function (resolve) { setTimeout(function () { resolve() - }, t) + }, t * 5) }) } g.wait = wait @@ -150,7 +150,11 @@ g.compareAllUsers = async(function * compareAllUsers (users) { for (var i = 0; i < d.len; i++) { var o = yield* this.getOperation([d.id[0], d.id[1] + i]) // gc'd or deleted - expect(o == null || o.deleted).toBeTruthy() + if (d.gc) { + expect(o).toBeUndefined() + } else { + expect(o.deleted).toBeTruthy() + } } } }) @@ -234,11 +238,11 @@ function logUsers (self) { if (self.constructor === Array) { self = {users: self} } - console.log('User 1: ', self.users[0].connector.userId) // eslint-disable-line - self.users[0].db.os.logTable() // eslint-disable-line - console.log('User 2: ', self.users[1].connector.userId) // eslint-disable-line - self.users[1].db.os.logTable() // eslint-disable-line - console.log('User 3: ', self.users[2].connector.userId) // eslint-disable-line - self.users[2].db.os.logTable() // eslint-disable-line + console.log('User 1: ', self.users[0].connector.userId, "=============================================") // eslint-disable-line + self.users[0].db.logTable() // eslint-disable-line + console.log('User 2: ', self.users[1].connector.userId, "=============================================") // eslint-disable-line + self.users[1].db.logTable() // eslint-disable-line + console.log('User 3: ', self.users[2].connector.userId, "=============================================") // eslint-disable-line + self.users[2].db.logTable() // eslint-disable-line } g.logUsers = logUsers diff --git a/src/OperationStore.js b/src/OperationStore.js index 8ddf4375..df532a63 100644 --- a/src/OperationStore.js +++ b/src/OperationStore.js @@ -3,9 +3,9 @@ /* Partial definition of a transaction - + A transaction provides all the the async functionality on a database. - + By convention, a transaction has the following properties: * ss for StateSet * os for OperationStore @@ -136,17 +136,20 @@ class AbstractTransaction { } } var left = target.left != null ? yield* this.getOperation(target.left) : null - var right = target.right != null ? yield* this.getOperation(target.right) : null this.store.addToGarbageCollector(target, left) // set here because it was deleted and/or gc'd yield* this.setOperation(target) - // check if it is possible to add right to the gc (this delete can't be responsible for left being gc'd) + /* + Check if it is possible to add right to the gc. + Because this delete can't be responsible for left being gc'd, + we don't have to add left to the gc.. + */ + var right = target.right != null ? yield* this.getOperation(target.right) : null if ( right != null && - right.right != null && this.store.addToGarbageCollector(right, target) ) { yield* this.setOperation(right) @@ -164,7 +167,8 @@ class AbstractTransaction { yield* this.deleteOperation(id) o = yield* this.getOperation(id) } - + + // TODO: I don't think that this is necessary!! // check to increase the state of the respective user var state = yield* this.getState(id[0]) if (state.clock === id[1]) { @@ -270,6 +274,10 @@ class AbstractOperationStore { garbageCollect() } } + stopGarbageCollector () { + this.gc1 = [] + this.gc2 = [] + } garbageCollectAfterSync () { var os = this.os var self = this @@ -284,12 +292,12 @@ class AbstractOperationStore { Try to add to GC. TODO: rename this function - + Rulez: * Only gc if this user is online * The most left element in a list must not be gc'd. => There is at least one element in the list - + returns true iff op was added to GC */ addToGarbageCollector (op, left) { @@ -342,7 +350,7 @@ class AbstractOperationStore { } /* Apply a list of operations. - + * get a transaction * check whether all Struct.*.requiredOps are in the OS * check if it is an expected op (otherwise wait for it) @@ -423,7 +431,7 @@ class AbstractOperationStore { /* Actually execute an operation, when all expected operations are available. If op is not yet expected, add it to the list of waiting operations. - + This will also try to execute waiting operations (ops that were not expected yet), after it was applied */ diff --git a/src/OperationStores/Memory.js b/src/OperationStores/Memory.js index 60d709c4..983790c6 100644 --- a/src/OperationStores/Memory.js +++ b/src/OperationStores/Memory.js @@ -70,7 +70,10 @@ class DeleteStore extends Y.utils.RBTree { } // can extend right? var next = n.next() - if (next !== null && Y.utils.compareIds([n.val.id[0], n.val.id[1] + n.val.len], next.val.id)) { + if (next !== null && + Y.utils.compareIds([n.val.id[0], n.val.id[1] + n.val.len], next.val.id) && + next.val.gc === false + ) { n.val.len = n.val.len + next.val.len super.delete(next.val.id) } @@ -303,7 +306,12 @@ Y.Memory = (function () { this.ds = new DeleteStore() } logTable () { - this.os.logTable() + console.log('User: ', this.y.connector.userId, "=============================================") // eslint-disable-line + console.log("State Set (SS):", this.ss) // eslint-disable-line + console.log("Operation Store (OS):") // eslint-disable-line + this.os.logTable() // eslint-disable-line + console.log("Deletion Store (DS):") //eslint-disable-line + this.ds.logTable() // eslint-disable-line } requestTransaction (_makeGen, requestNow) { if (requestNow == null) { requestNow = false } diff --git a/src/Struct.js b/src/Struct.js index 69ee2710..8b418bea 100644 --- a/src/Struct.js +++ b/src/Struct.js @@ -175,10 +175,11 @@ var Struct = { op.right = left.right left.right = op.id - // if left exists, and it is supposed to be gc'd. Remove it from the gc + /*/ if left exists, and it is supposed to be gc'd. Remove it from the gc if (left.gc != null) { this.store.removeFromGarbageCollector(left) } + */ yield* this.setOperation(left) } else { diff --git a/src/y.js b/src/y.js index 0008f941..97f5dc5d 100644 --- a/src/y.js +++ b/src/y.js @@ -24,7 +24,7 @@ class YConfig { map: {} } yield* this.addOperation(model) - var root = yield* this.createType(model) + var root = yield* this.getType(model.id) this.store.y.root = root callback() })