started refactoring the Memory db
This commit is contained in:
		
							parent
							
								
									181595293f
								
							
						
					
					
						commit
						aff10fa4db
					
				| @ -275,5 +275,28 @@ class AbstractDatabase { | ||||
|       yield* t._changed(transaction, Y.utils.copyObject(op)) | ||||
|     } | ||||
|   } | ||||
|   getNextRequest () { | ||||
|     if (this.waitingTransactions.length === 0) { | ||||
|       this.transactionInProgress = false | ||||
|       return null | ||||
|     } else { | ||||
|       return this.waitingTransactions.shift() | ||||
|     } | ||||
|   } | ||||
|   requestTransaction (makeGen, callImmediately) { | ||||
|     if (!this.transactionInProgress) { | ||||
|       this.transactionInProgress = true | ||||
|       if (callImmediately) { | ||||
|         this.transact(makeGen) | ||||
|       } else { | ||||
|         var self = this | ||||
|         setTimeout(function () { | ||||
|           self.transact(makeGen) | ||||
|         }, 0) | ||||
|       } | ||||
|     } else { | ||||
|       this.waitingTransactions.push(makeGen) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| Y.AbstractDatabase = AbstractDatabase | ||||
|  | ||||
| @ -156,48 +156,48 @@ for (var database of databases) { | ||||
|         }) | ||||
|         it('debug #1', function (done) { | ||||
|           store.requestTransaction(function * () { | ||||
|             yield this.os.put({id: [2]}) | ||||
|             yield this.os.put({id: [0]}) | ||||
|             yield this.os.delete([2]) | ||||
|             yield this.os.put({id: [1]}) | ||||
|             expect(yield this.os.find([0])).not.toBeNull() | ||||
|             expect(yield this.os.find([1])).not.toBeNull() | ||||
|             expect(yield this.os.find([2])).toBeNull() | ||||
|             yield* this.os.put({id: [2]}) | ||||
|             yield* this.os.put({id: [0]}) | ||||
|             yield* this.os.delete([2]) | ||||
|             yield* this.os.put({id: [1]}) | ||||
|             expect(yield* this.os.find([0])).not.toBeNull() | ||||
|             expect(yield* this.os.find([1])).not.toBeNull() | ||||
|             expect(yield* this.os.find([2])).toBeNull() | ||||
|             done() | ||||
|           }) | ||||
|         }) | ||||
|         it('can add&retrieve 5 elements', function (done) { | ||||
|           store.requestTransaction(function * () { | ||||
|             yield this.os.put({val: 'four', id: [4]}) | ||||
|             yield this.os.put({val: 'one', id: [1]}) | ||||
|             yield this.os.put({val: 'three', id: [3]}) | ||||
|             yield this.os.put({val: 'two', id: [2]}) | ||||
|             yield this.os.put({val: 'five', id: [5]}) | ||||
|             expect((yield this.os.find([1])).val).toEqual('one') | ||||
|             expect((yield this.os.find([2])).val).toEqual('two') | ||||
|             expect((yield this.os.find([3])).val).toEqual('three') | ||||
|             expect((yield this.os.find([4])).val).toEqual('four') | ||||
|             expect((yield this.os.find([5])).val).toEqual('five') | ||||
|             yield* this.os.put({val: 'four', id: [4]}) | ||||
|             yield* this.os.put({val: 'one', id: [1]}) | ||||
|             yield* this.os.put({val: 'three', id: [3]}) | ||||
|             yield* this.os.put({val: 'two', id: [2]}) | ||||
|             yield* this.os.put({val: 'five', id: [5]}) | ||||
|             expect((yield* this.os.find([1])).val).toEqual('one') | ||||
|             expect((yield* this.os.find([2])).val).toEqual('two') | ||||
|             expect((yield* this.os.find([3])).val).toEqual('three') | ||||
|             expect((yield* this.os.find([4])).val).toEqual('four') | ||||
|             expect((yield* this.os.find([5])).val).toEqual('five') | ||||
|             done() | ||||
|           }) | ||||
|         }) | ||||
|         it('5 elements do not exist anymore after deleting them', function (done) { | ||||
|           store.requestTransaction(function * () { | ||||
|             yield this.os.put({val: 'four', id: [4]}) | ||||
|             yield this.os.put({val: 'one', id: [1]}) | ||||
|             yield this.os.put({val: 'three', id: [3]}) | ||||
|             yield this.os.put({val: 'two', id: [2]}) | ||||
|             yield this.os.put({val: 'five', id: [5]}) | ||||
|             yield this.os.delete([4]) | ||||
|             expect(yield this.os.find([4])).not.toBeTruthy() | ||||
|             yield this.os.delete([3]) | ||||
|             expect(yield this.os.find([3])).not.toBeTruthy() | ||||
|             yield this.os.delete([2]) | ||||
|             expect(yield this.os.find([2])).not.toBeTruthy() | ||||
|             yield this.os.delete([1]) | ||||
|             expect(yield this.os.find([1])).not.toBeTruthy() | ||||
|             yield this.os.delete([5]) | ||||
|             expect(yield this.os.find([5])).not.toBeTruthy() | ||||
|             yield* this.os.put({val: 'four', id: [4]}) | ||||
|             yield* this.os.put({val: 'one', id: [1]}) | ||||
|             yield* this.os.put({val: 'three', id: [3]}) | ||||
|             yield* this.os.put({val: 'two', id: [2]}) | ||||
|             yield* this.os.put({val: 'five', id: [5]}) | ||||
|             yield* this.os.delete([4]) | ||||
|             expect(yield* this.os.find([4])).not.toBeTruthy() | ||||
|             yield* this.os.delete([3]) | ||||
|             expect(yield* this.os.find([3])).not.toBeTruthy() | ||||
|             yield* this.os.delete([2]) | ||||
|             expect(yield* this.os.find([2])).not.toBeTruthy() | ||||
|             yield* this.os.delete([1]) | ||||
|             expect(yield* this.os.find([1])).not.toBeTruthy() | ||||
|             yield* this.os.delete([5]) | ||||
|             expect(yield* this.os.find([5])).not.toBeTruthy() | ||||
|             done() | ||||
|           }) | ||||
|         }) | ||||
| @ -214,9 +214,9 @@ for (var database of databases) { | ||||
|               var r = Math.random() | ||||
|               if (r < 0.8) { | ||||
|                 var obj = [Math.floor(Math.random() * numberOfOSTests * 10000)] | ||||
|                 if (!(yield this.os.findNode(obj))) { | ||||
|                 if (!(this.os.findNode(obj))) { | ||||
|                   elements.push(obj) | ||||
|                   yield this.os.put({id: obj}) | ||||
|                   yield* this.os.put({id: obj}) | ||||
|                 } | ||||
|               } else if (elements.length > 0) { | ||||
|                 var elemid = Math.floor(Math.random() * elements.length) | ||||
| @ -224,7 +224,7 @@ for (var database of databases) { | ||||
|                 elements = elements.filter(function (e) { | ||||
|                   return !Y.utils.compareIds(e, elem) | ||||
|                 }) | ||||
|                 yield this.os.delete(elem) | ||||
|                 yield* this.os.delete(elem) | ||||
|               } | ||||
|             } | ||||
|             done() | ||||
| @ -233,7 +233,7 @@ for (var database of databases) { | ||||
|         it('can find every object', function (done) { | ||||
|           store.requestTransaction(function * () { | ||||
|             for (var id of elements) { | ||||
|               expect((yield this.os.find(id)).id).toEqual(id) | ||||
|               expect((yield* this.os.find(id)).id).toEqual(id) | ||||
|             } | ||||
|             done() | ||||
|           }) | ||||
| @ -242,7 +242,8 @@ for (var database of databases) { | ||||
|         it('can find every object with lower bound search', function (done) { | ||||
|           store.requestTransaction(function * () { | ||||
|             for (var id of elements) { | ||||
|               expect((yield this.os.findNodeWithLowerBound(id)).val.id).toEqual(id) | ||||
|               var e = yield* this.os.findNodeWithLowerBound(id) | ||||
|               expect(e.val.id).toEqual(id) | ||||
|             } | ||||
|             done() | ||||
|           }) | ||||
|  | ||||
| @ -3,43 +3,51 @@ | ||||
| 'use strict' | ||||
| 
 | ||||
| Y.IndexedDB = (function () { | ||||
|   class Store { | ||||
|     constructor (transaction, name) { | ||||
|       this.store = transaction.objectStore(name) | ||||
|     } | ||||
|     find (id) { | ||||
|       return this.store.get(id) | ||||
|     } | ||||
|     put (v) { | ||||
|       return this.store.put(v) | ||||
|     } | ||||
|     delete (id) { | ||||
|       return this.store.delete(id) | ||||
|     } | ||||
|     * findNodeWithLowerBound (start) { | ||||
|       var cursorResult = this.store.openCursor(window.IDBKeyRange.lowerBound(start)) | ||||
|       var cursor | ||||
|       while ((cursor = yield cursorResult) != null) { | ||||
|         // yield* gen.call(t, cursor.value)
 | ||||
|         cursor.continue() | ||||
|       } | ||||
|     } | ||||
|     * iterate (t, start, end, gen) { | ||||
|       var range = null | ||||
|       if (start != null && end != null) { | ||||
|         range = window.IDBKeyRange.bound(start, end) | ||||
|       } else if (start != null) { | ||||
|         range = window.IDBKeyRange.lowerBound(start) | ||||
|       } else if (end != null) { | ||||
|         range = window.IDBKeyRange.upperBound(end) | ||||
|       } | ||||
|       var cursorResult = this.store.openCursor(range) | ||||
|       var cursor | ||||
|       while ((cursor = yield cursorResult) != null) { | ||||
|         yield* gen.call(t, cursor.value) | ||||
|         cursor.continue() | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|   } | ||||
|   class Transaction { | ||||
|     constructor (store) { | ||||
|       this.transaction = store.db.transaction(['OperationStore', 'StateVector'], 'readwrite') | ||||
|       this.sv = this.transaction.objectStore('StateVector') | ||||
|       this.os = this.transaction.objectStore('OperationStore') | ||||
|       this.buffer = {} | ||||
|     } | ||||
|     * setOperation (op) { | ||||
|       yield this.os.put(op) | ||||
|       this.buffer[JSON.stringify(op.id)] = op | ||||
|       return op | ||||
|     } | ||||
|     * getOperation (id) { | ||||
|       var op = this.buffer[JSON.stringify(id)] | ||||
|       if (op == null) { | ||||
|         op = yield this.os.get(id) | ||||
|         this.buffer[JSON.stringify(id)] = op | ||||
|       } | ||||
|       return op | ||||
|     } | ||||
|     * removeOperation (id) { | ||||
|       this.buffer[JSON.stringify(id)] = null | ||||
|       return yield this.os.delete(id) | ||||
|     } | ||||
|     * setState (state) { | ||||
|       return yield this.sv.put(state) | ||||
|     } | ||||
|     * getState (user) { | ||||
|       var state | ||||
|       if ((state = yield this.sv.get(user)) != null) { | ||||
|         return state | ||||
|       } else { | ||||
|         return { | ||||
|           user: user, | ||||
|           clock: 0 | ||||
|         } | ||||
|       } | ||||
|       var transaction = store.db.transaction(['OperationStore', 'StateStore', 'DeleteStore'], 'readwrite') | ||||
|       this.ss = new Store(transaction, 'StateStore') | ||||
|       this.os = new Store(transaction, 'OperationStore') | ||||
|       this.ds = new Store(transaction, 'DeleteStore') | ||||
|     } | ||||
|     * getStateVector () { | ||||
|       var stateVector = [] | ||||
| @ -155,7 +163,8 @@ Y.IndexedDB = (function () { | ||||
|             var db = event.target.result | ||||
|             try { | ||||
|               db.createObjectStore('OperationStore', {keyPath: 'id'}) | ||||
|               db.createObjectStore('StateVector', {keyPath: 'user'}) | ||||
|               db.createObjectStore('DeleteStore', {keyPath: 'id'}) | ||||
|               db.createObjectStore('StateStore', {keyPath: 'id'}) | ||||
|             } catch (e) { | ||||
|               // console.log("Store already exists!")
 | ||||
|             } | ||||
| @ -172,7 +181,19 @@ Y.IndexedDB = (function () { | ||||
|         this.transactionQueue.onRequest() | ||||
|       } | ||||
|     } | ||||
|     * removeDatabase () { | ||||
|     transact (makeGen) { | ||||
|       var t = new Y.Transaction(this) | ||||
|       while (makeGen !== null) { | ||||
|         var gen = makeGen.call(t) | ||||
|         var res = gen.next() | ||||
|         while (!res.done) { | ||||
|           res = gen.next(res.value) | ||||
|         } | ||||
|         makeGen = this.getNextRequest() | ||||
|       } | ||||
|     } | ||||
|     // TODO: implement "free"..
 | ||||
|     * destroy () { | ||||
|       this.db.close() | ||||
|       yield window.indexedDB.deleteDatabase(this.namespace) | ||||
|     } | ||||
|  | ||||
| @ -2,6 +2,15 @@ | ||||
| 'use strict' | ||||
| 
 | ||||
| Y.Memory = (function () { | ||||
|   class Transaction extends Y.Transaction { | ||||
|     constructor (store) { | ||||
|       super(store) | ||||
|       this.store = store | ||||
|       this.ss = store.ss | ||||
|       this.os = store.os | ||||
|       this.ds = store.ds | ||||
|     } | ||||
|   } | ||||
|   class Database extends Y.AbstractDatabase { | ||||
|     constructor (y, opts) { | ||||
|       super(y, opts) | ||||
| @ -25,29 +34,15 @@ Y.Memory = (function () { | ||||
|         }, true) | ||||
|       }) | ||||
|     } | ||||
|     requestTransaction (_makeGen, callImmediately) { | ||||
|       if (!this.transactionInProgress) { | ||||
|         this.transactionInProgress = true | ||||
|         var transact = () => { | ||||
|           var makeGen = _makeGen | ||||
|           while (makeGen != null) { | ||||
|             var t = new Y.Transaction(this) | ||||
|             var gen = makeGen.call(t) | ||||
|             var res = gen.next() | ||||
|             while (!res.done) { | ||||
|               res = gen.next(res.value) | ||||
|             } | ||||
|             makeGen = this.waitingTransactions.shift() | ||||
|           } | ||||
|           this.transactionInProgress = false | ||||
|     transact (makeGen) { | ||||
|       var t = new Transaction(this) | ||||
|       while (makeGen !== null) { | ||||
|         var gen = makeGen.call(t) | ||||
|         var res = gen.next() | ||||
|         while (!res.done) { | ||||
|           res = gen.next(res.value) | ||||
|         } | ||||
|         if (callImmediately) { | ||||
|           transact() | ||||
|         } else { | ||||
|           setTimeout(transact, 0) | ||||
|         } | ||||
|       } else { | ||||
|         this.waitingTransactions.push(_makeGen) | ||||
|         makeGen = this.getNextRequest() | ||||
|       } | ||||
|     } | ||||
|     * destroy () { | ||||
|  | ||||
| @ -130,7 +130,13 @@ class RBTree { | ||||
|     this.root = null | ||||
|     this.length = 0 | ||||
|   } | ||||
|   findNodeWithLowerBound (from) { | ||||
|   * findNext (id) { | ||||
|     return yield* this.findNodeWithLowerBound([id[0], id[1] + 1]) | ||||
|   } | ||||
|   * findPrev (id) { | ||||
|     return yield* this.findNodeWithUpperBound([id[0], id[1] - 1]) | ||||
|   } | ||||
|   * findNodeWithLowerBound (from) { | ||||
|     if (from === void 0) { | ||||
|       throw new Error('You must define from!') | ||||
|     } | ||||
| @ -158,7 +164,7 @@ class RBTree { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   findNodeWithUpperBound (to) { | ||||
|   * findNodeWithUpperBound (to) { | ||||
|     if (to === void 0) { | ||||
|       throw new Error('You must define from!') | ||||
|     } | ||||
| @ -187,7 +193,7 @@ class RBTree { | ||||
|     } | ||||
|   } | ||||
|   * iterate (t, from, to, f) { | ||||
|     var o = this.findNodeWithLowerBound(from) | ||||
|     var o = yield* this.findNodeWithLowerBound(from) | ||||
|     while (o !== null && (to === null || Y.utils.smaller(o.val.id, to) || Y.utils.compareIds(o.val.id, to))) { | ||||
|       yield* f.call(t, o.val) | ||||
|       o = o.next() | ||||
| @ -220,7 +226,7 @@ class RBTree { | ||||
|       console.table(os) | ||||
|     } | ||||
|   } | ||||
|   find (id) { | ||||
|   * find (id) { | ||||
|     var n | ||||
|     return (n = this.findNode(id)) ? n.val : null | ||||
|   } | ||||
| @ -246,7 +252,7 @@ class RBTree { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   delete (id) { | ||||
|   * delete (id) { | ||||
|     if (id == null || id.constructor !== Array) { | ||||
|       throw new Error('id is expected to be an Array!') | ||||
|     } | ||||
| @ -388,7 +394,7 @@ class RBTree { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   put (v) { | ||||
|   * put (v) { | ||||
|     if (v == null || v.id == null || v.id.constructor !== Array) { | ||||
|       throw new Error('v is expected to have an id property which is an Array!') | ||||
|     } | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| 
 | ||||
| var numberOfRBTreeTests = 1000 | ||||
| 
 | ||||
| function itRedNodesDoNotHaveBlackChildren (tree) { | ||||
| function itRedNodesDoNotHaveBlackChildren () { | ||||
|   it('Red nodes do not have black children', function () { | ||||
|     function traverse (n) { | ||||
|       if (n == null) { | ||||
| @ -20,11 +20,11 @@ function itRedNodesDoNotHaveBlackChildren (tree) { | ||||
|       traverse(n.left) | ||||
|       traverse(n.right) | ||||
|     } | ||||
|     traverse(tree.root) | ||||
|     traverse(this.tree.root) | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
| function itBlackHeightOfSubTreesAreEqual (tree) { | ||||
| function itBlackHeightOfSubTreesAreEqual () { | ||||
|   it('Black-height of sub-trees are equal', function () { | ||||
|     function traverse (n) { | ||||
|       if (n == null) { | ||||
| @ -39,76 +39,99 @@ function itBlackHeightOfSubTreesAreEqual (tree) { | ||||
|         return sub1 + 1 | ||||
|       } | ||||
|     } | ||||
|     traverse(tree.root) | ||||
|     traverse(this.tree.root) | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
| function itRootNodeIsBlack (tree) { | ||||
| function itRootNodeIsBlack () { | ||||
|   it('root node is black', function () { | ||||
|     expect(tree.root == null || tree.root.isBlack()).toBeTruthy() | ||||
|     expect(this.tree.root == null || this.tree.root.isBlack()).toBeTruthy() | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
| describe('RedBlack Tree', function () { | ||||
|   beforeEach(function () { | ||||
|     this.memory = new Y.Memory(null, { | ||||
|       name: 'Memory', | ||||
|       gcTimeout: -1 | ||||
|     }) | ||||
|     this.tree = this.memory.os | ||||
|   }) | ||||
|   var tree, memory | ||||
|   describe('debug #2', function () { | ||||
|     var tree = new Y.utils.RBTree() | ||||
|     tree.put({id: [8433]}) | ||||
|     tree.put({id: [12844]}) | ||||
|     tree.put({id: [1795]}) | ||||
|     tree.put({id: [30302]}) | ||||
|     tree.put({id: [64287]}) | ||||
|     tree.delete([8433]) | ||||
|     tree.put({id: [28996]}) | ||||
|     tree.delete([64287]) | ||||
|     tree.put({id: [22721]}) | ||||
|     beforeAll(function (done) { | ||||
|       this.memory = new Y.Memory(null, { | ||||
|         name: 'Memory', | ||||
|         gcTimeout: -1 | ||||
|       }) | ||||
|       this.tree = this.memory.os | ||||
|       tree = this.tree | ||||
|       memory = this.memory | ||||
|       memory.requestTransaction(function * () { | ||||
|         yield* tree.put({id: [8433]}) | ||||
|         yield* tree.put({id: [12844]}) | ||||
|         yield* tree.put({id: [1795]}) | ||||
|         yield* tree.put({id: [30302]}) | ||||
|         yield* tree.put({id: [64287]}) | ||||
|         yield* tree.delete([8433]) | ||||
|         yield* tree.put({id: [28996]}) | ||||
|         yield* tree.delete([64287]) | ||||
|         yield* tree.put({id: [22721]}) | ||||
|         done() | ||||
|       }) | ||||
|     }) | ||||
| 
 | ||||
|     itRootNodeIsBlack(tree, []) | ||||
|     itBlackHeightOfSubTreesAreEqual(tree, []) | ||||
|     itRootNodeIsBlack() | ||||
|     itBlackHeightOfSubTreesAreEqual([]) | ||||
|   }) | ||||
| 
 | ||||
|   describe(`After adding&deleting (0.8/0.2) ${numberOfRBTreeTests} times`, function () { | ||||
|     var elements = [] | ||||
|     var tree = new Y.utils.RBTree() | ||||
|     for (var i = 0; i < numberOfRBTreeTests; i++) { | ||||
|       var r = Math.random() | ||||
|       if (r < 0.8) { | ||||
|         var obj = [Math.floor(Math.random() * numberOfRBTreeTests * 10000)] | ||||
|         if (!tree.findNode(obj)) { | ||||
|           elements.push(obj) | ||||
|           tree.put({id: obj}) | ||||
|     beforeAll(function (done) { | ||||
|       this.memory = new Y.Memory(null, { | ||||
|         name: 'Memory', | ||||
|         gcTimeout: -1 | ||||
|       }) | ||||
|       this.tree = this.memory.os | ||||
|       tree = this.tree | ||||
|       memory = this.memory | ||||
|       memory.requestTransaction(function * () { | ||||
|         for (var i = 0; i < numberOfRBTreeTests; i++) { | ||||
|           var r = Math.random() | ||||
|           if (r < 0.8) { | ||||
|             var obj = [Math.floor(Math.random() * numberOfRBTreeTests * 10000)] | ||||
|             if (!tree.findNode(obj)) { | ||||
|               elements.push(obj) | ||||
|               yield* tree.put({id: obj}) | ||||
|             } | ||||
|           } else if (elements.length > 0) { | ||||
|             var elemid = Math.floor(Math.random() * elements.length) | ||||
|             var elem = elements[elemid] | ||||
|             elements = elements.filter(function (e) { | ||||
|               return !Y.utils.compareIds(e, elem) | ||||
|             }) | ||||
|             yield* tree.delete(elem) | ||||
|           } | ||||
|         } | ||||
|       } else if (elements.length > 0) { | ||||
|         var elemid = Math.floor(Math.random() * elements.length) | ||||
|         var elem = elements[elemid] | ||||
|         elements = elements.filter(function (e) { | ||||
|           return !Y.utils.compareIds(e, elem) | ||||
|         }) | ||||
|         tree.delete(elem) | ||||
|       } | ||||
|     } | ||||
|     itRootNodeIsBlack(tree) | ||||
| 
 | ||||
|     it('can find every object', function () { | ||||
|       for (var id of elements) { | ||||
|         expect(tree.find(id).id).toEqual(id) | ||||
|       } | ||||
|         done() | ||||
|       }) | ||||
|     }) | ||||
| 
 | ||||
|     it('can find every object with lower bound search', function () { | ||||
|       for (var id of elements) { | ||||
|         expect(tree.findNodeWithLowerBound(id).val.id).toEqual(id) | ||||
|       } | ||||
|     }) | ||||
|     itRedNodesDoNotHaveBlackChildren(tree) | ||||
|     itRootNodeIsBlack() | ||||
| 
 | ||||
|     itBlackHeightOfSubTreesAreEqual(tree) | ||||
|     it('can find every object', function (done) { | ||||
|       memory.requestTransaction(function * () { | ||||
|         for (var id of elements) { | ||||
|           expect((yield* tree.find(id)).id).toEqual(id) | ||||
|         } | ||||
|         done() | ||||
|       }) | ||||
|     }) | ||||
| 
 | ||||
|     it('can find every object with lower bound search', function (done) { | ||||
|       this.memory.requestTransaction(function * () { | ||||
|         for (var id of elements) { | ||||
|           expect((yield* tree.findNodeWithLowerBound(id)).val.id).toEqual(id) | ||||
|         } | ||||
|         done() | ||||
|       }) | ||||
|     }) | ||||
|     itRedNodesDoNotHaveBlackChildren() | ||||
| 
 | ||||
|     itBlackHeightOfSubTreesAreEqual() | ||||
| 
 | ||||
|     it('iterating over a tree with lower bound yields the right amount of results', function (done) { | ||||
|       var lowerBound = elements[Math.floor(Math.random() * elements.length)] | ||||
|  | ||||
| @ -18,7 +18,7 @@ g.g = g | ||||
| 
 | ||||
| g.YConcurrency_TestingMode = true | ||||
| 
 | ||||
| jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000 | ||||
| jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000 | ||||
| 
 | ||||
| g.describeManyTimes = function describeManyTimes (times, name, f) { | ||||
|   for (var i = 0; i < times; i++) { | ||||
| @ -36,7 +36,7 @@ function wait (t) { | ||||
|   return new Promise(function (resolve) { | ||||
|     setTimeout(function () { | ||||
|       resolve() | ||||
|     }, t) | ||||
|     }, t * 2) | ||||
|   }) | ||||
| } | ||||
| g.wait = wait | ||||
|  | ||||
| @ -75,12 +75,6 @@ | ||||
|        applyable on a given SS. | ||||
| */ | ||||
| class Transaction { | ||||
|   constructor (store) { | ||||
|     this.store = store | ||||
|     this.ss = store.ss | ||||
|     this.os = store.os | ||||
|     this.ds = store.ds | ||||
|   } | ||||
|   /* | ||||
|     Get a type based on the id of its model. | ||||
|     If it does not exist yes, create it. | ||||
| @ -206,14 +200,14 @@ class Transaction { | ||||
|         // un-extend left
 | ||||
|         var newlen = n.val.len - (id[1] - n.val.id[1]) | ||||
|         n.val.len -= newlen | ||||
|         n = yield this.ds.put({id: id, len: newlen, gc: false}) | ||||
|         n = yield* this.ds.put({id: id, len: newlen, gc: false}) | ||||
|       } | ||||
|       // get prev&next before adding a new operation
 | ||||
|       var prev = n.prev() | ||||
|       var next = n.next() | ||||
|       if (id[1] < n.val.id[1] + n.val.len - 1) { | ||||
|         // un-extend right
 | ||||
|         yield this.ds.put({id: [id[0], id[1] + 1], len: n.val.len - 1, gc: false}) | ||||
|         yield* this.ds.put({id: [id[0], id[1] + 1], len: n.val.len - 1, gc: false}) | ||||
|         n.val.len = 1 | ||||
|       } | ||||
|       // set gc'd
 | ||||
| @ -225,7 +219,7 @@ class Transaction { | ||||
|         Y.utils.compareIds([prev.val.id[0], prev.val.id[1] + prev.val.len], n.val.id) | ||||
|       ) { | ||||
|         prev.val.len += n.val.len | ||||
|         yield this.ds.delete(n.val.id) | ||||
|         yield* this.ds.delete(n.val.id) | ||||
|         n = prev | ||||
|       } | ||||
|       // can extend right?
 | ||||
| @ -235,7 +229,7 @@ class Transaction { | ||||
|         Y.utils.compareIds([n.val.id[0], n.val.id[1] + n.val.len], next.val.id) | ||||
|       ) { | ||||
|         n.val.len += next.val.len | ||||
|         yield this.ds.delete(next.val.id) | ||||
|         yield* this.ds.delete(next.val.id) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @ -246,7 +240,7 @@ class Transaction { | ||||
|   */ | ||||
|   * markDeleted (id) { | ||||
|     // this.mem.push(["del", id]);
 | ||||
|     var n = yield this.ds.findNodeWithUpperBound(id) | ||||
|     var n = yield* this.ds.findNodeWithUpperBound(id) | ||||
|     if (n != null && n.val.id[0] === id[0]) { | ||||
|       if (n.val.id[1] <= id[1] && id[1] < n.val.id[1] + n.val.len) { | ||||
|         // already deleted
 | ||||
| @ -256,11 +250,11 @@ class Transaction { | ||||
|         n.val.len++ | ||||
|       } else { | ||||
|         // cannot extend left
 | ||||
|         n = yield this.ds.put({id: id, len: 1, gc: false}) | ||||
|         n = yield* this.ds.put({id: id, len: 1, gc: false}) | ||||
|       } | ||||
|     } else { | ||||
|       // cannot extend left
 | ||||
|       n = yield this.ds.put({id: id, len: 1, gc: false}) | ||||
|       n = yield* this.ds.put({id: id, len: 1, gc: false}) | ||||
|     } | ||||
|     // can extend right?
 | ||||
|     var next = n.next() | ||||
| @ -270,8 +264,8 @@ class Transaction { | ||||
|       !next.val.gc | ||||
|     ) { | ||||
|       n.val.len = n.val.len + next.val.len | ||||
|       yield this.ds.delete(next.val.id) | ||||
|       return yield this.ds.findNode(n.val.id) | ||||
|       yield* this.ds.delete(next.val.id) | ||||
|       return this.ds.findNode(n.val.id) | ||||
|     } else { | ||||
|       return n | ||||
|     } | ||||
| @ -389,7 +383,7 @@ class Transaction { | ||||
|     } | ||||
|   } | ||||
|   * checkDeleteStoreForState (state) { | ||||
|     var n = yield this.ds.findNodeWithUpperBound([state.user, state.clock]) | ||||
|     var n = yield* this.ds.findNodeWithUpperBound([state.user, state.clock]) | ||||
|     if (n !== null && n.val.id[0] === state.user && n.val.gc) { | ||||
|       state.clock = Math.max(state.clock, n.val.id[1] + n.val.len) | ||||
|     } | ||||
| @ -468,7 +462,7 @@ class Transaction { | ||||
|     } | ||||
|   } | ||||
|   * isGarbageCollected (id) { | ||||
|     var n = yield this.ds.findNodeWithUpperBound(id) | ||||
|     var n = yield* this.ds.findNodeWithUpperBound(id) | ||||
|     return n !== null && n.val.id[0] === id[0] && id[1] < n.val.id[1] + n.val.len && n.val.gc | ||||
|   } | ||||
|   /* | ||||
| @ -491,15 +485,15 @@ class Transaction { | ||||
|     return ds | ||||
|   } | ||||
|   * isDeleted (id) { | ||||
|     var n = yield this.ds.findNodeWithUpperBound(id) | ||||
|     var n = yield* this.ds.findNodeWithUpperBound(id) | ||||
|     return n !== null && n.val.id[0] === id[0] && id[1] < n.val.id[1] + n.val.len | ||||
|   } | ||||
|   * setOperation (op) { | ||||
|     yield this.os.put(op) | ||||
|     yield* this.os.put(op) | ||||
|     return op | ||||
|   } | ||||
|   * addOperation (op) { | ||||
|     var n = yield this.os.put(op) | ||||
|     var n = yield* this.os.put(op) | ||||
|     return function () { | ||||
|       if (n != null) { | ||||
|         n = n.next() | ||||
| @ -510,10 +504,10 @@ class Transaction { | ||||
|     } | ||||
|   } | ||||
|   * getOperation (id) { | ||||
|     return yield this.os.find(id) | ||||
|     return yield* this.os.find(id) | ||||
|   } | ||||
|   * removeOperation (id) { | ||||
|     yield this.os.delete(id) | ||||
|     yield* this.os.delete(id) | ||||
|   } | ||||
|   * setState (state) { | ||||
|     var val = { | ||||
| @ -521,15 +515,15 @@ class Transaction { | ||||
|       clock: state.clock | ||||
|     } | ||||
|     // TODO: find a way to skip this step.. (after implementing some dbs..)
 | ||||
|     if (yield this.ss.find([state.user])) { | ||||
|       yield this.ss.put(val) | ||||
|     if (yield* this.ss.find([state.user])) { | ||||
|       yield* this.ss.put(val) | ||||
|     } else { | ||||
|       yield this.ss.put(val) | ||||
|       yield* this.ss.put(val) | ||||
|     } | ||||
|   } | ||||
|   * getState (user) { | ||||
|     var n | ||||
|     var clock = (n = this.ss.find([user])) == null ? null : n.clock | ||||
|     var clock = (n = yield* this.ss.find([user])) == null ? null : n.clock | ||||
|     if (clock == null) { | ||||
|       clock = 0 | ||||
|     } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| /* global createUsers, wait, Y, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, garbageCollectAllUsers, describeManyTimes */ | ||||
| /* eslint-env browser,jasmine */ | ||||
| 
 | ||||
| var numberOfYArrayTests = 10 | ||||
| var numberOfYArrayTests = 200 | ||||
| var repeatArrayTests = 1 | ||||
| 
 | ||||
| describe('Array Type', function () { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user