From 8ab096e0842aa1beaec455e9bf5882095595c5b0 Mon Sep 17 00:00:00 2001 From: JiHwan Yim Date: Thu, 4 Jul 2024 14:22:27 +0900 Subject: [PATCH] Remove node from index during GC (#913) While improving GC structure, we missed removing nodes from internal indexes of Text when purging tombstones(#866). --------- Co-authored-by: Youngteac Hong --- pkg/document/crdt/rga_tree_split.go | 3 +++ pkg/document/crdt/text.go | 12 ++++++++++++ pkg/document/document_test.go | 25 +++++++++++++++++++++++++ test/integration/text_test.go | 2 ++ 4 files changed, 42 insertions(+) diff --git a/pkg/document/crdt/rga_tree_split.go b/pkg/document/crdt/rga_tree_split.go index 98a686ef6..b2e9448b3 100644 --- a/pkg/document/crdt/rga_tree_split.go +++ b/pkg/document/crdt/rga_tree_split.go @@ -628,6 +628,9 @@ func (s *RGATreeSplit[V]) ToTestString() string { func (s *RGATreeSplit[V]) Purge(child GCChild) error { node := child.(*RGATreeSplitNode[V]) + s.treeByIndex.Delete(node.indexNode) + s.treeByID.Remove(node.id) + node.prev.next = node.next if node.next != nil { node.next.prev = node.prev diff --git a/pkg/document/crdt/text.go b/pkg/document/crdt/text.go index 6cd09295f..09f3520f3 100644 --- a/pkg/document/crdt/text.go +++ b/pkg/document/crdt/text.go @@ -22,6 +22,8 @@ import ( "unicode/utf16" "github.com/yorkie-team/yorkie/pkg/document/time" + "github.com/yorkie-team/yorkie/pkg/llrb" + "github.com/yorkie-team/yorkie/pkg/splay" ) // TextValue is a value of Text which has an attributes that represent @@ -366,3 +368,13 @@ func (t *Text) ToTestString() string { func (t *Text) CheckWeight() bool { return t.rgaTreeSplit.CheckWeight() } + +// TreeByIndex returns IndexTree of the text for debugging purpose. +func (t *Text) TreeByIndex() *splay.Tree[*RGATreeSplitNode[*TextValue]] { + return t.rgaTreeSplit.treeByIndex +} + +// TreeByID returns the tree by ID for debugging purpose. +func (t *Text) TreeByID() *llrb.Tree[*RGATreeSplitNodeID, *RGATreeSplitNode[*TextValue]] { + return t.rgaTreeSplit.treeByID +} diff --git a/pkg/document/document_test.go b/pkg/document/document_test.go index 1046efd53..c5beb855b 100644 --- a/pkg/document/document_test.go +++ b/pkg/document/document_test.go @@ -524,4 +524,29 @@ func TestDocument(t *testing.T) { assert.Equal(t, "{}", doc.Marshal()) assert.Equal(t, 0, doc.GarbageLen()) }) + + t.Run("purge node from index during GC test", func(t *testing.T) { + doc := document.New("d1") + + assert.NoError(t, doc.Update(func(root *json.Object, p *presence.Presence) error { + root.SetNewText("k1") + return nil + })) + assert.Equal(t, 1, doc.Root().GetText("k1").TreeByID().Len()) + + assert.NoError(t, doc.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("k1").Edit(0, 0, "ABC", nil) + return nil + })) + assert.Equal(t, 2, doc.Root().GetText("k1").TreeByID().Len()) + + assert.NoError(t, doc.Update(func(root *json.Object, p *presence.Presence) error { + root.GetText("k1").Edit(1, 3, "", nil) + return nil + })) + assert.Equal(t, 3, doc.Root().GetText("k1").TreeByID().Len()) + + doc.GarbageCollect(time.MaxTicket) + assert.Equal(t, 2, doc.Root().GetText("k1").TreeByID().Len()) + }) } diff --git a/test/integration/text_test.go b/test/integration/text_test.go index b85be27d4..890c4857f 100644 --- a/test/integration/text_test.go +++ b/test/integration/text_test.go @@ -262,6 +262,8 @@ func TestText(t *testing.T) { syncClientsThenAssertEqual(t, []clientAndDocPair{{c1, d1}, {c2, d2}}) assert.True(t, d1.Root().GetText("k1").CheckWeight()) assert.True(t, d2.Root().GetText("k1").CheckWeight()) + assert.True(t, d1.Root().GetText("k1").TreeByIndex().CheckWeight()) + assert.True(t, d2.Root().GetText("k1").TreeByIndex().CheckWeight()) }) // Peritext test