mirror of
https://github.com/jeremyd/ergo.git
synced 2026-07-27 17:28:11 -07:00
Merge pull request #264 from slingamn/deps.1
reduce copying of output lines
This commit is contained in:
+8
-4
@@ -820,13 +820,13 @@ func (client *Client) SendRawMessage(message ircmsg.IrcMessage) error {
|
||||
|
||||
// assemble message
|
||||
maxlenTags, maxlenRest := client.maxlens()
|
||||
line, err := message.LineMaxLen(maxlenTags, maxlenRest)
|
||||
line, err := message.LineMaxLenBytes(maxlenTags, maxlenRest)
|
||||
if err != nil {
|
||||
logline := fmt.Sprintf("Error assembling message for sending: %v\n%s", err, debug.Stack())
|
||||
client.server.logger.Error("internal", logline)
|
||||
|
||||
message = ircmsg.MakeMessage(nil, client.server.name, ERR_UNKNOWNERROR, "*", "Error assembling message for sending")
|
||||
line, _ := message.Line()
|
||||
line, _ := message.LineBytes()
|
||||
|
||||
client.socket.Write(line)
|
||||
return err
|
||||
@@ -834,10 +834,14 @@ func (client *Client) SendRawMessage(message ircmsg.IrcMessage) error {
|
||||
|
||||
// if we used the trailing hack, we need to strip the final space we appended earlier on
|
||||
if usedTrailingHack {
|
||||
line = line[:len(line)-3] + "\r\n"
|
||||
copy(line[len(line)-3:], []byte{'\r', '\n'})
|
||||
line = line[:len(line)-1]
|
||||
}
|
||||
|
||||
client.server.logger.Debug("useroutput", client.nick, " ->", strings.TrimRight(line, "\r\n"))
|
||||
if client.server.logger.IsLoggingRawIO() {
|
||||
logline := string(line[:len(line)-2]) // strip "\r\n"
|
||||
client.server.logger.Debug("useroutput", client.nick, " ->", logline)
|
||||
}
|
||||
|
||||
client.socket.Write(line)
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
colorable "github.com/mattn/go-colorable"
|
||||
"github.com/mgutz/ansi"
|
||||
@@ -57,7 +58,7 @@ type Manager struct {
|
||||
loggers []singleLogger
|
||||
stdoutWriteLock sync.Mutex // use one lock for both stdout and stderr
|
||||
fileWriteLock sync.Mutex
|
||||
loggingRawIO bool
|
||||
loggingRawIO uint32
|
||||
}
|
||||
|
||||
// LoggingConfig represents the configuration of a single logger.
|
||||
@@ -95,7 +96,7 @@ func (logger *Manager) ApplyConfig(config []LoggingConfig) error {
|
||||
}
|
||||
|
||||
logger.loggers = nil
|
||||
logger.loggingRawIO = false
|
||||
atomic.StoreUint32(&logger.loggingRawIO, 0)
|
||||
|
||||
// for safety, this deep-copies all mutable data in `config`
|
||||
// XXX let's keep it that way
|
||||
@@ -124,7 +125,7 @@ func (logger *Manager) ApplyConfig(config []LoggingConfig) error {
|
||||
fileWriteLock: &logger.fileWriteLock,
|
||||
}
|
||||
if typeMap["userinput"] || typeMap["useroutput"] || (typeMap["*"] && !(excludedTypeMap["userinput"] && excludedTypeMap["useroutput"])) {
|
||||
logger.loggingRawIO = true
|
||||
atomic.StoreUint32(&logger.loggingRawIO, 1)
|
||||
}
|
||||
if sLogger.MethodFile.Enabled {
|
||||
file, err := os.OpenFile(sLogger.MethodFile.Filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
|
||||
@@ -143,9 +144,7 @@ func (logger *Manager) ApplyConfig(config []LoggingConfig) error {
|
||||
|
||||
// IsLoggingRawIO returns true if raw user input and output is being logged.
|
||||
func (logger *Manager) IsLoggingRawIO() bool {
|
||||
logger.configMutex.RLock()
|
||||
defer logger.configMutex.RUnlock()
|
||||
return logger.loggingRawIO
|
||||
return atomic.LoadUint32(&logger.loggingRawIO) == 1
|
||||
}
|
||||
|
||||
// Log logs the given message with the given details.
|
||||
|
||||
+21
-10
@@ -34,7 +34,8 @@ type Socket struct {
|
||||
// this is a trylock enforcing that only one goroutine can write to `conn` at a time
|
||||
writerSemaphore Semaphore
|
||||
|
||||
buffer []byte
|
||||
buffers [][]byte
|
||||
totalLength int
|
||||
closed bool
|
||||
sendQExceeded bool
|
||||
finalData string // what to send when we die
|
||||
@@ -121,15 +122,23 @@ func (socket *Socket) Read() (string, error) {
|
||||
// 2. MUST NOT reorder messages
|
||||
// 3. MUST provide mutual exclusion for socket.conn.Write
|
||||
// 4. SHOULD NOT tie up additional goroutines, beyond the one blocked on socket.conn.Write
|
||||
func (socket *Socket) Write(data string) (err error) {
|
||||
func (socket *Socket) Write(data []byte) (err error) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
socket.Lock()
|
||||
if socket.closed {
|
||||
err = io.EOF
|
||||
} else if len(data)+len(socket.buffer) > socket.maxSendQBytes {
|
||||
socket.sendQExceeded = true
|
||||
err = errSendQExceeded
|
||||
} else {
|
||||
socket.buffer = append(socket.buffer, data...)
|
||||
prospectiveLen := socket.totalLength + len(data)
|
||||
if prospectiveLen > socket.maxSendQBytes {
|
||||
socket.sendQExceeded = true
|
||||
err = errSendQExceeded
|
||||
} else {
|
||||
socket.buffers = append(socket.buffers, data)
|
||||
socket.totalLength = prospectiveLen
|
||||
}
|
||||
}
|
||||
socket.Unlock()
|
||||
|
||||
@@ -165,7 +174,7 @@ func (socket *Socket) readyToWrite() bool {
|
||||
socket.Lock()
|
||||
defer socket.Unlock()
|
||||
// on the first time observing socket.closed, we still have to write socket.finalData
|
||||
return !socket.finalized && (len(socket.buffer) > 0 || socket.closed || socket.sendQExceeded)
|
||||
return !socket.finalized && (socket.totalLength > 0 || socket.closed || socket.sendQExceeded)
|
||||
}
|
||||
|
||||
// send actually writes messages to socket.Conn; it may block
|
||||
@@ -193,11 +202,13 @@ func (socket *Socket) send() {
|
||||
func (socket *Socket) performWrite() {
|
||||
// retrieve the buffered data, clear the buffer
|
||||
socket.Lock()
|
||||
buffer := socket.buffer
|
||||
socket.buffer = nil
|
||||
buffers := socket.buffers
|
||||
socket.buffers = nil
|
||||
socket.totalLength = 0
|
||||
socket.Unlock()
|
||||
|
||||
_, err := socket.conn.Write(buffer)
|
||||
// on Linux, the runtime will optimize this into a single writev(2) call:
|
||||
_, err := (*net.Buffers)(&buffers).WriteTo(socket.conn)
|
||||
|
||||
socket.Lock()
|
||||
shouldClose := (err != nil) || socket.closed || socket.sendQExceeded
|
||||
|
||||
Reference in New Issue
Block a user