From 0c219ff30cdff2937a2dfac0bc7415767707baaf Mon Sep 17 00:00:00 2001 From: raararaara Date: Fri, 25 Oct 2024 18:02:04 +0900 Subject: [PATCH] Add `root.getStatus()` for debugging purpose --- packages/sdk/src/document/crdt/root.ts | 25 ++++++++++++ packages/sdk/src/util/splay_tree.ts | 56 +++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/document/crdt/root.ts b/packages/sdk/src/document/crdt/root.ts index 246d87d41..5b71d2772 100644 --- a/packages/sdk/src/document/crdt/root.ts +++ b/packages/sdk/src/document/crdt/root.ts @@ -39,6 +39,17 @@ interface CRDTElementPair { parent?: CRDTContainer; } +/** + * `RootStatus` is a structure that represents TODO(raa). + */ +interface RootStatus { + elements?: number; + textNodes?: number; + gcPairs?: number; + gcElements?: number; + maxSplayTreeHeight?: number; +} + /** * `CRDTRoot` is a structure that represents the root. It has a hash table of * all elements to find a specific element when applying remote changes @@ -308,4 +319,18 @@ export class CRDTRoot { public toSortedJSON(): string { return this.rootObject.toSortedJSON(); } + + /** + * `getStatus` returns the current status of root. + * for debugging purpose. + */ + public getStatus(): RootStatus { + const text = this.rootObject.get('content') as CRDTText; + return { + elements: this.getElementMapSize(), + gcPairs: this.gcPairMap.size, + gcElements: this.getGarbageElementSetSize(), + maxSplayTreeHeight: text.getTreeByIndex().getHeight(), + }; + } } diff --git a/packages/sdk/src/util/splay_tree.ts b/packages/sdk/src/util/splay_tree.ts index 30d64a038..06c4d0f1e 100644 --- a/packages/sdk/src/util/splay_tree.ts +++ b/packages/sdk/src/util/splay_tree.ts @@ -26,9 +26,11 @@ export abstract class SplayNode { private right?: SplayNode; private parent?: SplayNode; private weight!: number; + public height!: number; constructor(value: V) { this.value = value; + this.height = 1; this.initWeight(); } @@ -62,6 +64,20 @@ export abstract class SplayNode { return !this.hasRight() ? 0 : this.right!.getWeight(); } + /** + * `getLeftHeight` returns left height of this node. + */ + public getLeftHeight(): number { + return !this.hasLeft() ? 0 : this.left!.height; + } + + /** + * `getRightHeight` returns left height of this node. + */ + public getRightHeight(): number { + return !this.hasRight() ? 0 : this.right!.height; + } + /** * `getWeight` returns weight of this node. */ @@ -161,6 +177,13 @@ export abstract class SplayNode { public initWeight(): void { this.weight = this.getLength(); } + + /** + * `initHeight` sets initial height of this node. + */ + public initHeight() { + this.height = 1; + } } /** @@ -211,7 +234,7 @@ export class SplayTree { `out of index range: pos: ${pos} > node.length: ${node.getLength()}`, ); } - this.splayNode(node) + this.splayNode(node); return [node, pos]; } @@ -226,7 +249,7 @@ export class SplayTree { return -1; } - this.splayNode(node) + this.splayNode(node); return this.root!.getLeftWeight(); } @@ -268,6 +291,8 @@ export class SplayTree { target.setRight(); this.updateWeight(target); this.updateWeight(newNode); + this.updateHeight(target); + this.updateHeight(newNode); return newNode; } @@ -289,10 +314,23 @@ export class SplayTree { private updateTreeWeight(node: SplayNode): void { while (node) { this.updateWeight(node); + this.updateHeight(node); node = node.getParent()!; } } + private updateHeight(node: SplayNode): void { + node.initHeight(); + + if (node.height < node.getLeftHeight() + 1) { + node.height = node.getLeftHeight() + 1; + } + + if (node.height < node.getRightHeight() + 1) { + node.height = node.getRightHeight() + 1; + } + } + /** * `splayNode` moves the given node to the root. */ @@ -332,6 +370,7 @@ export class SplayTree { this.rotateLeft(node); } this.updateWeight(node); + this.updateHeight(node); return; } } @@ -368,6 +407,7 @@ export class SplayTree { node.unlink(); if (this.root) { this.updateWeight(this.root); + this.updateHeight(this.root); } } @@ -435,6 +475,14 @@ export class SplayTree { return true; } + /** + * `getHeight` returns the height of this node. + * for debugging. + */ + public getHeight(): number { + return this.root!.height; + } + private getRightmost(): SplayNode { let node = this.root!; while (node.hasRight()) { @@ -492,6 +540,8 @@ export class SplayTree { this.updateWeight(root); this.updateWeight(pivot); + this.updateHeight(root); + this.updateHeight(pivot); } private rotateRight(pivot: SplayNode): void { @@ -517,6 +567,8 @@ export class SplayTree { this.updateWeight(root); this.updateWeight(pivot); + this.updateHeight(root); + this.updateHeight(pivot); } private isLeftChild(node?: SplayNode): boolean {