diff options
author | Valery Piashchynski <[email protected]> | 2021-09-16 17:12:37 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2021-09-16 17:12:37 +0300 |
commit | f3491c089b4da77fd8d2bc942a88b6b8d117a8a5 (patch) | |
tree | 32bfffb1f24eeee7b909747cc00a6a6b9fd3ee83 /pkg/bst | |
parent | 5d2cd55ab522d4f1e65a833f91146444465a32ac (diff) |
Move plugins to a separate repository
Signed-off-by: Valery Piashchynski <[email protected]>
Diffstat (limited to 'pkg/bst')
-rw-r--r-- | pkg/bst/bst.go | 152 | ||||
-rw-r--r-- | pkg/bst/bst_test.go | 325 | ||||
-rw-r--r-- | pkg/bst/doc.go | 7 | ||||
-rw-r--r-- | pkg/bst/interface.go | 13 |
4 files changed, 0 insertions, 497 deletions
diff --git a/pkg/bst/bst.go b/pkg/bst/bst.go deleted file mode 100644 index dab9346c..00000000 --- a/pkg/bst/bst.go +++ /dev/null @@ -1,152 +0,0 @@ -package bst - -// BST ... -type BST struct { - // registered topic, not unique - topic string - // associated connections with the topic - uuids map[string]struct{} - - // left and right subtrees - left *BST - right *BST -} - -func NewBST() Storage { - return &BST{ - uuids: make(map[string]struct{}, 10), - } -} - -// Insert uuid to the topic -func (b *BST) Insert(uuid string, topic string) { - curr := b - - for { - if topic == curr.topic { - curr.uuids[uuid] = struct{}{} - return - } - // if topic less than curr topic - if topic < curr.topic { - if curr.left == nil { - curr.left = &BST{ - topic: topic, - uuids: map[string]struct{}{uuid: {}}, - } - return - } - // move forward - curr = curr.left - } else { - if curr.right == nil { - curr.right = &BST{ - topic: topic, - uuids: map[string]struct{}{uuid: {}}, - } - return - } - - curr = curr.right - } - } -} - -func (b *BST) Contains(topic string) bool { - curr := b - for curr != nil { - switch { - case topic < curr.topic: - curr = curr.left - case topic > curr.topic: - curr = curr.right - case topic == curr.topic: - return true - } - } - - return false -} - -func (b *BST) Get(topic string) map[string]struct{} { - curr := b - for curr != nil { - switch { - case topic < curr.topic: - curr = curr.left - case topic > curr.topic: - curr = curr.right - case topic == curr.topic: - return curr.uuids - } - } - - return nil -} - -func (b *BST) Remove(uuid string, topic string) { - b.removeHelper(uuid, topic, nil) -} - -func (b *BST) removeHelper(uuid string, topic string, parent *BST) { - curr := b - for curr != nil { - if topic < curr.topic { //nolint:gocritic - parent = curr - curr = curr.left - } else if topic > curr.topic { - parent = curr - curr = curr.right - } else { - // if more than 1 topic - remove only topic, do not remove the whole vertex - if len(curr.uuids) > 1 { - if _, ok := curr.uuids[uuid]; ok { - delete(curr.uuids, uuid) - return - } - } - - if curr.left != nil && curr.right != nil { //nolint:gocritic - curr.topic, curr.uuids = curr.right.traverseForMinString() - curr.right.removeHelper(curr.topic, uuid, curr) - } else if parent == nil { - if curr.left != nil { //nolint:gocritic - curr.topic = curr.left.topic - curr.uuids = curr.left.uuids - - curr.right = curr.left.right - curr.left = curr.left.left - } else if curr.right != nil { - curr.topic = curr.right.topic - curr.uuids = curr.right.uuids - - curr.left = curr.right.left - curr.right = curr.right.right - } else { //nolint:staticcheck - // single node tree - } - } else if parent.left == curr { - if curr.left != nil { - parent.left = curr.left - } else { - parent.left = curr.right - } - } else if parent.right == curr { - if curr.left != nil { - parent.right = curr.left - } else { - parent.right = curr.right - } - } - break - } - } -} - -//go:inline -func (b *BST) traverseForMinString() (string, map[string]struct{}) { - if b.left == nil { - return b.topic, b.uuids - } - return b.left.traverseForMinString() -} diff --git a/pkg/bst/bst_test.go b/pkg/bst/bst_test.go deleted file mode 100644 index 2271508c..00000000 --- a/pkg/bst/bst_test.go +++ /dev/null @@ -1,325 +0,0 @@ -package bst - -import ( - "math/rand" - "testing" - "time" - - "github.com/google/uuid" - "github.com/stretchr/testify/assert" -) - -const predifined = "chat-1-2" - -func TestNewBST(t *testing.T) { - // create a new bst - g := NewBST() - - for i := 0; i < 100; i++ { - g.Insert(uuid.NewString(), "comments") - } - - for i := 0; i < 100; i++ { - g.Insert(uuid.NewString(), "comments2") - } - - for i := 0; i < 100; i++ { - g.Insert(uuid.NewString(), "comments3") - } - - // should be 100 - exist := g.Get("comments") - assert.Len(t, exist, 100) - - // should be 100 - exist2 := g.Get("comments2") - assert.Len(t, exist2, 100) - - // should be 100 - exist3 := g.Get("comments3") - assert.Len(t, exist3, 100) -} - -func BenchmarkGraph(b *testing.B) { - g := NewBST() - - for i := 0; i < 1000; i++ { - uid := uuid.New().String() - g.Insert(uuid.NewString(), uid) - } - - g.Insert(uuid.NewString(), predifined) - - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - exist := g.Get(predifined) - _ = exist - } -} - -func BenchmarkBigSearch(b *testing.B) { - g1 := NewBST() - g2 := NewBST() - g3 := NewBST() - - predefinedSlice := make([]string, 0, 1000) - for i := 0; i < 1000; i++ { - predefinedSlice = append(predefinedSlice, uuid.NewString()) - } - if predefinedSlice == nil { - b.FailNow() - } - - for i := 0; i < 1000; i++ { - g1.Insert(uuid.NewString(), uuid.NewString()) - } - for i := 0; i < 1000; i++ { - g2.Insert(uuid.NewString(), uuid.NewString()) - } - for i := 0; i < 1000; i++ { - g3.Insert(uuid.NewString(), uuid.NewString()) - } - - for i := 0; i < 333; i++ { - g1.Insert(uuid.NewString(), predefinedSlice[i]) - } - - for i := 0; i < 333; i++ { - g2.Insert(uuid.NewString(), predefinedSlice[333+i]) - } - - for i := 0; i < 333; i++ { - g3.Insert(uuid.NewString(), predefinedSlice[666+i]) - } - - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - for i := 0; i < 333; i++ { - exist := g1.Get(predefinedSlice[i]) - _ = exist - } - } - for i := 0; i < b.N; i++ { - for i := 0; i < 333; i++ { - exist := g2.Get(predefinedSlice[333+i]) - _ = exist - } - } - for i := 0; i < b.N; i++ { - for i := 0; i < 333; i++ { - exist := g3.Get(predefinedSlice[666+i]) - _ = exist - } - } -} - -func BenchmarkBigSearchWithRemoves(b *testing.B) { - g1 := NewBST() - g2 := NewBST() - g3 := NewBST() - - predefinedSlice := make([]string, 0, 1000) - for i := 0; i < 1000; i++ { - predefinedSlice = append(predefinedSlice, uuid.NewString()) - } - if predefinedSlice == nil { - b.FailNow() - } - - for i := 0; i < 1000; i++ { - g1.Insert(uuid.NewString(), uuid.NewString()) - } - for i := 0; i < 1000; i++ { - g2.Insert(uuid.NewString(), uuid.NewString()) - } - for i := 0; i < 1000; i++ { - g3.Insert(uuid.NewString(), uuid.NewString()) - } - - for i := 0; i < 333; i++ { - g1.Insert(uuid.NewString(), predefinedSlice[i]) - } - - for i := 0; i < 333; i++ { - g2.Insert(uuid.NewString(), predefinedSlice[333+i]) - } - - for i := 0; i < 333; i++ { - g3.Insert(uuid.NewString(), predefinedSlice[666+i]) - } - - go func() { - tt := time.NewTicker(time.Millisecond) - for { - select { - case <-tt.C: - num := rand.Intn(333) //nolint:gosec - values := g1.Get(predefinedSlice[num]) - for k := range values { - g1.Remove(k, predefinedSlice[num]) - } - } - } - }() - - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - for i := 0; i < 333; i++ { - exist := g1.Get(predefinedSlice[i]) - _ = exist - } - } - for i := 0; i < b.N; i++ { - for i := 0; i < 333; i++ { - exist := g2.Get(predefinedSlice[333+i]) - _ = exist - } - } - for i := 0; i < b.N; i++ { - for i := 0; i < 333; i++ { - exist := g3.Get(predefinedSlice[666+i]) - _ = exist - } - } -} - -func TestGraph(t *testing.T) { - g := NewBST() - - for i := 0; i < 1000; i++ { - uid := uuid.New().String() - g.Insert(uuid.NewString(), uid) - } - - g.Insert(uuid.NewString(), predifined) - - exist := g.Get(predifined) - assert.NotNil(t, exist) - assert.Len(t, exist, 1) -} - -func TestTreeConcurrentContains(t *testing.T) { - g := NewBST() - - key1 := uuid.NewString() - key2 := uuid.NewString() - key3 := uuid.NewString() - key4 := uuid.NewString() - key5 := uuid.NewString() - - g.Insert(key1, predifined) - g.Insert(key2, predifined) - g.Insert(key3, predifined) - g.Insert(key4, predifined) - g.Insert(key5, predifined) - - for i := 0; i < 100; i++ { - go func() { - _ = g.Get(predifined) - }() - - go func() { - _ = g.Get(predifined) - }() - - go func() { - _ = g.Get(predifined) - }() - - go func() { - _ = g.Get(predifined) - }() - } - - time.Sleep(time.Second * 2) - - exist := g.Get(predifined) - assert.NotNil(t, exist) - assert.Len(t, exist, 5) -} - -func TestGraphRemove(t *testing.T) { - g := NewBST() - - key1 := uuid.NewString() - key2 := uuid.NewString() - key3 := uuid.NewString() - key4 := uuid.NewString() - key5 := uuid.NewString() - - g.Insert(key1, predifined) - g.Insert(key2, predifined) - g.Insert(key3, predifined) - g.Insert(key4, predifined) - g.Insert(key5, predifined) - - exist := g.Get(predifined) - assert.NotNil(t, exist) - assert.Len(t, exist, 5) - - g.Remove(key1, predifined) - - exist = g.Get(predifined) - assert.NotNil(t, exist) - assert.Len(t, exist, 4) -} - -func TestBigSearch(t *testing.T) { - g1 := NewBST() - g2 := NewBST() - g3 := NewBST() - - predefinedSlice := make([]string, 0, 1000) - for i := 0; i < 1000; i++ { - predefinedSlice = append(predefinedSlice, uuid.NewString()) - } - if predefinedSlice == nil { - t.FailNow() - } - - for i := 0; i < 1000; i++ { - g1.Insert(uuid.NewString(), uuid.NewString()) - } - for i := 0; i < 1000; i++ { - g2.Insert(uuid.NewString(), uuid.NewString()) - } - for i := 0; i < 1000; i++ { - g3.Insert(uuid.NewString(), uuid.NewString()) - } - - for i := 0; i < 333; i++ { - g1.Insert(uuid.NewString(), predefinedSlice[i]) - } - - for i := 0; i < 333; i++ { - g2.Insert(uuid.NewString(), predefinedSlice[333+i]) - } - - for i := 0; i < 333; i++ { - g3.Insert(uuid.NewString(), predefinedSlice[666+i]) - } - - for i := 0; i < 333; i++ { - exist := g1.Get(predefinedSlice[i]) - assert.NotNil(t, exist) - assert.Len(t, exist, 1) - } - - for i := 0; i < 333; i++ { - exist := g2.Get(predefinedSlice[333+i]) - assert.NotNil(t, exist) - assert.Len(t, exist, 1) - } - - for i := 0; i < 333; i++ { - exist := g3.Get(predefinedSlice[666+i]) - assert.NotNil(t, exist) - assert.Len(t, exist, 1) - } -} diff --git a/pkg/bst/doc.go b/pkg/bst/doc.go deleted file mode 100644 index abb7e6e9..00000000 --- a/pkg/bst/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -package bst - -/* -Binary search tree for the pubsub - -The vertex may have one or multiply topics associated with the single websocket connection UUID -*/ diff --git a/pkg/bst/interface.go b/pkg/bst/interface.go deleted file mode 100644 index 95b03e11..00000000 --- a/pkg/bst/interface.go +++ /dev/null @@ -1,13 +0,0 @@ -package bst - -// Storage is general in-memory BST storage implementation -type Storage interface { - // Insert inserts to a vertex with topic ident connection uuid - Insert(uuid string, topic string) - // Remove removes uuid from topic, if the uuid is single for a topic, whole vertex will be removed - Remove(uuid, topic string) - // Get will return all connections associated with the topic - Get(topic string) map[string]struct{} - // Contains checks if the BST contains a topic - Contains(topic string) bool -} |