Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Registered channels should be eagerly created on startup, and should
remain (and be visible in LIST) even when they have no members.
  • Loading branch information
slingamn committed Feb 3, 2021
1 parent 4860c5c commit 8c111ec
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 22 deletions.
15 changes: 4 additions & 11 deletions irc/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,6 @@ func (channel *Channel) MarkDirty(dirtyBits uint) {
// ChannelManager's lock (that way, no one can join and make the channel dirty again
// between this method exiting and the actual deletion).
func (channel *Channel) IsClean() bool {
config := channel.server.Config()

if !channel.writerSemaphore.TryAcquire() {
// a database write (which may fail) is in progress, the channel cannot be cleaned up
return false
Expand All @@ -223,13 +221,8 @@ func (channel *Channel) IsClean() bool {
if len(channel.members) != 0 {
return false
}
if channel.registeredFounder == "" {
return true
}
// a registered channel must be fully written to the DB,
// and not set to ephemeral history (#704)
return channel.dirtyBits == 0 &&
channelHistoryStatus(config, true, channel.settings.History) != HistoryEphemeral
// see #1507 and #704 among others; registered channels should never be removed
return channel.registeredFounder == ""
}

func (channel *Channel) wakeWriter() {
Expand Down Expand Up @@ -793,7 +786,7 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
return joinErr, ""
}

client.server.logger.Debug("join", fmt.Sprintf("%s joined channel %s", details.nick, chname))
client.server.logger.Debug("channels", fmt.Sprintf("%s joined channel %s", details.nick, chname))

givenMode := func() (givenMode modes.Mode) {
channel.joinPartMutex.Lock()
Expand Down Expand Up @@ -1033,7 +1026,7 @@ func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer)
}, details.account)
}

client.server.logger.Debug("part", fmt.Sprintf("%s left channel %s", details.nick, chname))
client.server.logger.Debug("channels", fmt.Sprintf("%s left channel %s", details.nick, chname))
}

// Resume is called after a successful global resume to:
Expand Down
39 changes: 31 additions & 8 deletions irc/channelmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,46 @@ func (cm *ChannelManager) loadRegisteredChannels(config *Config) {
return
}

var newChannels []*Channel
var collisions []string
defer func() {
for _, ch := range newChannels {
ch.EnsureLoaded()
cm.server.logger.Debug("channels", "initialized registered channel", ch.Name())
}
for _, collision := range collisions {
cm.server.logger.Warning("channels", "registered channel collides with existing channel", collision)
}
}()

rawNames := cm.server.channelRegistry.AllChannels()
registeredChannels := make(utils.StringSet, len(rawNames))
registeredSkeletons := make(utils.StringSet, len(rawNames))

cm.Lock()
defer cm.Unlock()

cm.registeredChannels = make(utils.StringSet, len(rawNames))
cm.registeredSkeletons = make(utils.StringSet, len(rawNames))
for _, name := range rawNames {
cfname, err := CasefoldChannel(name)
if err == nil {
registeredChannels.Add(cfname)
cm.registeredChannels.Add(cfname)
}
skeleton, err := Skeleton(name)
if err == nil {
registeredSkeletons.Add(skeleton)
cm.registeredSkeletons.Add(skeleton)
}

if _, ok := cm.chans[cfname]; !ok {
ch := NewChannel(cm.server, name, cfname, true)
cm.chans[cfname] = &channelManagerEntry{
channel: ch,
pendingJoins: 0,
}
newChannels = append(newChannels, ch)
} else {
collisions = append(collisions, name)
}
}
cm.Lock()
defer cm.Unlock()
cm.registeredChannels = registeredChannels
cm.registeredSkeletons = registeredSkeletons
}

// Get returns an existing channel with name equivalent to `name`, or nil
Expand Down
5 changes: 2 additions & 3 deletions irc/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -1614,9 +1614,8 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp

nick := client.Nick()
rplList := func(channel *Channel) {
if members, name, topic := channel.listData(); members != 0 {
rb.Add(nil, client.server.name, RPL_LIST, nick, name, strconv.Itoa(members), topic)
}
members, name, topic := channel.listData()
rb.Add(nil, client.server.name, RPL_LIST, nick, name, strconv.Itoa(members), topic)
}

clientIsOp := client.HasMode(modes.Operator)
Expand Down

0 comments on commit 8c111ec

Please sign in to comment.