tile38/internal/server/group.go

151 lines
3.2 KiB
Go

package server
import (
"github.com/tidwall/btree"
)
func byGroupHook(va, vb interface{}) bool {
a, b := va.(*groupItem), vb.(*groupItem)
if a.hookName < b.hookName {
return true
}
if a.hookName > b.hookName {
return false
}
if a.colKey < b.colKey {
return true
}
if a.colKey > b.colKey {
return false
}
return a.objID < b.objID
}
func byGroupObject(va, vb interface{}) bool {
a, b := va.(*groupItem), vb.(*groupItem)
if a.colKey < b.colKey {
return true
}
if a.colKey > b.colKey {
return false
}
if a.objID < b.objID {
return true
}
if a.objID > b.objID {
return false
}
return a.hookName < b.hookName
}
type groupItem struct {
hookName string
colKey string
objID string
groupID string
}
func newGroupItem(hookName, colKey, objID string) *groupItem {
groupID := bsonID()
g := &groupItem{}
// create a single string allocation
ustr := hookName + colKey + objID + groupID
var pos int
g.hookName = ustr[pos : pos+len(hookName)]
pos += len(hookName)
g.colKey = ustr[pos : pos+len(colKey)]
pos += len(colKey)
g.objID = ustr[pos : pos+len(objID)]
pos += len(objID)
g.groupID = ustr[pos : pos+len(groupID)]
pos += len(groupID)
return g
}
func (s *Server) groupConnect(hookName, colKey, objID string) (groupID string) {
g := newGroupItem(hookName, colKey, objID)
s.groupHooks.Set(g)
s.groupObjects.Set(g)
return g.groupID
}
func (s *Server) groupDisconnect(hookName, colKey, objID string) {
g := &groupItem{
hookName: hookName,
colKey: colKey,
objID: objID,
}
s.groupHooks.Delete(g)
s.groupObjects.Delete(g)
}
func (s *Server) groupGet(hookName, colKey, objID string) (groupID string) {
v := s.groupHooks.Get(&groupItem{
hookName: hookName,
colKey: colKey,
objID: objID,
})
if v != nil {
return v.(*groupItem).groupID
}
return ""
}
func deleteGroups(s *Server, groups []*groupItem) {
var hhint btree.PathHint
var ohint btree.PathHint
for _, g := range groups {
s.groupHooks.DeleteHint(g, &hhint)
s.groupObjects.DeleteHint(g, &ohint)
}
}
// groupDisconnectObject disconnects all hooks from provide object
func (s *Server) groupDisconnectObject(colKey, objID string) {
var groups []*groupItem
s.groupObjects.Ascend(&groupItem{colKey: colKey, objID: objID},
func(v interface{}) bool {
g := v.(*groupItem)
if g.colKey != colKey || g.objID != objID {
return false
}
groups = append(groups, g)
return true
},
)
deleteGroups(s, groups)
}
// groupDisconnectCollection disconnects all hooks from objects in provided
// collection.
func (s *Server) groupDisconnectCollection(colKey string) {
var groups []*groupItem
s.groupObjects.Ascend(&groupItem{colKey: colKey},
func(v interface{}) bool {
g := v.(*groupItem)
if g.colKey != colKey {
return false
}
groups = append(groups, g)
return true
},
)
deleteGroups(s, groups)
}
// groupDisconnectHook disconnects all objects from provided hook.
func (s *Server) groupDisconnectHook(hookName string) {
var groups []*groupItem
s.groupHooks.Ascend(&groupItem{hookName: hookName},
func(v interface{}) bool {
g := v.(*groupItem)
if g.hookName != hookName {
return false
}
groups = append(groups, g)
return true
},
)
deleteGroups(s, groups)
}