<commit_before>package events

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"
	"sync"
	"time"

	"github.com/gorilla/websocket"

	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/logger"
)

// EventListenerConnection represents an event listener connection.
type EventListenerConnection interface {
	Reader(ctx context.Context, recvFunc EventHandler)
	WriteJSON(event any) error
	Close() error
	LocalAddr() net.Addr  // Used for logging
	RemoteAddr() net.Addr // Used for logging
}

type websockListenerConnection struct {
	*websocket.Conn

	lock         sync.Mutex
	pongsPending int
}

type streamListenerConnection struct {
	net.Conn

	lock sync.Mutex
}

// NewWebsocketListenerConnection returns a new websocket listener connection.
func NewWebsocketListenerConnection(connection *websocket.Conn) EventListenerConnection {
	return &websockListenerConnection{
		Conn: connection,
	}
}

func (e *websockListenerConnection) Reader(ctx context.Context, recvFunc EventHandler) {
	ctx, cancel := context.WithCancel(ctx)

	close := func() {
		e.lock.Lock()
		defer e.lock.Unlock()

		if ctx.Err() != nil {
			return
		}

		_ = e.Close()
		cancel()
	}

	defer close()

	pingInterval := time.Second * 10
	e.pongsPending = 0

	e.SetPongHandler(func(msg string) error {
		e.lock.Lock()
		e.pongsPending = 0
		e.lock.Unlock()
		return nil
	})

	// Start reader from client.
	go func() {
		defer close()

		if recvFunc != nil {
			for {
				var event api.Event
				err := e.Conn.ReadJSON(&event)
				if err != nil {
					return // This detects if client has disconnected or sent invalid data.
				}

				// Pass received event to the handler.
				recvFunc(event)
			}
		} else {
			// Run a blocking reader to detect if the client has disconnected. We don't expect to get
			// anything from the remote side, so this should remain blocked until disconnected.
			_, _, _ = e.Conn.NextReader()
		}
	}()

	for {
		if ctx.Err() != nil {
			return
		}

		e.lock.Lock()
		if e.pongsPending > 2 {
			e.lock.Unlock()
			return
		}
		err := e.WriteControl(websocket.PingMessage, []byte("keepalive"), time.Now().Add(5*time.Second))
		if err != nil {
			e.lock.Unlock()
			return
		}

		e.pongsPending++
		e.lock.Unlock()

		select {
		case <-time.After(pingInterval):
		case <-ctx.Done():
			return
		}
	}
}

func (e *websockListenerConnection) WriteJSON(event any) error {
	e.lock.Lock()
	defer e.lock.Unlock()

	err := e.Conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
	if err != nil {
		return fmt.Errorf("Failed setting write deadline: %w", err)
	}

	return e.Conn.WriteJSON(event)
}

// NewStreamListenerConnection returns a new http stream listener connection.
func NewStreamListenerConnection(connection net.Conn) (EventListenerConnection, error) {
	// Send HTTP response to let the client know what to expect.
	// This is only sent once, and is followed by events.
	//
	// The X-Content-Type-Options response HTTP header is a marker used by the server to indicate
	// that the MIME types advertised in the Content-Type headers should be followed and not be
	// changed. The header allows you to avoid MIME type sniffing by saying that the MIME types are
	// deliberately configured.
	_, err := io.WriteString(connection, `HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json
X-Content-Type-Options: nosniff

`)
	if err != nil {
		return nil, fmt.Errorf("Failed sending initial HTTP response: %w", err)
	}

	return &streamListenerConnection{
		Conn: connection,
	}, nil
}

func (e *streamListenerConnection) Reader(ctx context.Context, recvFunc EventHandler) {
	ctx, cancelFunc := context.WithCancel(ctx)

	close := func() {
		e.lock.Lock()
		defer e.lock.Unlock()

		if ctx.Err() != nil {
			return
		}

		err := e.Close()
		if err != nil {
			logger.Warn("Failed closing connection", logger.Ctx{"err": err})
		}

		cancelFunc()
	}

	defer close()

	// Start reader from client.
	go func() {
		defer close()

		buf := make([]byte, 1)

		// This is used to determine whether the client has terminated.
		_, err := e.Read(buf)
		if err != nil && errors.Is(err, io.EOF) {
			return
		}
	}()

	for {
		if ctx.Err() != nil {
			return
		}

		select {
		case <-ctx.Done():
			return
		}
	}
}

func (e *streamListenerConnection) WriteJSON(event any) error {
	e.lock.Lock()
	defer e.lock.Unlock()

	err := e.SetWriteDeadline(time.Now().Add(5 * (time.Second)))
	if err != nil {
		return fmt.Errorf("Failed setting write deadline: %w", err)
	}

	err = json.NewEncoder(e.Conn).Encode(event)
	if err != nil {
		return fmt.Errorf("Failed sending event: %w", err)
	}

	return nil
}

func (e *streamListenerConnection) Close() error {
	return e.Conn.Close()
}
<commit_msg>lxd/events: Fixes gosimple lint errors.<commit_after>package events

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"
	"sync"
	"time"

	"github.com/gorilla/websocket"

	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/logger"
)

// EventListenerConnection represents an event listener connection.
type EventListenerConnection interface {
	Reader(ctx context.Context, recvFunc EventHandler)
	WriteJSON(event any) error
	Close() error
	LocalAddr() net.Addr  // Used for logging
	RemoteAddr() net.Addr // Used for logging
}

type websockListenerConnection struct {
	*websocket.Conn

	lock         sync.Mutex
	pongsPending int
}

type streamListenerConnection struct {
	net.Conn

	lock sync.Mutex
}

// NewWebsocketListenerConnection returns a new websocket listener connection.
func NewWebsocketListenerConnection(connection *websocket.Conn) EventListenerConnection {
	return &websockListenerConnection{
		Conn: connection,
	}
}

func (e *websockListenerConnection) Reader(ctx context.Context, recvFunc EventHandler) {
	ctx, cancel := context.WithCancel(ctx)

	close := func() {
		e.lock.Lock()
		defer e.lock.Unlock()

		if ctx.Err() != nil {
			return
		}

		_ = e.Close()
		cancel()
	}

	defer close()

	pingInterval := time.Second * 10
	e.pongsPending = 0

	e.SetPongHandler(func(msg string) error {
		e.lock.Lock()
		e.pongsPending = 0
		e.lock.Unlock()
		return nil
	})

	// Start reader from client.
	go func() {
		defer close()

		if recvFunc != nil {
			for {
				var event api.Event
				err := e.Conn.ReadJSON(&event)
				if err != nil {
					return // This detects if client has disconnected or sent invalid data.
				}

				// Pass received event to the handler.
				recvFunc(event)
			}
		} else {
			// Run a blocking reader to detect if the client has disconnected. We don't expect to get
			// anything from the remote side, so this should remain blocked until disconnected.
			_, _, _ = e.Conn.NextReader()
		}
	}()

	for {
		if ctx.Err() != nil {
			return
		}

		e.lock.Lock()
		if e.pongsPending > 2 {
			e.lock.Unlock()
			return
		}
		err := e.WriteControl(websocket.PingMessage, []byte("keepalive"), time.Now().Add(5*time.Second))
		if err != nil {
			e.lock.Unlock()
			return
		}

		e.pongsPending++
		e.lock.Unlock()

		select {
		case <-time.After(pingInterval):
		case <-ctx.Done():
			return
		}
	}
}

func (e *websockListenerConnection) WriteJSON(event any) error {
	e.lock.Lock()
	defer e.lock.Unlock()

	err := e.Conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
	if err != nil {
		return fmt.Errorf("Failed setting write deadline: %w", err)
	}

	return e.Conn.WriteJSON(event)
}

// NewStreamListenerConnection returns a new http stream listener connection.
func NewStreamListenerConnection(connection net.Conn) (EventListenerConnection, error) {
	// Send HTTP response to let the client know what to expect.
	// This is only sent once, and is followed by events.
	//
	// The X-Content-Type-Options response HTTP header is a marker used by the server to indicate
	// that the MIME types advertised in the Content-Type headers should be followed and not be
	// changed. The header allows you to avoid MIME type sniffing by saying that the MIME types are
	// deliberately configured.
	_, err := io.WriteString(connection, `HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json
X-Content-Type-Options: nosniff

`)
	if err != nil {
		return nil, fmt.Errorf("Failed sending initial HTTP response: %w", err)
	}

	return &streamListenerConnection{
		Conn: connection,
	}, nil
}

func (e *streamListenerConnection) Reader(ctx context.Context, recvFunc EventHandler) {
	ctx, cancelFunc := context.WithCancel(ctx)

	close := func() {
		e.lock.Lock()
		defer e.lock.Unlock()

		if ctx.Err() != nil {
			return
		}

		err := e.Close()
		if err != nil {
			logger.Warn("Failed closing connection", logger.Ctx{"err": err})
		}

		cancelFunc()
	}

	defer close()

	// Start reader from client.
	go func() {
		defer close()

		buf := make([]byte, 1)

		// This is used to determine whether the client has terminated.
		_, err := e.Read(buf)
		if err != nil && errors.Is(err, io.EOF) {
			return
		}
	}()

	if ctx.Err() != nil {
		return
	}

	<-ctx.Done()
}

func (e *streamListenerConnection) WriteJSON(event any) error {
	e.lock.Lock()
	defer e.lock.Unlock()

	err := e.SetWriteDeadline(time.Now().Add(5 * (time.Second)))
	if err != nil {
		return fmt.Errorf("Failed setting write deadline: %w", err)
	}

	err = json.NewEncoder(e.Conn).Encode(event)
	if err != nil {
		return fmt.Errorf("Failed sending event: %w", err)
	}

	return nil
}

func (e *streamListenerConnection) Close() error {
	return e.Conn.Close()
}
<|endoftext|>


<commit_before>package bunyan

import (
	"fmt"
	"log"
)

type Logger struct {
	*log.Logger
	name        string
	streams     []StreamInterface
	sync        bool
	minLogLevel LogLevel
}

// Creates a new logger, given one or more streams
func NewLogger(name string, streams []StreamInterface) *Logger {
	return &Logger{
		name:     name,
		streams:  streams,
		sync:     false,
		minLevel: 0,
	}
}

func (l *Logger) SetSynchronous(sync bool) {
	l.sync = sync
}

func (l *Logger) SetGlobalMinLogLevel(minLogLevel LogLevel) {
	l.minLevel = minLogLevel
}

func (l *Logger) AddStream(s StreamInterface) {
	l.streams = append(l.streams, s)
}

func (l *Logger) Log(e *LogEntry) {
	e.setLogger(l)

	if e.Level < l.minLogLevel {
		return
	}

	if l.sync {
		for _, stream := range l.streams {
			stream.Publish(e)
		}
	} else {
		for _, stream := range l.streams {
			go stream.Publish(e)
		}

	}
}

func (l *Logger) Logln(level LogLevel, message string) *LogEntry {
	e := NewLogEntry(level, message)

	l.Log(e)

	return e
}

func (l *Logger) LogF(level LogLevel, format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(level, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Trace(message string) *LogEntry {
	e := NewLogEntry(Trace, message)

	l.Log(e)

	return e
}

func (l *Logger) TraceF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Trace, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Debug(message string) *LogEntry {
	e := NewLogEntry(Debug, message)

	l.Log(e)

	return e
}

func (l *Logger) DebugF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Debug, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Info(message string) *LogEntry {
	e := NewLogEntry(Info, message)

	l.Log(e)

	return e
}

func (l *Logger) InfoF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Info, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Warn(message string) *LogEntry {
	e := NewLogEntry(Warn, message)

	l.Log(e)

	return e
}

func (l *Logger) WarnF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Warn, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Error(message string) *LogEntry {
	e := NewLogEntry(Error, message)

	l.Log(e)

	return e
}

func (l *Logger) ErrorF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Error, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Fatal(message string) *LogEntry {
	e := NewLogEntry(Fatal, message)

	l.Log(e)

	return e
}

func (l *Logger) FatalF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Fatal, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

// log.Logger compatibility

func (l *Logger) Println(val interface{}) {
	l.Logln(Info, fmt.Sprintf("%v", val))
}
<commit_msg>- Fix typo<commit_after>package bunyan

import (
	"fmt"
	"log"
)

type Logger struct {
	*log.Logger
	name        string
	streams     []StreamInterface
	sync        bool
	minLogLevel LogLevel
}

// Creates a new logger, given one or more streams
func NewLogger(name string, streams []StreamInterface) *Logger {
	return &Logger{
		name:        name,
		streams:     streams,
		sync:        false,
		minLogLevel: 0,
	}
}

func (l *Logger) SetSynchronous(sync bool) {
	l.sync = sync
}

func (l *Logger) SetGlobalMinLogLevel(minLogLevel LogLevel) {
	l.minLogLevel = minLogLevel
}

func (l *Logger) AddStream(s StreamInterface) {
	l.streams = append(l.streams, s)
}

func (l *Logger) Log(e *LogEntry) {
	e.setLogger(l)

	if e.Level < l.minLogLevel {
		return
	}

	if l.sync {
		for _, stream := range l.streams {
			stream.Publish(e)
		}
	} else {
		for _, stream := range l.streams {
			go stream.Publish(e)
		}

	}
}

func (l *Logger) Logln(level LogLevel, message string) *LogEntry {
	e := NewLogEntry(level, message)

	l.Log(e)

	return e
}

func (l *Logger) LogF(level LogLevel, format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(level, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Trace(message string) *LogEntry {
	e := NewLogEntry(Trace, message)

	l.Log(e)

	return e
}

func (l *Logger) TraceF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Trace, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Debug(message string) *LogEntry {
	e := NewLogEntry(Debug, message)

	l.Log(e)

	return e
}

func (l *Logger) DebugF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Debug, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Info(message string) *LogEntry {
	e := NewLogEntry(Info, message)

	l.Log(e)

	return e
}

func (l *Logger) InfoF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Info, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Warn(message string) *LogEntry {
	e := NewLogEntry(Warn, message)

	l.Log(e)

	return e
}

func (l *Logger) WarnF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Warn, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Error(message string) *LogEntry {
	e := NewLogEntry(Error, message)

	l.Log(e)

	return e
}

func (l *Logger) ErrorF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Error, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

func (l *Logger) Fatal(message string) *LogEntry {
	e := NewLogEntry(Fatal, message)

	l.Log(e)

	return e
}

func (l *Logger) FatalF(format string, values ...interface{}) *LogEntry {
	e := NewLogEntry(Fatal, fmt.Sprintf(format, values...))

	l.Log(e)

	return e
}

// log.Logger compatibility

func (l *Logger) Println(val interface{}) {
	l.Logln(Info, fmt.Sprintf("%v", val))
}
<|endoftext|>


<commit_before>package gormrus

import (
	"database/sql/driver"
	"fmt"
	"github.com/Sirupsen/logrus"
	"reflect"
	"regexp"
	"time"
)

var sqlRegexp = regexp.MustCompile(`(\$\d+)|\?`)

type gormLogger struct {
	name   string
	logger *logrus.Logger
}

func (l *gormLogger) Print(values ...interface{}) {
	entry := l.logger.WithField("name", l.name)
	if len(values) > 1 {
		level := values[0]
		source := values[1]
		entry = l.logger.WithField("source", source)
		if level == "sql" {
			duration := values[2]
			// sql
			var formattedValues []interface{}
			for _, value := range values[4].([]interface{}) {
				indirectValue := reflect.Indirect(reflect.ValueOf(value))
				if indirectValue.IsValid() {
					value = indirectValue.Interface()
					if t, ok := value.(time.Time); ok {
						formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format(time.RFC3339)))
					} else if b, ok := value.([]byte); ok {
						formattedValues = append(formattedValues, fmt.Sprintf("'%v'", string(b)))
					} else if r, ok := value.(driver.Valuer); ok {
						if value, err := r.Value(); err == nil && value != nil {
							formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
						} else {
							formattedValues = append(formattedValues, "NULL")
						}
					} else {
						formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
					}
				} else {
					formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
				}
			}
			entry.WithField("took", duration).Debug(fmt.Sprintf(sqlRegexp.ReplaceAllString(values[3].(string), "%v"), formattedValues...))
		} else {
			entry.Error(values[2:]...)
		}
	} else {
		entry.Error(values...)
	}

}

// New Create new logger
func New() *gormLogger {
	return NewWithName("db")
}

// NewWithName Create new logger with custom name
func NewWithName(name string) *gormLogger {
	return NewWithNameAndLogger(name, logrus.StandardLogger())
}

// NewWithLogger Create new logger with custom logger
func NewWithLogger(logger *logrus.Logger) *gormLogger {
	return NewWithNameAndLogger("db", logger)
}

// NewWithNameAndLogger Create new logger with custom name and logger
func NewWithNameAndLogger(name string, logger *logrus.Logger) *gormLogger {
	return &gormLogger{name: name, logger: logger}
}
<commit_msg>Update logrus reference to lower-case variant<commit_after>package gormrus

import (
	"database/sql/driver"
	"fmt"
	"github.com/sirupsen/logrus"
	"reflect"
	"regexp"
	"time"
)

var sqlRegexp = regexp.MustCompile(`(\$\d+)|\?`)

type gormLogger struct {
	name   string
	logger *logrus.Logger
}

func (l *gormLogger) Print(values ...interface{}) {
	entry := l.logger.WithField("name", l.name)
	if len(values) > 1 {
		level := values[0]
		source := values[1]
		entry = l.logger.WithField("source", source)
		if level == "sql" {
			duration := values[2]
			// sql
			var formattedValues []interface{}
			for _, value := range values[4].([]interface{}) {
				indirectValue := reflect.Indirect(reflect.ValueOf(value))
				if indirectValue.IsValid() {
					value = indirectValue.Interface()
					if t, ok := value.(time.Time); ok {
						formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format(time.RFC3339)))
					} else if b, ok := value.([]byte); ok {
						formattedValues = append(formattedValues, fmt.Sprintf("'%v'", string(b)))
					} else if r, ok := value.(driver.Valuer); ok {
						if value, err := r.Value(); err == nil && value != nil {
							formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
						} else {
							formattedValues = append(formattedValues, "NULL")
						}
					} else {
						formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
					}
				} else {
					formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
				}
			}
			entry.WithField("took", duration).Debug(fmt.Sprintf(sqlRegexp.ReplaceAllString(values[3].(string), "%v"), formattedValues...))
		} else {
			entry.Error(values[2:]...)
		}
	} else {
		entry.Error(values...)
	}

}

// New Create new logger
func New() *gormLogger {
	return NewWithName("db")
}

// NewWithName Create new logger with custom name
func NewWithName(name string) *gormLogger {
	return NewWithNameAndLogger(name, logrus.StandardLogger())
}

// NewWithLogger Create new logger with custom logger
func NewWithLogger(logger *logrus.Logger) *gormLogger {
	return NewWithNameAndLogger("db", logger)
}

// NewWithNameAndLogger Create new logger with custom name and logger
func NewWithNameAndLogger(name string, logger *logrus.Logger) *gormLogger {
	return &gormLogger{name: name, logger: logger}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package seelog

import (
	"errors"
	"fmt"
	"os"
	"sync"
)

func reportInternalError(err error) {
	fmt.Fprintln(os.Stderr, "Seelog error: "+err.Error())
}

// LoggerInterface represents structs capable of logging Seelog messages
type LoggerInterface interface {

	// Tracef formats message according to format specifier
	// and writes to log with level = Trace.
	Tracef(format string, params ...interface{})

	// Debugf formats message according to format specifier
	// and writes to log with level = Debug.
	Debugf(format string, params ...interface{})

	// Infof formats message according to format specifier
	// and writes to log with level = Info.
	Infof(format string, params ...interface{})

	// Warnf formats message according to format specifier
	// and writes to log with level = Warn.
	Warnf(format string, params ...interface{}) error

	// Errorf formats message according to format specifier
	// and writes to log with level = Error.
	Errorf(format string, params ...interface{}) error

	// Criticalf formats message according to format specifier
	// and writes to log with level = Critical.
	Criticalf(format string, params ...interface{}) error

	// Trace formats message using the default formats for its operands
	// and writes to log with level = Trace
	Trace(v ...interface{})

	// Debug formats message using the default formats for its operands
	// and writes to log with level = Debug
	Debug(v ...interface{})

	// Info formats message using the default formats for its operands
	// and writes to log with level = Info
	Info(v ...interface{})

	// Warn formats message using the default formats for its operands
	// and writes to log with level = Warn
	Warn(v ...interface{}) error

	// Error formats message using the default formats for its operands
	// and writes to log with level = Error
	Error(v ...interface{}) error

	// Critical formats message using the default formats for its operands
	// and writes to log with level = Critical
	Critical(v ...interface{}) error

	traceWithCallDepth(callDepth int, message fmt.Stringer)
	debugWithCallDepth(callDepth int, message fmt.Stringer)
	infoWithCallDepth(callDepth int, message fmt.Stringer)
	warnWithCallDepth(callDepth int, message fmt.Stringer)
	errorWithCallDepth(callDepth int, message fmt.Stringer)
	criticalWithCallDepth(callDepth int, message fmt.Stringer)

	// Close flushes all the messages in the logger and closes it. It cannot be used after this operation.
	Close()

	// Flush flushes all the messages in the logger.
	Flush()

	// Closed returns true if the logger was previously closed.
	Closed() bool

	// SetAdditionalStackDepth sets the additional number of frames to skip by runtime.Caller
	// when getting function information needed to print seelog format identifiers such as %Func or %File.
	//
	// This func may be used when you wrap seelog funcs and want to print caller info of you own
	// wrappers instead of seelog func callers. In this case you should set depth = 1. If you then
	// wrap your wrapper, you should set depth = 2, etc.
	//
	// NOTE: Incorrect depth value may lead to errors in runtime.Caller evaluation or incorrect
	// function/file names in log files. Do not use it if you are not going to wrap seelog funcs.
	// You may reset the value to default using a SetAdditionalStackDepth(0) call.
	SetAdditionalStackDepth(depth int) error
}

// innerLoggerInterface is an internal logging interface
type innerLoggerInterface interface {
	innerLog(level LogLevel, context LogContextInterface, message fmt.Stringer)
	Flush()
}

// [file path][func name][level] -> [allowed]
type allowedContextCache map[string]map[string]map[LogLevel]bool

// commonLogger contains all common data needed for logging and contains methods used to log messages.
type commonLogger struct {
	config        *logConfig          // Config used for logging
	contextCache  allowedContextCache // Caches whether log is enabled for specific "full path-func name-level" sets
	closed        bool                // 'true' when all writers are closed, all data is flushed, logger is unusable.
	m             sync.Mutex          // Mutex for main operations
	unusedLevels  []bool
	innerLogger   innerLoggerInterface
	addStackDepth int // Additional stack depth needed for correct seelog caller context detection
}

func newCommonLogger(config *logConfig, internalLogger innerLoggerInterface) *commonLogger {
	cLogger := new(commonLogger)

	cLogger.config = config
	cLogger.contextCache = make(allowedContextCache)
	cLogger.unusedLevels = make([]bool, Off)
	cLogger.fillUnusedLevels()
	cLogger.innerLogger = internalLogger

	return cLogger
}

func (cLogger *commonLogger) SetAdditionalStackDepth(depth int) error {
	if depth < 0 {
		return fmt.Errorf("negative depth: %d", depth)
	}
	cLogger.m.Lock()
	cLogger.addStackDepth = depth
	cLogger.m.Unlock()
	return nil
}

func (cLogger *commonLogger) Tracef(format string, params ...interface{}) {
	cLogger.traceWithCallDepth(loggerFuncCallDepth, newLogFormattedMessage(format, params))
}

func (cLogger *commonLogger) Debugf(format string, params ...interface{}) {
	cLogger.debugWithCallDepth(loggerFuncCallDepth, newLogFormattedMessage(format, params))
}

func (cLogger *commonLogger) Infof(format string, params ...interface{}) {
	cLogger.infoWithCallDepth(loggerFuncCallDepth, newLogFormattedMessage(format, params))
}

func (cLogger *commonLogger) Warnf(format string, params ...interface{}) error {
	message := newLogFormattedMessage(format, params)
	cLogger.warnWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Errorf(format string, params ...interface{}) error {
	message := newLogFormattedMessage(format, params)
	cLogger.errorWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Criticalf(format string, params ...interface{}) error {
	message := newLogFormattedMessage(format, params)
	cLogger.criticalWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Trace(v ...interface{}) {
	cLogger.traceWithCallDepth(loggerFuncCallDepth, newLogMessage(v))
}

func (cLogger *commonLogger) Debug(v ...interface{}) {
	cLogger.debugWithCallDepth(loggerFuncCallDepth, newLogMessage(v))
}

func (cLogger *commonLogger) Info(v ...interface{}) {
	cLogger.infoWithCallDepth(loggerFuncCallDepth, newLogMessage(v))
}

func (cLogger *commonLogger) Warn(v ...interface{}) error {
	message := newLogMessage(v)
	cLogger.warnWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Error(v ...interface{}) error {
	message := newLogMessage(v)
	cLogger.errorWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Critical(v ...interface{}) error {
	message := newLogMessage(v)
	cLogger.criticalWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) traceWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(TraceLvl, message, callDepth)
}

func (cLogger *commonLogger) debugWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(DebugLvl, message, callDepth)
}

func (cLogger *commonLogger) infoWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(InfoLvl, message, callDepth)
}

func (cLogger *commonLogger) warnWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(WarnLvl, message, callDepth)
}

func (cLogger *commonLogger) errorWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(ErrorLvl, message, callDepth)
}

func (cLogger *commonLogger) criticalWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(CriticalLvl, message, callDepth)
	cLogger.innerLogger.Flush()
}

func (cLogger *commonLogger) Closed() bool {
	return cLogger.closed
}

func (cLogger *commonLogger) fillUnusedLevels() {
	for i := 0; i < len(cLogger.unusedLevels); i++ {
		cLogger.unusedLevels[i] = true
	}

	cLogger.fillUnusedLevelsByContraint(cLogger.config.Constraints)

	for _, exception := range cLogger.config.Exceptions {
		cLogger.fillUnusedLevelsByContraint(exception)
	}
}

func (cLogger *commonLogger) fillUnusedLevelsByContraint(constraint logLevelConstraints) {
	for i := 0; i < len(cLogger.unusedLevels); i++ {
		if constraint.IsAllowed(LogLevel(i)) {
			cLogger.unusedLevels[i] = false
		}
	}
}

// stackCallDepth is used to indicate the call depth of 'log' func.
// This depth level is used in the runtime.Caller(...) call. See
// common_context.go -> specifyContext, extractCallerInfo for details.
func (cLogger *commonLogger) log(level LogLevel, message fmt.Stringer, stackCallDepth int) {
	cLogger.m.Lock()
	defer cLogger.m.Unlock()

	if cLogger.Closed() {
		return
	}
	if cLogger.unusedLevels[level] {
		return
	}
	context, _ := specifyContext(stackCallDepth + cLogger.addStackDepth)
	// Context errors are not reported because there are situations
	// in which context errors are normal Seelog usage cases. For
	// example in executables with stripped symbols.
	// Error contexts are returned instead. See common_context.go.
	/*if err != nil {
		reportInternalError(err)
		return
	}*/
	cLogger.innerLogger.innerLog(level, context, message)
}

func (cLogger *commonLogger) processLogMsg(level LogLevel, message fmt.Stringer, context LogContextInterface) {
	defer func() {
		if err := recover(); err != nil {
			reportInternalError(fmt.Errorf("recovered from panic during message processing: %s", err))
		}
	}()
	if cLogger.config.IsAllowed(level, context) {
		cLogger.config.RootDispatcher.Dispatch(message.String(), level, context, reportInternalError)
	}
}

func (cLogger *commonLogger) isAllowed(level LogLevel, context LogContextInterface) bool {
	funcMap, ok := cLogger.contextCache[context.FullPath()]
	if !ok {
		funcMap = make(map[string]map[LogLevel]bool, 0)
		cLogger.contextCache[context.FullPath()] = funcMap
	}

	levelMap, ok := funcMap[context.Func()]
	if !ok {
		levelMap = make(map[LogLevel]bool, 0)
		funcMap[context.Func()] = levelMap
	}

	isAllowValue, ok := levelMap[level]
	if !ok {
		isAllowValue = cLogger.config.IsAllowed(level, context)
		levelMap[level] = isAllowValue
	}

	return isAllowValue
}

type logMessage struct {
	params []interface{}
}

type logFormattedMessage struct {
	format string
	params []interface{}
}

func newLogMessage(params []interface{}) fmt.Stringer {
	message := new(logMessage)

	message.params = params

	return message
}

func newLogFormattedMessage(format string, params []interface{}) *logFormattedMessage {
	message := new(logFormattedMessage)

	message.params = params
	message.format = format

	return message
}

func (message *logMessage) String() string {
	return fmt.Sprint(message.params...)
}

func (message *logFormattedMessage) String() string {
	return fmt.Sprintf(message.format, message.params...)
}
<commit_msg>Update logger.go<commit_after>// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package seelog

import (
	"errors"
	"fmt"
	"os"
	"sync"
)

func reportInternalError(err error) {
	fmt.Fprintln(os.Stderr, "Seelog error: "+err.Error())
}

// LoggerInterface represents structs capable of logging Seelog messages
type LoggerInterface interface {

	// Tracef formats message according to format specifier
	// and writes to log with level = Trace.
	Tracef(format string, params ...interface{})

	// Debugf formats message according to format specifier
	// and writes to log with level = Debug.
	Debugf(format string, params ...interface{})

	// Infof formats message according to format specifier
	// and writes to log with level = Info.
	Infof(format string, params ...interface{})

	// Warnf formats message according to format specifier
	// and writes to log with level = Warn.
	Warnf(format string, params ...interface{}) error

	// Errorf formats message according to format specifier
	// and writes to log with level = Error.
	Errorf(format string, params ...interface{}) error

	// Criticalf formats message according to format specifier
	// and writes to log with level = Critical.
	Criticalf(format string, params ...interface{}) error

	// Trace formats message using the default formats for its operands
	// and writes to log with level = Trace
	Trace(v ...interface{})

	// Debug formats message using the default formats for its operands
	// and writes to log with level = Debug
	Debug(v ...interface{})

	// Info formats message using the default formats for its operands
	// and writes to log with level = Info
	Info(v ...interface{})

	// Warn formats message using the default formats for its operands
	// and writes to log with level = Warn
	Warn(v ...interface{}) error

	// Error formats message using the default formats for its operands
	// and writes to log with level = Error
	Error(v ...interface{}) error

	// Critical formats message using the default formats for its operands
	// and writes to log with level = Critical
	Critical(v ...interface{}) error

	traceWithCallDepth(callDepth int, message fmt.Stringer)
	debugWithCallDepth(callDepth int, message fmt.Stringer)
	infoWithCallDepth(callDepth int, message fmt.Stringer)
	warnWithCallDepth(callDepth int, message fmt.Stringer)
	errorWithCallDepth(callDepth int, message fmt.Stringer)
	criticalWithCallDepth(callDepth int, message fmt.Stringer)

	// Close flushes all the messages in the logger and closes it. It cannot be used after this operation.
	Close()

	// Flush flushes all the messages in the logger.
	Flush()

	// Closed returns true if the logger was previously closed.
	Closed() bool

	// SetAdditionalStackDepth sets the additional number of frames to skip by runtime.Caller
	// when getting function information needed to print seelog format identifiers such as %Func or %File.
	//
	// This func may be used when you wrap seelog funcs and want to print caller info of you own
	// wrappers instead of seelog func callers. In this case you should set depth = 1. If you then
	// wrap your wrapper, you should set depth = 2, etc.
	//
	// NOTE: Incorrect depth value may lead to errors in runtime.Caller evaluation or incorrect
	// function/file names in log files. Do not use it if you are not going to wrap seelog funcs.
	// You may reset the value to default using a SetAdditionalStackDepth(0) call.
	SetAdditionalStackDepth(depth int) error
}

// innerLoggerInterface is an internal logging interface
type innerLoggerInterface interface {
	innerLog(level LogLevel, context LogContextInterface, message fmt.Stringer)
	Flush()
}

// [file path][func name][level] -> [allowed]
type allowedContextCache map[string]map[string]map[LogLevel]bool

// commonLogger contains all common data needed for logging and contains methods used to log messages.
type commonLogger struct {
	config        *logConfig          // Config used for logging
	contextCache  allowedContextCache // Caches whether log is enabled for specific "full path-func name-level" sets
	closed        bool                // 'true' when all writers are closed, all data is flushed, logger is unusable.
	m             sync.Mutex          // Mutex for main operations
	unusedLevels  []bool
	innerLogger   innerLoggerInterface
	addStackDepth int // Additional stack depth needed for correct seelog caller context detection
}

func newCommonLogger(config *logConfig, internalLogger innerLoggerInterface) *commonLogger {
	cLogger := new(commonLogger)

	cLogger.config = config
	cLogger.contextCache = make(allowedContextCache)
	cLogger.unusedLevels = make([]bool, Off)
	cLogger.fillUnusedLevels()
	cLogger.innerLogger = internalLogger

	return cLogger
}

func (cLogger *commonLogger) SetAdditionalStackDepth(depth int) error {
	if depth < 0 {
		return fmt.Errorf("negative depth: %d", depth)
	}
	cLogger.m.Lock()
	cLogger.addStackDepth = depth
	cLogger.m.Unlock()
	return nil
}

func (cLogger *commonLogger) Tracef(format string, params ...interface{}) {
	cLogger.traceWithCallDepth(loggerFuncCallDepth, newLogFormattedMessage(format, params))
}

func (cLogger *commonLogger) Debugf(format string, params ...interface{}) {
	cLogger.debugWithCallDepth(loggerFuncCallDepth, newLogFormattedMessage(format, params))
}

func (cLogger *commonLogger) Infof(format string, params ...interface{}) {
	cLogger.infoWithCallDepth(loggerFuncCallDepth, newLogFormattedMessage(format, params))
}

func (cLogger *commonLogger) Warnf(format string, params ...interface{}) error {
	message := newLogFormattedMessage(format, params)
	cLogger.warnWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Errorf(format string, params ...interface{}) error {
	message := newLogFormattedMessage(format, params)
	cLogger.errorWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Criticalf(format string, params ...interface{}) error {
	message := newLogFormattedMessage(format, params)
	cLogger.criticalWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Trace(v ...interface{}) {
	cLogger.traceWithCallDepth(loggerFuncCallDepth, newLogMessage(v))
}

func (cLogger *commonLogger) Debug(v ...interface{}) {
	cLogger.debugWithCallDepth(loggerFuncCallDepth, newLogMessage(v))
}

func (cLogger *commonLogger) Info(v ...interface{}) {
	cLogger.infoWithCallDepth(loggerFuncCallDepth, newLogMessage(v))
}

func (cLogger *commonLogger) Warn(v ...interface{}) error {
	message := newLogMessage(v)
	cLogger.warnWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Error(v ...interface{}) error {
	message := newLogMessage(v)
	cLogger.errorWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) Critical(v ...interface{}) error {
	message := newLogMessage(v)
	cLogger.criticalWithCallDepth(loggerFuncCallDepth, message)
	return errors.New(message.String())
}

func (cLogger *commonLogger) traceWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(TraceLvl, message, callDepth)
}

func (cLogger *commonLogger) debugWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(DebugLvl, message, callDepth)
}

func (cLogger *commonLogger) infoWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(InfoLvl, message, callDepth)
}

func (cLogger *commonLogger) warnWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(WarnLvl, message, callDepth)
}

func (cLogger *commonLogger) errorWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(ErrorLvl, message, callDepth)
}

func (cLogger *commonLogger) criticalWithCallDepth(callDepth int, message fmt.Stringer) {
	cLogger.log(CriticalLvl, message, callDepth)
	cLogger.innerLogger.Flush()
}

func (cLogger *commonLogger) Closed() bool {
	return cLogger.closed
}

func (cLogger *commonLogger) fillUnusedLevels() {
	for i := 0; i < len(cLogger.unusedLevels); i++ {
		cLogger.unusedLevels[i] = true
	}

	cLogger.fillUnusedLevelsByContraint(cLogger.config.Constraints)

	for _, exception := range cLogger.config.Exceptions {
		cLogger.fillUnusedLevelsByContraint(exception)
	}
}

func (cLogger *commonLogger) fillUnusedLevelsByContraint(constraint logLevelConstraints) {
	for i := 0; i < len(cLogger.unusedLevels); i++ {
		if constraint.IsAllowed(LogLevel(i)) {
			cLogger.unusedLevels[i] = false
		}
	}
}

// stackCallDepth is used to indicate the call depth of 'log' func.
// This depth level is used in the runtime.Caller(...) call. See
// common_context.go -> specifyContext, extractCallerInfo for details.
func (cLogger *commonLogger) log(level LogLevel, message fmt.Stringer, stackCallDepth int) {
	if cLogger.unusedLevels[level] {
		return
	}
	cLogger.m.Lock()
	defer cLogger.m.Unlock()

	if cLogger.Closed() {
		return
	}
	context, _ := specifyContext(stackCallDepth + cLogger.addStackDepth)
	// Context errors are not reported because there are situations
	// in which context errors are normal Seelog usage cases. For
	// example in executables with stripped symbols.
	// Error contexts are returned instead. See common_context.go.
	/*if err != nil {
		reportInternalError(err)
		return
	}*/
	cLogger.innerLogger.innerLog(level, context, message)
}

func (cLogger *commonLogger) processLogMsg(level LogLevel, message fmt.Stringer, context LogContextInterface) {
	defer func() {
		if err := recover(); err != nil {
			reportInternalError(fmt.Errorf("recovered from panic during message processing: %s", err))
		}
	}()
	if cLogger.config.IsAllowed(level, context) {
		cLogger.config.RootDispatcher.Dispatch(message.String(), level, context, reportInternalError)
	}
}

func (cLogger *commonLogger) isAllowed(level LogLevel, context LogContextInterface) bool {
	funcMap, ok := cLogger.contextCache[context.FullPath()]
	if !ok {
		funcMap = make(map[string]map[LogLevel]bool, 0)
		cLogger.contextCache[context.FullPath()] = funcMap
	}

	levelMap, ok := funcMap[context.Func()]
	if !ok {
		levelMap = make(map[LogLevel]bool, 0)
		funcMap[context.Func()] = levelMap
	}

	isAllowValue, ok := levelMap[level]
	if !ok {
		isAllowValue = cLogger.config.IsAllowed(level, context)
		levelMap[level] = isAllowValue
	}

	return isAllowValue
}

type logMessage struct {
	params []interface{}
}

type logFormattedMessage struct {
	format string
	params []interface{}
}

func newLogMessage(params []interface{}) fmt.Stringer {
	message := new(logMessage)

	message.params = params

	return message
}

func newLogFormattedMessage(format string, params []interface{}) *logFormattedMessage {
	message := new(logFormattedMessage)

	message.params = params
	message.format = format

	return message
}

func (message *logMessage) String() string {
	return fmt.Sprint(message.params...)
}

func (message *logFormattedMessage) String() string {
	return fmt.Sprintf(message.format, message.params...)
}
<|endoftext|>


<commit_before>package client

import (
	"bytes"
	"fmt"

	ninchat "github.com/ninchat/ninchat-go"
)

func asError(x interface{}) error {
	if x == nil {
		return nil
	}

	if err, ok := x.(error); ok {
		return err
	} else {
		return fmt.Errorf("%v", x)
	}
}

type Strings struct {
	a []string
}

func NewStrings() *Strings {
	return new(Strings)
}

func (ss *Strings) Append(val string) { ss.a = append(ss.a, val) }
func (ss *Strings) Get(i int) string  { return ss.a[i] }
func (ss *Strings) Length() int       { return len(ss.a) }

type Props struct {
	m map[string]interface{}
}

func NewProps() *Props {
	return &Props{make(map[string]interface{})}
}

func (ps *Props) SetBool(key string, val bool)            { ps.m[key] = val }
func (ps *Props) SetInt(key string, val int)              { ps.m[key] = val }
func (ps *Props) SetFloat(key string, val float64)        { ps.m[key] = val }
func (ps *Props) SetString(key string, val string)        { ps.m[key] = val }
func (ps *Props) SetStringArray(key string, ref *Strings) { ps.m[key] = ref.a }
func (ps *Props) SetObject(key string, ref *Props)        { ps.m[key] = ref.m }

func (ps *Props) GetBool(key string) (val bool, err error) {
	if x, found := ps.m[key]; found {
		if b, ok := x.(bool); ok {
			val = b
		} else {
			err = fmt.Errorf("Prop type: %q is not a bool", key)
		}
	}
	return
}

func (ps *Props) GetInt(key string) (val int, err error) {
	if x, found := ps.m[key]; found {
		if f, ok := x.(float64); ok {
			val = int(f)
		} else {
			err = fmt.Errorf("Prop type: %q is not a number", key)
		}
	}
	return
}

func (ps *Props) GetFloat(key string) (val float64, err error) {
	if x, found := ps.m[key]; found {
		if f, ok := x.(float64); ok {
			val = f
		} else {
			err = fmt.Errorf("Prop type: %q is not a number", key)
		}
	}
	return
}

func (ps *Props) GetString(key string) (val string, err error) {
	if x, found := ps.m[key]; found {
		if s, ok := x.(string); ok {
			val = s
		} else {
			err = fmt.Errorf("Prop type: %q is not a string", key)
		}
	}
	return
}

func (ps *Props) GetStringArray(key string) (ref *Strings, err error) {
	if x, found := ps.m[key]; found {
		if xs, ok := x.([]interface{}); ok {
			ref = &Strings{make([]string, len(xs))}
			for i, x := range xs {
				if s, ok := x.(string); ok {
					ref.a[i] = s
				} else {
					err = fmt.Errorf("Prop type: %q is not a string array", key)
					return
				}
			}
		} else {
			err = fmt.Errorf("Prop type: %q is not an array", key)
		}
	}
	return
}

func (ps *Props) GetObject(key string) (ref *Props, err error) {
	if x, found := ps.m[key]; found {
		if m, ok := x.(map[string]interface{}); ok {
			ref = &Props{m}
		} else {
			err = fmt.Errorf("Prop type: %q is not an object", key)
		}
	}
	return
}

type Payload struct {
	a []ninchat.Frame
}

func NewPayload() *Payload {
	return new(Payload)
}

func (p *Payload) Append(blob []byte) { p.a = append(p.a, blob) }
func (p *Payload) Get(i int) []byte   { return p.a[i] }
func (p *Payload) Length() int        { return len(p.a) }

type SessionEventHandler interface {
	OnSessionEvent(params *Props)
}

type EventHandler interface {
	OnEvent(params *Props, payload *Payload, lastReply bool)
}

type CloseHandler interface {
	OnClose()
}

type ConnStateHandler interface {
	OnConnState(state string)
}

type ConnActiveHandler interface {
	OnConnActive()
}

type LogHandler interface {
	OnLog(msg string)
}

type Session struct {
	s ninchat.Session
}

func NewSession() *Session {
	return new(Session)
}

func (s *Session) SetOnSessionEvent(callback SessionEventHandler) {
	s.s.OnSessionEvent = func(e *ninchat.Event) {
		callback.OnSessionEvent(&Props{e.Params})
	}
}

func (s *Session) SetOnEvent(callback EventHandler) {
	s.s.OnEvent = func(e *ninchat.Event) {
		callback.OnEvent(&Props{e.Params}, &Payload{e.Payload}, e.LastReply)
	}
}

func (s *Session) SetOnClose(callback CloseHandler) {
	s.s.OnClose = callback.OnClose
}

func (s *Session) SetOnConnState(callback ConnStateHandler) {
	s.s.OnConnState = callback.OnConnState
}

func (s *Session) SetOnConnActive(callback ConnActiveHandler) {
	s.s.OnConnActive = callback.OnConnActive
}

func (s *Session) SetOnLog(callback LogHandler) {
	s.s.OnLog = func(fragments ...interface{}) {
		var msg bytes.Buffer
		for i, x := range fragments {
			fmt.Fprint(&msg, x)
			if i < len(fragments)-1 {
				msg.WriteString(" ")
			}
		}
		callback.OnLog(msg.String())
	}
}

func (s *Session) SetAddress(address string) {
	s.s.Address = address
}

func (s *Session) SetParams(params *Props) (err error) {
	defer func() {
		err = asError(recover())
	}()

	s.s.SetParams(params.m)
	return
}

func (s *Session) Open() (err error) {
	defer func() {
		err = asError(recover())
	}()

	s.s.Open()
	return
}

func (s *Session) Close() {
	s.s.Close()
}

func (s *Session) Send(params *Props, payload *Payload) (err error) {
	defer func() {
		if x := recover(); x != nil {
			err = asError(x)
		}
	}()

	action := &ninchat.Action{
		Params: params.m,
	}
	if payload != nil {
		action.Payload = payload.a
	}
	err = s.s.Send(action)
	return
}
<commit_msg>mobile: String() implementations<commit_after>package client

import (
	"bytes"
	"fmt"

	ninchat "github.com/ninchat/ninchat-go"
)

func asError(x interface{}) error {
	if x == nil {
		return nil
	}

	if err, ok := x.(error); ok {
		return err
	} else {
		return fmt.Errorf("%v", x)
	}
}

type Strings struct {
	a []string
}

func NewStrings() *Strings { return new(Strings) }

func (ss *Strings) Append(val string) { ss.a = append(ss.a, val) }
func (ss *Strings) Get(i int) string  { return ss.a[i] }
func (ss *Strings) Length() int       { return len(ss.a) }
func (ss *Strings) String() string    { return fmt.Sprint(ss.a) }

type Props struct {
	m map[string]interface{}
}

func NewProps() *Props { return &Props{make(map[string]interface{})} }

func (ps *Props) String() string { return fmt.Sprint(ps.m) }

func (ps *Props) SetBool(key string, val bool)            { ps.m[key] = val }
func (ps *Props) SetInt(key string, val int)              { ps.m[key] = val }
func (ps *Props) SetFloat(key string, val float64)        { ps.m[key] = val }
func (ps *Props) SetString(key string, val string)        { ps.m[key] = val }
func (ps *Props) SetStringArray(key string, ref *Strings) { ps.m[key] = ref.a }
func (ps *Props) SetObject(key string, ref *Props)        { ps.m[key] = ref.m }

func (ps *Props) GetBool(key string) (val bool, err error) {
	if x, found := ps.m[key]; found {
		if b, ok := x.(bool); ok {
			val = b
		} else {
			err = fmt.Errorf("Prop type: %q is not a bool", key)
		}
	}
	return
}

func (ps *Props) GetInt(key string) (val int, err error) {
	if x, found := ps.m[key]; found {
		if f, ok := x.(float64); ok {
			val = int(f)
		} else {
			err = fmt.Errorf("Prop type: %q is not a number", key)
		}
	}
	return
}

func (ps *Props) GetFloat(key string) (val float64, err error) {
	if x, found := ps.m[key]; found {
		if f, ok := x.(float64); ok {
			val = f
		} else {
			err = fmt.Errorf("Prop type: %q is not a number", key)
		}
	}
	return
}

func (ps *Props) GetString(key string) (val string, err error) {
	if x, found := ps.m[key]; found {
		if s, ok := x.(string); ok {
			val = s
		} else {
			err = fmt.Errorf("Prop type: %q is not a string", key)
		}
	}
	return
}

func (ps *Props) GetStringArray(key string) (ref *Strings, err error) {
	if x, found := ps.m[key]; found {
		if xs, ok := x.([]interface{}); ok {
			ref = &Strings{make([]string, len(xs))}
			for i, x := range xs {
				if s, ok := x.(string); ok {
					ref.a[i] = s
				} else {
					err = fmt.Errorf("Prop type: %q is not a string array", key)
					return
				}
			}
		} else {
			err = fmt.Errorf("Prop type: %q is not an array", key)
		}
	}
	return
}

func (ps *Props) GetObject(key string) (ref *Props, err error) {
	if x, found := ps.m[key]; found {
		if m, ok := x.(map[string]interface{}); ok {
			ref = &Props{m}
		} else {
			err = fmt.Errorf("Prop type: %q is not an object", key)
		}
	}
	return
}

type Payload struct {
	a []ninchat.Frame
}

func NewPayload() *Payload { return new(Payload) }

func (p *Payload) Append(blob []byte) { p.a = append(p.a, blob) }
func (p *Payload) Get(i int) []byte   { return p.a[i] }
func (p *Payload) Length() int        { return len(p.a) }
func (p *Payload) String() string     { return fmt.Sprint(p.a) }

type SessionEventHandler interface {
	OnSessionEvent(params *Props)
}

type EventHandler interface {
	OnEvent(params *Props, payload *Payload, lastReply bool)
}

type CloseHandler interface {
	OnClose()
}

type ConnStateHandler interface {
	OnConnState(state string)
}

type ConnActiveHandler interface {
	OnConnActive()
}

type LogHandler interface {
	OnLog(msg string)
}

type Session struct {
	s ninchat.Session
}

func NewSession() *Session {
	return new(Session)
}

func (s *Session) SetOnSessionEvent(callback SessionEventHandler) {
	s.s.OnSessionEvent = func(e *ninchat.Event) {
		callback.OnSessionEvent(&Props{e.Params})
	}
}

func (s *Session) SetOnEvent(callback EventHandler) {
	s.s.OnEvent = func(e *ninchat.Event) {
		callback.OnEvent(&Props{e.Params}, &Payload{e.Payload}, e.LastReply)
	}
}

func (s *Session) SetOnClose(callback CloseHandler) {
	s.s.OnClose = callback.OnClose
}

func (s *Session) SetOnConnState(callback ConnStateHandler) {
	s.s.OnConnState = callback.OnConnState
}

func (s *Session) SetOnConnActive(callback ConnActiveHandler) {
	s.s.OnConnActive = callback.OnConnActive
}

func (s *Session) SetOnLog(callback LogHandler) {
	s.s.OnLog = func(fragments ...interface{}) {
		var msg bytes.Buffer
		for i, x := range fragments {
			fmt.Fprint(&msg, x)
			if i < len(fragments)-1 {
				msg.WriteString(" ")
			}
		}
		callback.OnLog(msg.String())
	}
}

func (s *Session) SetAddress(address string) {
	s.s.Address = address
}

func (s *Session) SetParams(params *Props) (err error) {
	defer func() {
		err = asError(recover())
	}()

	s.s.SetParams(params.m)
	return
}

func (s *Session) Open() (err error) {
	defer func() {
		err = asError(recover())
	}()

	s.s.Open()
	return
}

func (s *Session) Close() {
	s.s.Close()
}

func (s *Session) Send(params *Props, payload *Payload) (err error) {
	defer func() {
		if x := recover(); x != nil {
			err = asError(x)
		}
	}()

	action := &ninchat.Action{
		Params: params.m,
	}
	if payload != nil {
		action.Payload = payload.a
	}
	err = s.s.Send(action)
	return
}
<|endoftext|>


<commit_before>// Automatically generated by MockGen. DO NOT EDIT!
// Source: github.com/johnny-morrice/godless/api (interfaces: RemoteNamespace,RemoteStore,NamespaceTree,NamespaceSearcher)

package mock_godless

import (
	gomock "github.com/golang/mock/gomock"
	api "github.com/johnny-morrice/godless/api"
	crdt "github.com/johnny-morrice/godless/crdt"
	query "github.com/johnny-morrice/godless/query"
)

// Mock of RemoteNamespace interface
type MockRemoteNamespace struct {
	ctrl     *gomock.Controller
	recorder *_MockRemoteNamespaceRecorder
}

// Recorder for MockRemoteNamespace (not exported)
type _MockRemoteNamespaceRecorder struct {
	mock *MockRemoteNamespace
}

func NewMockRemoteNamespace(ctrl *gomock.Controller) *MockRemoteNamespace {
	mock := &MockRemoteNamespace{ctrl: ctrl}
	mock.recorder = &_MockRemoteNamespaceRecorder{mock}
	return mock
}

func (_m *MockRemoteNamespace) EXPECT() *_MockRemoteNamespaceRecorder {
	return _m.recorder
}

func (_m *MockRemoteNamespace) Close() {
	_m.ctrl.Call(_m, "Close")
}

func (_mr *_MockRemoteNamespaceRecorder) Close() *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Close")
}

func (_m *MockRemoteNamespace) Replicate(_param0 crdt.IPFSPath, _param1 api.KvQuery) {
	_m.ctrl.Call(_m, "Replicate", _param0, _param1)
}

func (_mr *_MockRemoteNamespaceRecorder) Replicate(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Replicate", arg0, arg1)
}

func (_m *MockRemoteNamespace) RunKvQuery(_param0 *query.Query, _param1 api.KvQuery) {
	_m.ctrl.Call(_m, "RunKvQuery", _param0, _param1)
}

func (_mr *_MockRemoteNamespaceRecorder) RunKvQuery(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "RunKvQuery", arg0, arg1)
}

func (_m *MockRemoteNamespace) RunKvReflection(_param0 api.APIReflectionType, _param1 api.KvQuery) {
	_m.ctrl.Call(_m, "RunKvReflection", _param0, _param1)
}

func (_mr *_MockRemoteNamespaceRecorder) RunKvReflection(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "RunKvReflection", arg0, arg1)
}

// Mock of RemoteStore interface
type MockRemoteStore struct {
	ctrl     *gomock.Controller
	recorder *_MockRemoteStoreRecorder
}

// Recorder for MockRemoteStore (not exported)
type _MockRemoteStoreRecorder struct {
	mock *MockRemoteStore
}

func NewMockRemoteStore(ctrl *gomock.Controller) *MockRemoteStore {
	mock := &MockRemoteStore{ctrl: ctrl}
	mock.recorder = &_MockRemoteStoreRecorder{mock}
	return mock
}

func (_m *MockRemoteStore) EXPECT() *_MockRemoteStoreRecorder {
	return _m.recorder
}

func (_m *MockRemoteStore) AddIndex(_param0 crdt.Index) (crdt.IPFSPath, error) {
	ret := _m.ctrl.Call(_m, "AddIndex", _param0)
	ret0, _ := ret[0].(crdt.IPFSPath)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) AddIndex(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "AddIndex", arg0)
}

func (_m *MockRemoteStore) AddNamespace(_param0 crdt.Namespace) (crdt.IPFSPath, error) {
	ret := _m.ctrl.Call(_m, "AddNamespace", _param0)
	ret0, _ := ret[0].(crdt.IPFSPath)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) AddNamespace(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "AddNamespace", arg0)
}

func (_m *MockRemoteStore) CatIndex(_param0 crdt.IPFSPath) (crdt.Index, error) {
	ret := _m.ctrl.Call(_m, "CatIndex", _param0)
	ret0, _ := ret[0].(crdt.Index)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) CatIndex(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "CatIndex", arg0)
}

func (_m *MockRemoteStore) CatNamespace(_param0 crdt.IPFSPath) (crdt.Namespace, error) {
	ret := _m.ctrl.Call(_m, "CatNamespace", _param0)
	ret0, _ := ret[0].(crdt.Namespace)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) CatNamespace(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "CatNamespace", arg0)
}

func (_m *MockRemoteStore) Connect() error {
	ret := _m.ctrl.Call(_m, "Connect")
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockRemoteStoreRecorder) Connect() *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Connect")
}

func (_m *MockRemoteStore) Disconnect() error {
	ret := _m.ctrl.Call(_m, "Disconnect")
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockRemoteStoreRecorder) Disconnect() *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Disconnect")
}

func (_m *MockRemoteStore) PublishAddr(_param0 crdt.IPFSPath, _param1 []crdt.IPFSPath) error {
	ret := _m.ctrl.Call(_m, "PublishAddr", _param0, _param1)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockRemoteStoreRecorder) PublishAddr(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "PublishAddr", arg0, arg1)
}

func (_m *MockRemoteStore) SubscribeAddrStream(_param0 crdt.IPFSPath) (<-chan crdt.IPFSPath, <-chan error) {
	ret := _m.ctrl.Call(_m, "SubscribeAddrStream", _param0)
	ret0, _ := ret[0].(<-chan crdt.IPFSPath)
	ret1, _ := ret[1].(<-chan error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) SubscribeAddrStream(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "SubscribeAddrStream", arg0)
}

// Mock of NamespaceTree interface
type MockNamespaceTree struct {
	ctrl     *gomock.Controller
	recorder *_MockNamespaceTreeRecorder
}

// Recorder for MockNamespaceTree (not exported)
type _MockNamespaceTreeRecorder struct {
	mock *MockNamespaceTree
}

func NewMockNamespaceTree(ctrl *gomock.Controller) *MockNamespaceTree {
	mock := &MockNamespaceTree{ctrl: ctrl}
	mock.recorder = &_MockNamespaceTreeRecorder{mock}
	return mock
}

func (_m *MockNamespaceTree) EXPECT() *_MockNamespaceTreeRecorder {
	return _m.recorder
}

func (_m *MockNamespaceTree) JoinTable(_param0 crdt.TableName, _param1 crdt.Table) error {
	ret := _m.ctrl.Call(_m, "JoinTable", _param0, _param1)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockNamespaceTreeRecorder) JoinTable(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "JoinTable", arg0, arg1)
}

func (_m *MockNamespaceTree) LoadTraverse(_param0 api.NamespaceSearcher) error {
	ret := _m.ctrl.Call(_m, "LoadTraverse", _param0)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockNamespaceTreeRecorder) LoadTraverse(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "LoadTraverse", arg0)
}

// Mock of NamespaceSearcher interface
type MockNamespaceSearcher struct {
	ctrl     *gomock.Controller
	recorder *_MockNamespaceSearcherRecorder
}

// Recorder for MockNamespaceSearcher (not exported)
type _MockNamespaceSearcherRecorder struct {
	mock *MockNamespaceSearcher
}

func NewMockNamespaceSearcher(ctrl *gomock.Controller) *MockNamespaceSearcher {
	mock := &MockNamespaceSearcher{ctrl: ctrl}
	mock.recorder = &_MockNamespaceSearcherRecorder{mock}
	return mock
}

func (_m *MockNamespaceSearcher) EXPECT() *_MockNamespaceSearcherRecorder {
	return _m.recorder
}

func (_m *MockNamespaceSearcher) ReadNamespace(_param0 crdt.Namespace) api.TraversalUpdate {
	ret := _m.ctrl.Call(_m, "ReadNamespace", _param0)
	ret0, _ := ret[0].(api.TraversalUpdate)
	return ret0
}

func (_mr *_MockNamespaceSearcherRecorder) ReadNamespace(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadNamespace", arg0)
}

func (_m *MockNamespaceSearcher) Search(_param0 crdt.Index) []crdt.Link {
	ret := _m.ctrl.Call(_m, "Search", _param0)
	ret0, _ := ret[0].([]crdt.Link)
	return ret0
}

func (_mr *_MockNamespaceSearcherRecorder) Search(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Search", arg0)
}
<commit_msg>Update mocks<commit_after>// Automatically generated by MockGen. DO NOT EDIT!
// Source: github.com/johnny-morrice/godless/api (interfaces: RemoteNamespace,RemoteStore,NamespaceTree,NamespaceSearcher)

package mock_godless

import (
	gomock "github.com/golang/mock/gomock"
	api "github.com/johnny-morrice/godless/api"
	crdt "github.com/johnny-morrice/godless/crdt"
	query "github.com/johnny-morrice/godless/query"
)

// Mock of RemoteNamespace interface
type MockRemoteNamespace struct {
	ctrl     *gomock.Controller
	recorder *_MockRemoteNamespaceRecorder
}

// Recorder for MockRemoteNamespace (not exported)
type _MockRemoteNamespaceRecorder struct {
	mock *MockRemoteNamespace
}

func NewMockRemoteNamespace(ctrl *gomock.Controller) *MockRemoteNamespace {
	mock := &MockRemoteNamespace{ctrl: ctrl}
	mock.recorder = &_MockRemoteNamespaceRecorder{mock}
	return mock
}

func (_m *MockRemoteNamespace) EXPECT() *_MockRemoteNamespaceRecorder {
	return _m.recorder
}

func (_m *MockRemoteNamespace) Close() {
	_m.ctrl.Call(_m, "Close")
}

func (_mr *_MockRemoteNamespaceRecorder) Close() *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Close")
}

func (_m *MockRemoteNamespace) Replicate(_param0 []crdt.Link, _param1 api.KvQuery) {
	_m.ctrl.Call(_m, "Replicate", _param0, _param1)
}

func (_mr *_MockRemoteNamespaceRecorder) Replicate(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Replicate", arg0, arg1)
}

func (_m *MockRemoteNamespace) RunKvQuery(_param0 *query.Query, _param1 api.KvQuery) {
	_m.ctrl.Call(_m, "RunKvQuery", _param0, _param1)
}

func (_mr *_MockRemoteNamespaceRecorder) RunKvQuery(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "RunKvQuery", arg0, arg1)
}

func (_m *MockRemoteNamespace) RunKvReflection(_param0 api.APIReflectionType, _param1 api.KvQuery) {
	_m.ctrl.Call(_m, "RunKvReflection", _param0, _param1)
}

func (_mr *_MockRemoteNamespaceRecorder) RunKvReflection(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "RunKvReflection", arg0, arg1)
}

// Mock of RemoteStore interface
type MockRemoteStore struct {
	ctrl     *gomock.Controller
	recorder *_MockRemoteStoreRecorder
}

// Recorder for MockRemoteStore (not exported)
type _MockRemoteStoreRecorder struct {
	mock *MockRemoteStore
}

func NewMockRemoteStore(ctrl *gomock.Controller) *MockRemoteStore {
	mock := &MockRemoteStore{ctrl: ctrl}
	mock.recorder = &_MockRemoteStoreRecorder{mock}
	return mock
}

func (_m *MockRemoteStore) EXPECT() *_MockRemoteStoreRecorder {
	return _m.recorder
}

func (_m *MockRemoteStore) AddIndex(_param0 crdt.Index) (crdt.IPFSPath, error) {
	ret := _m.ctrl.Call(_m, "AddIndex", _param0)
	ret0, _ := ret[0].(crdt.IPFSPath)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) AddIndex(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "AddIndex", arg0)
}

func (_m *MockRemoteStore) AddNamespace(_param0 crdt.Namespace) (crdt.IPFSPath, error) {
	ret := _m.ctrl.Call(_m, "AddNamespace", _param0)
	ret0, _ := ret[0].(crdt.IPFSPath)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) AddNamespace(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "AddNamespace", arg0)
}

func (_m *MockRemoteStore) CatIndex(_param0 crdt.IPFSPath) (crdt.Index, error) {
	ret := _m.ctrl.Call(_m, "CatIndex", _param0)
	ret0, _ := ret[0].(crdt.Index)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) CatIndex(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "CatIndex", arg0)
}

func (_m *MockRemoteStore) CatNamespace(_param0 crdt.IPFSPath) (crdt.Namespace, error) {
	ret := _m.ctrl.Call(_m, "CatNamespace", _param0)
	ret0, _ := ret[0].(crdt.Namespace)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) CatNamespace(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "CatNamespace", arg0)
}

func (_m *MockRemoteStore) Connect() error {
	ret := _m.ctrl.Call(_m, "Connect")
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockRemoteStoreRecorder) Connect() *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Connect")
}

func (_m *MockRemoteStore) Disconnect() error {
	ret := _m.ctrl.Call(_m, "Disconnect")
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockRemoteStoreRecorder) Disconnect() *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Disconnect")
}

func (_m *MockRemoteStore) PublishAddr(_param0 crdt.Link, _param1 []api.PubSubTopic) error {
	ret := _m.ctrl.Call(_m, "PublishAddr", _param0, _param1)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockRemoteStoreRecorder) PublishAddr(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "PublishAddr", arg0, arg1)
}

func (_m *MockRemoteStore) SubscribeAddrStream(_param0 api.PubSubTopic) (<-chan crdt.Link, <-chan error) {
	ret := _m.ctrl.Call(_m, "SubscribeAddrStream", _param0)
	ret0, _ := ret[0].(<-chan crdt.Link)
	ret1, _ := ret[1].(<-chan error)
	return ret0, ret1
}

func (_mr *_MockRemoteStoreRecorder) SubscribeAddrStream(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "SubscribeAddrStream", arg0)
}

// Mock of NamespaceTree interface
type MockNamespaceTree struct {
	ctrl     *gomock.Controller
	recorder *_MockNamespaceTreeRecorder
}

// Recorder for MockNamespaceTree (not exported)
type _MockNamespaceTreeRecorder struct {
	mock *MockNamespaceTree
}

func NewMockNamespaceTree(ctrl *gomock.Controller) *MockNamespaceTree {
	mock := &MockNamespaceTree{ctrl: ctrl}
	mock.recorder = &_MockNamespaceTreeRecorder{mock}
	return mock
}

func (_m *MockNamespaceTree) EXPECT() *_MockNamespaceTreeRecorder {
	return _m.recorder
}

func (_m *MockNamespaceTree) JoinTable(_param0 crdt.TableName, _param1 crdt.Table) error {
	ret := _m.ctrl.Call(_m, "JoinTable", _param0, _param1)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockNamespaceTreeRecorder) JoinTable(arg0, arg1 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "JoinTable", arg0, arg1)
}

func (_m *MockNamespaceTree) LoadTraverse(_param0 api.NamespaceSearcher) error {
	ret := _m.ctrl.Call(_m, "LoadTraverse", _param0)
	ret0, _ := ret[0].(error)
	return ret0
}

func (_mr *_MockNamespaceTreeRecorder) LoadTraverse(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "LoadTraverse", arg0)
}

// Mock of NamespaceSearcher interface
type MockNamespaceSearcher struct {
	ctrl     *gomock.Controller
	recorder *_MockNamespaceSearcherRecorder
}

// Recorder for MockNamespaceSearcher (not exported)
type _MockNamespaceSearcherRecorder struct {
	mock *MockNamespaceSearcher
}

func NewMockNamespaceSearcher(ctrl *gomock.Controller) *MockNamespaceSearcher {
	mock := &MockNamespaceSearcher{ctrl: ctrl}
	mock.recorder = &_MockNamespaceSearcherRecorder{mock}
	return mock
}

func (_m *MockNamespaceSearcher) EXPECT() *_MockNamespaceSearcherRecorder {
	return _m.recorder
}

func (_m *MockNamespaceSearcher) ReadNamespace(_param0 crdt.Namespace) api.TraversalUpdate {
	ret := _m.ctrl.Call(_m, "ReadNamespace", _param0)
	ret0, _ := ret[0].(api.TraversalUpdate)
	return ret0
}

func (_mr *_MockNamespaceSearcherRecorder) ReadNamespace(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadNamespace", arg0)
}

func (_m *MockNamespaceSearcher) Search(_param0 crdt.Index) []crdt.Link {
	ret := _m.ctrl.Call(_m, "Search", _param0)
	ret0, _ := ret[0].([]crdt.Link)
	return ret0
}

func (_mr *_MockNamespaceSearcherRecorder) Search(arg0 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Search", arg0)
}
<|endoftext|>


<commit_before>package logops

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"sync"
	"time"
)

var pool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }}

type Level int

const (
	None = iota
	Debug
	Info
	Warn
	Error
	Fatal
)

var levelNames = [...]string{
	None:  "NONE",
	Debug: "DEBUG",
	Info:  "INFO",
	Warn:  "WARN",
	Error: "ERROR",
	Fatal: "FATAL",
}

type C map[string]string

type Logger struct {
	ContextFunc func() C
	Context     C
	Level       Level
	mu          sync.Mutex
	Writer      io.Writer
}

func NewLogger(context C) *Logger {
	return &Logger{Writer: os.Stdout, Context: context}
}

func (l *Logger) formatJSON(buffer *bytes.Buffer, level Level, localCx C, message string, params ...interface{}) {
	var dynCx C

	fmt.Fprintf(buffer, `{"time":%q, "lvl":%q`, time.Now().Format(time.RFC3339Nano), levelNames[level])
	for k, v := range localCx {
		fmt.Fprintf(buffer, ",%q:%q", k, v)
	}
	if l.ContextFunc != nil {
		dynCx = l.ContextFunc()
		for k, v := range dynCx {
			if _, already := localCx[k]; !already {
				fmt.Fprintf(buffer, ",%q:%q", k, v)
			}
		}
	}
	for k, v := range l.Context {
		if _, already := localCx[k]; !already {
			if _, already := dynCx[k]; !already {
				fmt.Fprintf(buffer, ",%q:%q", k, v)
			}
		}
	}
	if len(params) == 0 {
		fmt.Fprintf(buffer, `,"msg":%q}`, message)
	} else {
		m := fmt.Sprintf(message, params...)
		fmt.Fprintf(buffer, `,"msg":%q}`, m)
	}
	fmt.Fprintln(buffer)
}

func (l *Logger) LogC(lvl Level, context C, message string, params []interface{}) {
	buffer := pool.Get().(*bytes.Buffer)

	l.formatJSON(buffer, lvl, context, message, params...)
	l.mu.Lock()
	_, err := l.Writer.Write(buffer.Bytes())
	l.mu.Unlock()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}

	buffer.Reset()
	pool.Put(buffer)
}
func (l *Logger) InfoC(context C, message string, params ...interface{}) {
	l.LogC(Info, context, message, params)
}
func (l *Logger) Info(message string, params ...interface{}) {
	l.LogC(Info, nil, message, params)
}
<commit_msg>Add level check. Extract format to package-level vars<commit_after>package logops

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"sync"
	"time"
)

var pool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }}

type Level int

const (
	All = iota
	Debug
	Info
	Warn
	Error
	Fatal
	None
)

var levelNames = [...]string{
	All:   "ALL",
	Debug: "DEBUG",
	Info:  "INFO",
	Warn:  "WARN",
	Error: "ERROR",
	Fatal: "FATAL",
	None:  "NONE",
}

var (
	prefixFormat  = `{"time":%q, "lvl":%q`
	fieldFormat   = ",%q:%q"
	postfixFormat = `,"msg":%q}`
)

type C map[string]string

type Logger struct {
	ContextFunc func() C
	Context     C
	Level       Level
	mu          sync.Mutex
	Writer      io.Writer
}

func NewLogger(context C) *Logger {
	return &Logger{Writer: os.Stdout, Context: context}
}

func (l *Logger) formatJSON(buffer *bytes.Buffer, level Level, localCx C, message string, params ...interface{}) {
	var dynCx C

	fmt.Fprintf(buffer, prefixFormat, time.Now().Format(time.RFC3339Nano), levelNames[level])
	for k, v := range localCx {
		fmt.Fprintf(buffer, fieldFormat, k, v)
	}
	if l.ContextFunc != nil {
		dynCx = l.ContextFunc()
		for k, v := range dynCx {
			if _, already := localCx[k]; !already {
				fmt.Fprintf(buffer, fieldFormat, k, v)
			}
		}
	}
	for k, v := range l.Context {
		if _, already := localCx[k]; !already {
			if _, already := dynCx[k]; !already {
				fmt.Fprintf(buffer, fieldFormat, k, v)
			}
		}
	}
	if len(params) == 0 {
		fmt.Fprintf(buffer, postfixFormat, message)
	} else {
		m := fmt.Sprintf(message, params...)
		fmt.Fprintf(buffer, postfixFormat, m)
	}
	fmt.Fprintln(buffer)
}

func (l *Logger) LogC(lvl Level, context C, message string, params []interface{}) {
	if l.Level < lvl {
		buffer := pool.Get().(*bytes.Buffer)

		l.formatJSON(buffer, lvl, context, message, params...)
		l.mu.Lock()
		_, err := l.Writer.Write(buffer.Bytes())
		l.mu.Unlock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
		}

		buffer.Reset()
		pool.Put(buffer)
	}
}

func (l *Logger) InfoC(context C, message string, params ...interface{}) {
	l.LogC(Info, context, message, params)
}

func (l *Logger) Info(message string, params ...interface{}) {
	l.LogC(Info, nil, message, params)
}
<|endoftext|>


<commit_before>// weed master
package weedo

import (
	"errors"
	"io"
	"log"
	"net/http"
	"net/url"
	"strconv"
)

type Master struct {
	Url string
}

func NewMaster(addr string) *Master {
	return &Master{
		Url: addr,
	}
}

// Assign a file key
func (m *Master) Assign() (string, error) {
	return m.AssignArgs(url.Values{})
}

// Assign multi file keys
func (m *Master) AssignN(count int) (fid string, err error) {
	args := url.Values{}
	if count > 0 {
		args.Set("count", strconv.Itoa(count))
	}

	return m.AssignArgs(args)
}

type assignResp struct {
	Count     int
	Fid       string
	Url       string
	PublicUrl string
	Size      int64
	Error     string
}

// v0.4 or later only
func (m *Master) AssignArgs(args url.Values) (fid string, err error) {
	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/dir/assign",
		RawQuery: args.Encode(),
	}

	resp, err := http.Get(u.String())
	if err != nil {
		return
	}
	defer resp.Body.Close()

	assign := new(assignResp)
	if err = decodeJson(resp.Body, assign); err != nil {
		log.Println(err)
		return
	}

	if assign.Error != "" {
		err = errors.New(assign.Error)
		log.Println(err)
		return
	}

	fid = assign.Fid

	return
}

type lookupResp struct {
	Locations []Location
	Error     string
}

type Location struct {
	Url       string
	PublicUrl string
}

// Lookup Volume
func (m *Master) lookup(volumeId, collection string) (*Volume, error) {
	args := url.Values{}
	args.Set("volumeId", volumeId)
	args.Set("collection", collection)

	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/dir/lookup",
		RawQuery: args.Encode(),
	}
	resp, err := http.Get(u.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	lookup := new(lookupResp)
	if err = decodeJson(resp.Body, lookup); err != nil {
		log.Println(err)
		return nil, err
	}

	if lookup.Error != "" {
		return nil, errors.New(lookup.Error)
	}

	return NewVolume(lookup.Locations), nil
}

// Force Garbage Collection
func (m *Master) GC(threshold float64) error {
	args := url.Values{}
	args.Set("garbageThreshold", strconv.FormatFloat(threshold, 'f', -1, 64))
	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/vol/vacuum",
		RawQuery: args.Encode(),
	}
	resp, err := http.Get(u.String())
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	// TODO: handle result
	return nil
}

// Pre-Allocate Volumes
func (m *Master) Grow(count int, collection, replication, dataCenter string) error {
	args := url.Values{}
	if count > 0 {
		args.Set("count", strconv.Itoa(count))
	}
	args.Set("collection", collection)
	args.Set("replication", replication)
	args.Set("dataCenter", dataCenter)

	return m.GrowArgs(args)
}

// v0.4 or later only
func (m *Master) GrowArgs(args url.Values) error {
	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/vol/grow",
		RawQuery: args.Encode(),
	}
	resp, err := http.Get(u.String())
	resp.Body.Close()

	return err
}

func (m *Master) Submit(filename, mimeType string, file io.Reader) (fid string, size int64, err error) {
	return m.SubmitArgs(filename, mimeType, file, url.Values{})
}

// Upload File Directly
func (m *Master) SubmitArgs(filename, mimeType string, file io.Reader, args url.Values) (fid string, size int64, err error) {
	data, contentType, err := makeFormData(filename, mimeType, file)
	if err != nil {
		return
	}

	u := url.URL{
		Scheme: "http",
		Host:   m.Url,
		Path:   "/submit",
		RawQuery: args.Encode(),
	}

	resp, err := upload(u.String(), contentType, data)
	if err == nil {
		fid = resp.Fid
		size = resp.Size
	}

	return
}

type systemStatus struct {
	Topology topology
	Version  string
	Error    string
}

type topology struct {
	DataCenters dataCenter
	Free        int
	Max         int
	Layouts     []layout
}

type dataCenter struct {
	Free  int
	Max   int
	Racks []rack
}

type rack struct {
	DataNodes []dataNode
	Free      int
	Max       int
}

type dataNode struct {
	Free      int
	Max       int
	PublicUrl string
	Url       string
	Volumes   int
}

type layout struct {
	Replication string
	Writables   []uint64
}

// Check System Status
func (m *Master) Status() (err error) {
	u := url.URL{
		Scheme: "http",
		Host:   m.Url,
		Path:   "/dir/status",
	}
	resp, err := http.Get(u.String())
	if err != nil {
		return
	}

	defer resp.Body.Close()

	status := new(systemStatus)
	if err = decodeJson(resp.Body, status); err != nil {
		log.Println(err)
		return
	}

	if status.Error != "" {
		err = errors.New(status.Error)
		log.Println(err)
		return
	}
	return
}
<commit_msg>fix #5<commit_after>// weed master
package weedo

import (
	"errors"
	"io"
	"log"
	"net/http"
	"net/url"
	"strconv"
)

type Master struct {
	Url string
}

func NewMaster(addr string) *Master {
	return &Master{
		Url: addr,
	}
}

// Assign a file key
func (m *Master) Assign() (string, error) {
	return m.AssignArgs(url.Values{})
}

// Assign multi file keys
func (m *Master) AssignN(count int) (fid string, err error) {
	args := url.Values{}
	if count > 0 {
		args.Set("count", strconv.Itoa(count))
	}

	return m.AssignArgs(args)
}

type assignResp struct {
	Count     int
	Fid       string
	Url       string
	PublicUrl string
	Size      int64
	Error     string
}

// v0.4 or later only
func (m *Master) AssignArgs(args url.Values) (fid string, err error) {
	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/dir/assign",
		RawQuery: args.Encode(),
	}

	resp, err := http.Get(u.String())
	if err != nil {
		return
	}
	defer resp.Body.Close()

	assign := new(assignResp)
	if err = decodeJson(resp.Body, assign); err != nil {
		log.Println(err)
		return
	}

	if assign.Error != "" {
		err = errors.New(assign.Error)
		log.Println(err)
		return
	}

	fid = assign.Fid

	return
}

type lookupResp struct {
	Locations []Location
	Error     string
}

type Location struct {
	Url       string
	PublicUrl string
}

// Lookup Volume
func (m *Master) lookup(volumeId, collection string) (*Volume, error) {
	args := url.Values{}
	args.Set("volumeId", volumeId)
	args.Set("collection", collection)

	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/dir/lookup",
		RawQuery: args.Encode(),
	}
	resp, err := http.Get(u.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	lookup := new(lookupResp)
	if err = decodeJson(resp.Body, lookup); err != nil {
		log.Println(err)
		return nil, err
	}

	if lookup.Error != "" {
		return nil, errors.New(lookup.Error)
	}

	return NewVolume(lookup.Locations), nil
}

// Force Garbage Collection
func (m *Master) GC(threshold float64) error {
	args := url.Values{}
	args.Set("garbageThreshold", strconv.FormatFloat(threshold, 'f', -1, 64))
	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/vol/vacuum",
		RawQuery: args.Encode(),
	}
	resp, err := http.Get(u.String())
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	// TODO: handle result
	return nil
}

// Pre-Allocate Volumes
func (m *Master) Grow(count int, collection, replication, dataCenter string) error {
	args := url.Values{}
	if count > 0 {
		args.Set("count", strconv.Itoa(count))
	}
	args.Set("collection", collection)
	args.Set("replication", replication)
	args.Set("dataCenter", dataCenter)

	return m.GrowArgs(args)
}

// v0.4 or later only
func (m *Master) GrowArgs(args url.Values) error {
	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/vol/grow",
		RawQuery: args.Encode(),
	}
	resp, err := http.Get(u.String())
	resp.Body.Close()

	return err
}

func (m *Master) Submit(filename, mimeType string, file io.Reader) (fid string, size int64, err error) {
	return m.SubmitArgs(filename, mimeType, file, url.Values{})
}

// Upload File Directly
func (m *Master) SubmitArgs(filename, mimeType string, file io.Reader, args url.Values) (fid string, size int64, err error) {
	data, contentType, err := makeFormData(filename, mimeType, file)
	if err != nil {
		return
	}

	u := url.URL{
		Scheme:   "http",
		Host:     m.Url,
		Path:     "/submit",
		RawQuery: args.Encode(),
	}

	resp, err := upload(u.String(), contentType, data)
	if err == nil {
		fid = resp.Fid
		size = resp.Size
	}

	return
}

type systemStatus struct {
	Topology topology
	Version  string
	Error    string
}

type topology struct {
	DataCenters []dataCenter
	Free        int
	Max         int
	Layouts     []layout
}

type dataCenter struct {
	Free  int
	Max   int
	Racks []rack
}

type rack struct {
	DataNodes []dataNode
	Free      int
	Max       int
}

type dataNode struct {
	Free      int
	Max       int
	PublicUrl string
	Url       string
	Volumes   int
}

type layout struct {
	Replication string
	Writables   []uint64
}

// Check System Status
func (m *Master) Status() (err error) {
	u := url.URL{
		Scheme: "http",
		Host:   m.Url,
		Path:   "/dir/status",
	}
	resp, err := http.Get(u.String())
	if err != nil {
		return
	}

	defer resp.Body.Close()

	status := new(systemStatus)
	if err = decodeJson(resp.Body, status); err != nil {
		log.Println(err)
		return
	}

	if status.Error != "" {
		err = errors.New(status.Error)
		log.Println(err)
		return
	}
	return
}
<|endoftext|>