Sfoglia il codice sorgente

optimized implementation of Channel.Names()

tags/v0.12.0
Shivaram Lingamneni 6 anni fa
parent
commit
6533893863
1 ha cambiato i file con 38 aggiunte e 48 eliminazioni
  1. 38
    48
      irc/channel.go

+ 38
- 48
irc/channel.go Vedi File

@@ -6,6 +6,7 @@
6 6
 package irc
7 7
 
8 8
 import (
9
+	"bytes"
9 10
 	"crypto/subtle"
10 11
 	"fmt"
11 12
 	"strconv"
@@ -24,7 +25,7 @@ type Channel struct {
24 25
 	lists             map[modes.Mode]*UserMaskSet
25 26
 	key               string
26 27
 	members           MemberSet
27
-	membersCache      []*Client  // allow iteration over channel members without holding the lock
28
+	membersCache      []*Client // allow iteration over channel members without holding the lock
28 29
 	name              string
29 30
 	nameCasefolded    string
30 31
 	server            *Server
@@ -180,27 +181,47 @@ func (channel *Channel) regenerateMembersCache() {
180 181
 
181 182
 // Names sends the list of users joined to the channel to the given client.
182 183
 func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
183
-	currentNicks := channel.nicks(client)
184
-	// assemble and send replies
185
-	maxNamLen := 480 - len(client.server.name) - len(client.nick)
186
-	var buffer string
187
-	for _, nick := range currentNicks {
188
-		if buffer == "" {
189
-			buffer += nick
190
-			continue
184
+	isMultiPrefix := client.capabilities.Has(caps.MultiPrefix)
185
+	isUserhostInNames := client.capabilities.Has(caps.UserhostInNames)
186
+
187
+	maxNamLen := 480 - len(client.server.name) - len(client.Nick())
188
+	var namesLines []string
189
+	var buffer bytes.Buffer
190
+	for _, target := range channel.Members() {
191
+		var nick string
192
+		if isUserhostInNames {
193
+			nick = target.NickMaskString()
194
+		} else {
195
+			nick = target.Nick()
191 196
 		}
192
-
193
-		if len(buffer)+1+len(nick) > maxNamLen {
194
-			rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
195
-			buffer = nick
197
+		channel.stateMutex.RLock()
198
+		modes := channel.members[target]
199
+		channel.stateMutex.RUnlock()
200
+		if modes == nil {
196 201
 			continue
197 202
 		}
198
-
199
-		buffer += " "
200
-		buffer += nick
203
+		prefix := modes.Prefixes(isMultiPrefix)
204
+		if buffer.Len()+len(nick)+len(prefix)+1 > maxNamLen {
205
+			namesLines = append(namesLines, buffer.String())
206
+			// memset(&buffer, 0, sizeof(bytes.Buffer));
207
+			var newBuffer bytes.Buffer
208
+			buffer = newBuffer
209
+		}
210
+		if buffer.Len() > 0 {
211
+			buffer.WriteString(" ")
212
+		}
213
+		buffer.WriteString(prefix)
214
+		buffer.WriteString(nick)
215
+	}
216
+	if buffer.Len() > 0 {
217
+		namesLines = append(namesLines, buffer.String())
201 218
 	}
202 219
 
203
-	rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
220
+	for _, line := range namesLines {
221
+		if buffer.Len() > 0 {
222
+			rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, line)
223
+		}
224
+	}
204 225
 	rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
205 226
 }
206 227
 
@@ -263,37 +284,6 @@ func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool
263 284
 	return result
264 285
 }
265 286
 
266
-func (channel *Channel) nicks(target *Client) []string {
267
-	isMultiPrefix := (target != nil) && target.capabilities.Has(caps.MultiPrefix)
268
-	isUserhostInNames := (target != nil) && target.capabilities.Has(caps.UserhostInNames)
269
-
270
-	// slightly cumbersome: get the mutex and copy both the client pointers and
271
-	// the mode prefixes
272
-	channel.stateMutex.RLock()
273
-	length := len(channel.members)
274
-	clients := make([]*Client, length)
275
-	result := make([]string, length)
276
-	i := 0
277
-	for client, modes := range channel.members {
278
-		clients[i] = client
279
-		result[i] = modes.Prefixes(isMultiPrefix)
280
-		i++
281
-	}
282
-	channel.stateMutex.RUnlock()
283
-
284
-	i = 0
285
-	for i < length {
286
-		if isUserhostInNames {
287
-			result[i] += clients[i].NickMaskString()
288
-		} else {
289
-			result[i] += clients[i].Nick()
290
-		}
291
-		i++
292
-	}
293
-
294
-	return result
295
-}
296
-
297 287
 func (channel *Channel) hasClient(client *Client) bool {
298 288
 	channel.stateMutex.RLock()
299 289
 	defer channel.stateMutex.RUnlock()

Loading…
Annulla
Salva