<commit_before>// Copyright (c) 2014 Ludovic Fauvet
// Licensed under the MIT license

package main

import (
	"bytes"
	"fmt"
	"github.com/op/go-logging"
	stdlog "log"
	"os"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

var (
	log     = logging.MustGetLogger("main")
	rlogger RuntimeLogger
	dlogger DownloadsLogger
)

type RuntimeLogger struct {
	f *os.File
}

type DownloadsLogger struct {
	sync.RWMutex
	l *stdlog.Logger
	f *os.File
}

// ReloadLogs will reopen the logs to allow rotations
func ReloadLogs() {
	LoadConfig()
	ReloadDownloadLogs()
	ReloadRuntimeLogs()
}

func ReloadRuntimeLogs() {
	logging.SetFormatter(logging.MustStringFormatter("%{time:2006/01/02 15:04:05.000 MST} %{message}"))
	logFlags := 0

	if os.Getenv("DEBUG") != "" {
		logFlags = stdlog.Lshortfile
		logging.SetLevel(logging.DEBUG, "main")
	} else {
		logging.SetLevel(logging.INFO, "main")
	}

	logColor := true //TODO make it optionnal

	if rlogger.f != nil {
		rlogger.f.Close()
	} else {
		rlogger.f = os.Stderr
	}

	if runLog != "" {
		var err error
		rlogger.f, err = os.OpenFile(runLog, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Cannot open log file for writing")
			rlogger.f = os.Stderr
		} else {
			logColor = false
		}
	}

	logBackend := logging.NewLogBackend(rlogger.f, "", logFlags)
	logBackend.Color = logColor

	logging.SetBackend(logBackend)
}

func ReloadDownloadLogs() {
	dlogger.Lock()

	logfile := GetConfig().LogDir + "/downloads.log"
	createHeader := true

	s, err := os.Stat(logfile)
	if err == nil && s.Size() > 0 {
		createHeader = false
	}

	if dlogger.f != nil {
		dlogger.f.Close()
	}
	dlogger.f, err = os.OpenFile(logfile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)

	if err != nil {
		fmt.Fprint(os.Stderr, "Warning: cannot open log file\n")
		createHeader = false
		dlogger.f = os.Stderr
	}

	if createHeader {
		var buf bytes.Buffer
		hostname, _ := os.Hostname()
		fmt.Fprintf(&buf, "# Log file created at: %s\n", time.Now().Format("2006/01/02 15:04:05"))
		fmt.Fprintf(&buf, "# Running on machine: %s\n", hostname)
		fmt.Fprintf(&buf, "# Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
		dlogger.f.Write(buf.Bytes())
	}

	dlogger.l = stdlog.New(dlogger.f, "", stdlog.Ldate|stdlog.Lmicroseconds)
	dlogger.Unlock()
}

// This function will write a download result in the logs.
func logDownload(typ string, statuscode int, p *MirrorlistPage, err error) {
	/*defer func() {
		if r := recover(); r != nil {
			logger.l.Println("Recovered from panic in logDownload", r)
		}
	}()*/

	dlogger.RLock()
	defer dlogger.RUnlock()

	if statuscode == 302 || statuscode == 200 {
		var distance, countries string
		m := p.MirrorList[0]
		distance = strconv.FormatFloat(float64(m.Distance), 'f', 2, 32)
		countries = strings.Join(m.CountryFields, ",")
		fallback := ""
		if p.Fallback == true {
			fallback = " fallback:true"
		}
		sameASNum := ""
		if m.Asnum > 0 && m.Asnum == p.ClientInfo.ASNum {
			sameASNum = "same"
		}

		dlogger.l.Printf("%s %d \"%s\" ip:%s mirror:%s%s %sasn:%d distance:%skm countries:%s",
			typ, statuscode, p.FileInfo.Path, p.IP, m.ID, fallback, sameASNum, m.Asnum, distance, countries)
	} else if statuscode == 404 {
		dlogger.l.Printf("%s 404 \"%s\" %s", typ, p.FileInfo.Path, p.IP)
	} else if statuscode == 500 {
		mirrorID := "unknown"
		if len(p.MirrorList) > 0 {
			mirrorID = p.MirrorList[0].ID
		}
		dlogger.l.Printf("%s 500 \"%s\" ip:%s mirror:%s error:%s", typ, p.FileInfo.Path, p.IP, mirrorID, err.Error())
	} else {
		dlogger.l.Printf("%s %d \"%s\" ip:%s error:%s", typ, statuscode, p.FileInfo.Path, p.IP, err.Error())
	}
}
<commit_msg>logs: remove commented code<commit_after>// Copyright (c) 2014 Ludovic Fauvet
// Licensed under the MIT license

package main

import (
	"bytes"
	"fmt"
	"github.com/op/go-logging"
	stdlog "log"
	"os"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

var (
	log     = logging.MustGetLogger("main")
	rlogger RuntimeLogger
	dlogger DownloadsLogger
)

type RuntimeLogger struct {
	f *os.File
}

type DownloadsLogger struct {
	sync.RWMutex
	l *stdlog.Logger
	f *os.File
}

// ReloadLogs will reopen the logs to allow rotations
func ReloadLogs() {
	LoadConfig()
	ReloadDownloadLogs()
	ReloadRuntimeLogs()
}

func ReloadRuntimeLogs() {
	logging.SetFormatter(logging.MustStringFormatter("%{time:2006/01/02 15:04:05.000 MST} %{message}"))
	logFlags := 0

	if os.Getenv("DEBUG") != "" {
		logFlags = stdlog.Lshortfile
		logging.SetLevel(logging.DEBUG, "main")
	} else {
		logging.SetLevel(logging.INFO, "main")
	}

	logColor := true //TODO make it optionnal

	if rlogger.f != nil {
		rlogger.f.Close()
	} else {
		rlogger.f = os.Stderr
	}

	if runLog != "" {
		var err error
		rlogger.f, err = os.OpenFile(runLog, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Cannot open log file for writing")
			rlogger.f = os.Stderr
		} else {
			logColor = false
		}
	}

	logBackend := logging.NewLogBackend(rlogger.f, "", logFlags)
	logBackend.Color = logColor

	logging.SetBackend(logBackend)
}

func ReloadDownloadLogs() {
	dlogger.Lock()

	logfile := GetConfig().LogDir + "/downloads.log"
	createHeader := true

	s, err := os.Stat(logfile)
	if err == nil && s.Size() > 0 {
		createHeader = false
	}

	if dlogger.f != nil {
		dlogger.f.Close()
	}
	dlogger.f, err = os.OpenFile(logfile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)

	if err != nil {
		fmt.Fprint(os.Stderr, "Warning: cannot open log file\n")
		createHeader = false
		dlogger.f = os.Stderr
	}

	if createHeader {
		var buf bytes.Buffer
		hostname, _ := os.Hostname()
		fmt.Fprintf(&buf, "# Log file created at: %s\n", time.Now().Format("2006/01/02 15:04:05"))
		fmt.Fprintf(&buf, "# Running on machine: %s\n", hostname)
		fmt.Fprintf(&buf, "# Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
		dlogger.f.Write(buf.Bytes())
	}

	dlogger.l = stdlog.New(dlogger.f, "", stdlog.Ldate|stdlog.Lmicroseconds)
	dlogger.Unlock()
}

// This function will write a download result in the logs.
func logDownload(typ string, statuscode int, p *MirrorlistPage, err error) {
	dlogger.RLock()
	defer dlogger.RUnlock()

	if statuscode == 302 || statuscode == 200 {
		var distance, countries string
		m := p.MirrorList[0]
		distance = strconv.FormatFloat(float64(m.Distance), 'f', 2, 32)
		countries = strings.Join(m.CountryFields, ",")
		fallback := ""
		if p.Fallback == true {
			fallback = " fallback:true"
		}
		sameASNum := ""
		if m.Asnum > 0 && m.Asnum == p.ClientInfo.ASNum {
			sameASNum = "same"
		}

		dlogger.l.Printf("%s %d \"%s\" ip:%s mirror:%s%s %sasn:%d distance:%skm countries:%s",
			typ, statuscode, p.FileInfo.Path, p.IP, m.ID, fallback, sameASNum, m.Asnum, distance, countries)
	} else if statuscode == 404 {
		dlogger.l.Printf("%s 404 \"%s\" %s", typ, p.FileInfo.Path, p.IP)
	} else if statuscode == 500 {
		mirrorID := "unknown"
		if len(p.MirrorList) > 0 {
			mirrorID = p.MirrorList[0].ID
		}
		dlogger.l.Printf("%s 500 \"%s\" ip:%s mirror:%s error:%s", typ, p.FileInfo.Path, p.IP, mirrorID, err.Error())
	} else {
		dlogger.l.Printf("%s %d \"%s\" ip:%s error:%s", typ, statuscode, p.FileInfo.Path, p.IP, err.Error())
	}
}
<|endoftext|>


<commit_before>package logx

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
)

var logger *Logger

func init() {
	chaos()
	if out == "file" {
		go poller()
	}
}

func chaos() {
	loadConfig()
	y, m, d := time.Now().Date()
	if logger == nil {
		logger = &Logger{
			look:        uint32(coreDead),
			fileName:    fileName,
			fileBufSize: bufSize,
			path:        filepath.Join(filePath, fileName),
			timestamp:   y*10000 + int(m)*100 + d*1,
			fileMaxSize: maxSize,
			bucket:      make(chan *bytes.Buffer, bucketLen),
			closeSignal: make(chan string),
			lock:        &sync.RWMutex{},
		}
	}
}

func (l *Logger) loadCurLogFile() error {
	l.link = filepath.Join(l.path, fileName+".log")
	actFileName, ok := isLinkFile(l.link)
	if !ok {
		return errors.New("is not link file")
	}
	l.fileName = filepath.Join(l.path, actFileName)
	f, err := openFile(l.fileName)
	if err != nil {
		return err
	}
	info, err := os.Stat(l.fileName)
	if err != nil {
		return err
	}
	sp := strings.Split(actFileName, ".")
	t, err := time.Parse("2006-01-02", sp[1])
	if err != nil {
		fmt.Errorf("loadCurrentLogFile |err=%v", err)
		return err
	}
	y, m, d := t.Date()
	l.timestamp = y*10000 + int(m)*100 + d*1
	l.file = f
	l.fileActualSize = int(info.Size())
	l.fileWriter = bufio.NewWriterSize(f, l.fileBufSize)
	return nil
}

func (l *Logger) createFile() (err error) {
	if !pathIsExist(l.path) {
		if err = os.MkdirAll(l.path, os.ModePerm); err != nil {
			return
		}
	}
	now := time.Now()
	y, m, d := now.Date()
	l.timestamp = y*10000 + int(m)*100 + d*1
	l.fileName = filepath.Join(
		l.path,
		filepath.Base(os.Args[0])+"."+now.Format("2006-01-02.15.04.05.000")+".log")
	f, err := openFile(l.fileName)
	if err != nil {
		return err
	}
	l.file = f
	l.fileActualSize = 0
	l.fileWriter = bufio.NewWriterSize(f, l.fileBufSize)
	l.link = filepath.Join(l.path, fileName+".log")
	return createLinkFile(l.fileName, l.link)
}

func (l *Logger) sync() {
	if l.lookRunning() {
		l.fileWriter.Flush()
	}
}

const fileMaxDelta = 100

func (l *Logger) rotate() bool {
	if !l.lookRunning() {
		return false
	}
	y, m, d := time.Now().Date()
	timestamp := y*10000 + int(m)*100 + d*1
	if l.fileActualSize <= l.fileMaxSize-fileMaxDelta && timestamp <= l.timestamp {
		return false
	}
	l.fileWriter.Flush()
	closeFile(l.file)
	if err := l.createFile(); err != nil {
		return false
	}
	return true
}

func (l *Logger) lookRunning() bool {
	if atomic.LoadUint32(&l.look) == uint32(coreRunning) {
		return true
	}
	return false
}

func (l *Logger) lookDead() bool {
	if atomic.LoadUint32(&l.look) == uint32(coreDead) {
		return true
	}
	return false
}

func (l *Logger) lookBlock() bool {
	if atomic.LoadUint32(&l.look) == uint32(coreBlock) {
		return true
	}
	return false
}

func (l *Logger) signalHandler() {
	var sigChan = make(chan os.Signal)
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGQUIT)
	for {
		select {
		case sig := <-sigChan:
			l.closeSignal <- "close"
			fmt.Println("LOGX receive os signal is ", sig)
			l.fileWriter.Flush()
			closeFile(l.file)
			atomic.SwapUint32(&l.look, uint32(coreDead))
			close(l.bucket)
			os.Exit(1)
		}
	}
}

func (l *Logger) release(buf *bytes.Buffer) { bufferPoolFree(buf) }

func caller() string {
	if pc, f, l, ok := runtime.Caller(2); ok {
		funcName := runtime.FuncForPC(pc).Name()
		return path.Base(f) + "|" + path.Base(funcName) + "|" + strconv.Itoa(l)
	}
	//pc := make([]uintptr, 3, 3)
	//cnt := runtime.Callers(6, pc)
	//
	//for i := 0; i < cnt; i++ {
	//	fu := runtime.FuncForPC(pc[i] - 1)
	//	name := fu.Name()
	//
	//	if !strings.Contains(name, "github.com/kafrax/logx") {
	//		f, l := fu.FileLine(pc[i] - 1)
	//		return path.Base(f) + "|" + path.Base(name) + "|" + strconv.Itoa(l)
	//	}
	//
	//	if pc, f, l, ok := runtime.Caller(8); ok {
	//		funcName := runtime.FuncForPC(pc).Name()
	//		return path.Base(f) + "|" + path.Base(funcName) + "|" + strconv.Itoa(l)
	//	}
	//}
	return ""
}

func print(buf *bytes.Buffer) {
	switch out {
	case "file":
		logger.bucket <- buf
	case "stdout":
		fmt.Print(buf.String())
	case "kafka": //todo send to kafka etc.
	case "nsq": //todo send to kafka nsq etc.
	default:
		fmt.Println(buf.String())
	}
}

func Debugf(format string, msg ... interface{}) {
	if levelFlag > _DEBUG {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[DEBU][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Infof(format string, msg ... interface{}) {
	if levelFlag > _INFO {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[INFO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Warnf(format string, msg ... interface{}) {
	if levelFlag > _WARN {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[WARN][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Errorf(format string, msg ... interface{}) {
	if levelFlag > _ERR {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[ERRO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Fatalf(format string, msg ... interface{}) {
	if levelFlag > _DISASTER {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[FTAL][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Stackf(format string, msg ... interface{}) {
	s := fmt.Sprintf(format, msg...)
	s += "\n"
	buf := make([]byte, 1<<20)
	n := runtime.Stack(buf, true)
	s += string(buf[:n])
	s += "\n"
	fmt.Println("[STAC][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] " + s)
}

func Debug(msg ... interface{}) {
	if levelFlag > _DEBUG {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[DEBU][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Info(msg ... interface{}) {
	if levelFlag > _INFO {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[INFO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Warn(msg ... interface{}) {
	if levelFlag > _WARN {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[WARN][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Error(msg ... interface{}) {
	if levelFlag > _ERR {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[ERRO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Fatal(msg ... interface{}) {
	if levelFlag > _DISASTER {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[FTAL][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Stack(msg ... interface{}) {
	s := fmt.Sprintln(msg...)
	s += "\n"
	buf := make([]byte, 1<<20)
	n := runtime.Stack(buf, true)
	s += string(buf[:n])
	s += "\n"
	fmt.Println("[STAC][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] " + s)
}
<commit_msg>sole memory overflow<commit_after>package logx

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
)

var logger *Logger

func init() {
	chaos()
	if out == "file" {
		go poller()
	}
}

func chaos() {
	loadConfig()
	y, m, d := time.Now().Date()
	if logger == nil {
		logger = &Logger{
			look:        uint32(coreDead),
			fileName:    fileName,
			fileBufSize: bufSize,
			path:        filepath.Join(filePath, fileName),
			timestamp:   y*10000 + int(m)*100 + d*1,
			fileMaxSize: maxSize,
			bucket:      make(chan *bytes.Buffer, bucketLen),
			closeSignal: make(chan string),
			lock:        &sync.RWMutex{},
		}
	}
}

func (l *Logger) loadCurLogFile() error {
	l.link = filepath.Join(l.path, fileName+".log")
	actFileName, ok := isLinkFile(l.link)
	if !ok {
		return errors.New("is not link file")
	}
	l.fileName = filepath.Join(l.path, actFileName)
	f, err := openFile(l.fileName)
	if err != nil {
		return err
	}
	info, err := os.Stat(l.fileName)
	if err != nil {
		return err
	}
	sp := strings.Split(actFileName, ".")
	t, err := time.Parse("2006-01-02", sp[1])
	if err != nil {
		fmt.Errorf("loadCurrentLogFile |err=%v", err)
		return err
	}
	y, m, d := t.Date()
	l.timestamp = y*10000 + int(m)*100 + d*1
	l.file = f
	l.fileActualSize = int(info.Size())
	l.fileWriter = bufio.NewWriterSize(f, l.fileBufSize)
	return nil
}

func (l *Logger) createFile() (err error) {
	if !pathIsExist(l.path) {
		if err = os.MkdirAll(l.path, os.ModePerm); err != nil {
			return
		}
	}
	now := time.Now()
	y, m, d := now.Date()
	l.timestamp = y*10000 + int(m)*100 + d*1
	l.fileName = filepath.Join(
		l.path,
		filepath.Base(os.Args[0])+"."+now.Format("2006-01-02.15.04.05.000")+".log")
	f, err := openFile(l.fileName)
	if err != nil {
		return err
	}
	l.file = f
	l.fileActualSize = 0
	l.fileWriter = bufio.NewWriterSize(f, l.fileBufSize)
	l.link = filepath.Join(l.path, fileName+".log")
	return createLinkFile(l.fileName, l.link)
}

func (l *Logger) sync() {
	if l.lookRunning() {
		l.fileWriter.Flush()
	}
}

const fileMaxDelta = 100

func (l *Logger) rotate() bool {
	if !l.lookRunning() {
		return false
	}
	y, m, d := time.Now().Date()
	timestamp := y*10000 + int(m)*100 + d*1
	if l.fileActualSize <= l.fileMaxSize-fileMaxDelta && timestamp <= l.timestamp {
		return false
	}
	l.fileWriter.Flush()
	closeFile(l.file)
	if err := l.createFile(); err != nil {
		return false
	}
	return true
}

func (l *Logger) lookRunning() bool {
	if atomic.LoadUint32(&l.look) == uint32(coreRunning) {
		return true
	}
	return false
}

func (l *Logger) lookDead() bool {
	if atomic.LoadUint32(&l.look) == uint32(coreDead) {
		return true
	}
	return false
}

func (l *Logger) lookBlock() bool {
	if atomic.LoadUint32(&l.look) == uint32(coreBlock) {
		return true
	}
	return false
}

func (l *Logger) signalHandler() {
	var sigChan = make(chan os.Signal)
	//syscall.SIGHUP
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT)
	for {
		select {
		case sig := <-sigChan:
			l.closeSignal <- "close"
			fmt.Println("LOGX receive os signal is ", sig)
			l.fileWriter.Flush()
			closeFile(l.file)
			atomic.SwapUint32(&l.look, uint32(coreDead))
			close(l.bucket)
			os.Exit(1)
		}
	}
}

func (l *Logger) release(buf *bytes.Buffer) { bufferPoolFree(buf) }

func caller() string {
	if pc, f, l, ok := runtime.Caller(2); ok {
		funcName := runtime.FuncForPC(pc).Name()
		return path.Base(f) + "|" + path.Base(funcName) + "|" + strconv.Itoa(l)
	}
	//pc := make([]uintptr, 3, 3)
	//cnt := runtime.Callers(6, pc)
	//
	//for i := 0; i < cnt; i++ {
	//	fu := runtime.FuncForPC(pc[i] - 1)
	//	name := fu.Name()
	//
	//	if !strings.Contains(name, "github.com/kafrax/logx") {
	//		f, l := fu.FileLine(pc[i] - 1)
	//		return path.Base(f) + "|" + path.Base(name) + "|" + strconv.Itoa(l)
	//	}
	//
	//	if pc, f, l, ok := runtime.Caller(8); ok {
	//		funcName := runtime.FuncForPC(pc).Name()
	//		return path.Base(f) + "|" + path.Base(funcName) + "|" + strconv.Itoa(l)
	//	}
	//}
	return ""
}

func print(buf *bytes.Buffer) {
	switch out {
	case "file":
		logger.bucket <- buf
	case "stdout":
		fmt.Print(buf.String())
	case "kafka": //todo send to kafka etc.
	case "nsq": //todo send to kafka nsq etc.
	default:
		fmt.Println(buf.String())
	}
}

func Debugf(format string, msg ... interface{}) {
	if levelFlag > _DEBUG {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[DEBU][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Infof(format string, msg ... interface{}) {
	if levelFlag > _INFO {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[INFO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Warnf(format string, msg ... interface{}) {
	if levelFlag > _WARN {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[WARN][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Errorf(format string, msg ... interface{}) {
	if levelFlag > _ERR {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[ERRO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Fatalf(format string, msg ... interface{}) {
	if levelFlag > _DISASTER {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[FTAL][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintf(format, msg...) + "\n"))
	print(buf)
}

func Stackf(format string, msg ... interface{}) {
	s := fmt.Sprintf(format, msg...)
	s += "\n"
	buf := make([]byte, 1<<20)
	n := runtime.Stack(buf, true)
	s += string(buf[:n])
	s += "\n"
	fmt.Println("[STAC][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] " + s)
}

func Debug(msg ... interface{}) {
	if levelFlag > _DEBUG {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[DEBU][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Info(msg ... interface{}) {
	if levelFlag > _INFO {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[INFO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Warn(msg ... interface{}) {
	if levelFlag > _WARN {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[WARN][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Error(msg ... interface{}) {
	if levelFlag > _ERR {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[ERRO][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Fatal(msg ... interface{}) {
	if levelFlag > _DISASTER {
		return
	}
	buf := bufferPoolGet()
	buf.Write(s2b("[FTAL][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] "))
	buf.Write(s2b(fmt.Sprintln(msg...)))
	print(buf)
}

func Stack(msg ... interface{}) {
	s := fmt.Sprintln(msg...)
	s += "\n"
	buf := make([]byte, 1<<20)
	n := runtime.Stack(buf, true)
	s += string(buf[:n])
	s += "\n"
	fmt.Println("[STAC][" + time.Now().Format("01-02.15.04.05.000") + "]" + "[" + caller() + "] " + s)
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Package membership:
//-----------------------------------------------------------------------------

package main

//-----------------------------------------------------------------------------
// Imports:
//-----------------------------------------------------------------------------

import (

	// Standard library:
	"errors"
	"log"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	// Community:
	"github.com/calavera/dkvolume"
)

//-----------------------------------------------------------------------------
// Package constant declarations factored into a block:
//-----------------------------------------------------------------------------

const (
	lockID = "dockerLock"
)

//-----------------------------------------------------------------------------
// Package variable declarations factored into a block:
//-----------------------------------------------------------------------------

var (
	nameRegex = regexp.MustCompile(`^(([-_.[:alnum:]]+)/)?([-_.[:alnum:]]+)(@([0-9]+))?$`)
	lockRegex = regexp.MustCompile(`^(client.[0-9]+) ` + lockID)
	commands  = [...]string{"rbd", "mkfs"}
)

//-----------------------------------------------------------------------------
// Structs definitions:
//-----------------------------------------------------------------------------

type rbdDriver struct {
	volRoot   string
	defPool   string
	defFsType string
	defSize   int
	cmd       map[string]string
}

//-----------------------------------------------------------------------------
// initDriver
//-----------------------------------------------------------------------------

func initDriver(volRoot, defPool, defFsType string, defSize int) rbdDriver {

	// Variables
	var err error
	cmd := make(map[string]string)

	// Search for binaries
	for _, i := range commands {
		cmd[i], err = exec.LookPath(i)
		if err != nil {
			log.Fatal("Make sure binary %s is in your PATH", i)
		}
	}

	// Initialize the struct
	driver := rbdDriver{
		volRoot:   volRoot,
		defPool:   defPool,
		defFsType: defFsType,
		defSize:   defSize,
		cmd:       cmd,
	}

	return driver
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Create
//
// Request:
//  { "Name": "volume_name" }
//  Instruct the plugin that the user wants to create a volume, given a user
//  specified volume name. The plugin does not need to actually manifest the
//  volume on the filesystem yet (until Mount is called).
//
// Response:
//  { "Err": null }
//  Respond with a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Create(r dkvolume.Request) dkvolume.Response {

	// Parse the docker --volume option
	pool, name, size, err := d.parsePoolNameSize(r.Name)
	if err != nil {
		log.Printf("ERROR: parsing volume: %s", err)
		return dkvolume.Response{Err: err.Error()}
	}

	mountpoint := filepath.Join(d.volRoot, pool, name)

	// Create RBD image if not exist
	if exists, err := d.imageExists(pool, name); !exists && err == nil {
		if err = d.createImage(pool, name, d.defFsType, size); err != nil {
			return dkvolume.Response{Err: err.Error()}
		}
	} else if err != nil {
		log.Printf("ERROR: checking for RBD Image: %s", err)
		return dkvolume.Response{Err: err.Error()}
	}

	log.Printf("Mountpoint: %s", mountpoint)

	return dkvolume.Response{}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Remove
//
// Request:
//  { "Name": "volume_name" }
//  Delete the specified volume from disk. This request is issued when a user
//  invokes docker rm -v to remove volumes associated with a container.
//
// Response:
//  { "Err": null }
//  Respond with a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Remove(r dkvolume.Request) dkvolume.Response {
	log.Printf("Remove: %s", r.Name)
	return dkvolume.Response{}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Path
//
// Request:
//  { "Name": "volume_name" }
//  Docker needs reminding of the path to the volume on the host.
//
// Response:
//  { "Mountpoint": "/path/to/directory/on/host", "Err": null }
//  Respond with the path on the host filesystem where the volume has been
//  made available, and/or a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Path(r dkvolume.Request) dkvolume.Response {
	log.Printf("Path: %s", r.Name)
	return dkvolume.Response{Mountpoint: "/path/to/directory/on/host"}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Mount
//
// Request:
//  { "Name": "volume_name" }
//  Docker requires the plugin to provide a volume, given a user specified
//  volume name. This is called once per container start.
//
// Response:
//  { "Mountpoint": "/path/to/directory/on/host", "Err": null }
//  Respond with the path on the host filesystem where the volume has been
//  made available, and/or a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Mount(r dkvolume.Request) dkvolume.Response {
	log.Printf("Mount: %s", r.Name)
	return dkvolume.Response{Mountpoint: "/path/to/directory/on/host"}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Unmount
//
// Request:
//  { "Name": "volume_name" }
//  Indication that Docker no longer is using the named volume. This is called
//  once per container stop. Plugin may deduce that it is safe to deprovision
//  it at this point.
//
// Response:
//  { "Err": null }
//  Respond with a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Unmount(r dkvolume.Request) dkvolume.Response {
	log.Printf("Umount: %s", r.Name)
	return dkvolume.Response{}
}

//-----------------------------------------------------------------------------
// parsePoolNameSize
//-----------------------------------------------------------------------------

func (d *rbdDriver) parsePoolNameSize(src string) (string, string, int, error) {

	sub := nameRegex.FindStringSubmatch(src)

	if len(sub) != 6 {
		return "", "", 0, errors.New("Unable to parse docker --volume option: %s" + src)
	}

	// Set defaults
	pool := d.defPool
	name := sub[3]
	size := d.defSize

	// Pool overwrite
	if sub[2] != "" {
		pool = sub[2]
	}

	// Size overwrite
	if sub[5] != "" {
		var err error
		size, err = strconv.Atoi(sub[5])
		if err != nil {
			size = d.defSize
		}
	}

	return pool, name, size, nil
}

//-----------------------------------------------------------------------------
// imageExists
//-----------------------------------------------------------------------------

func (d *rbdDriver) imageExists(pool, name string) (bool, error) {

	// List RBD images
	out, err := exec.Command(d.cmd["rbd"], "ls", pool).Output()
	if err != nil {
		return false, errors.New("Unable to list images")
	}

	// Parse the output
	list := strings.Split(string(out), "\n")
	for _, item := range list {
		if item == name {
			return true, nil
		}
	}

	return false, nil
}

//-----------------------------------------------------------------------------
// createImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) createImage(pool, name, fstype string, size int) error {

	// Create the image device
	err := exec.Command(
		d.cmd["rbd"], "create",
		"--pool", pool,
		"--size", strconv.Itoa(size),
		name,
	).Run()

	if err != nil {
		return errors.New("Unable to create the image device")
	}

	// Add image lock
	locker, err := d.lockImage(pool, name, lockID)
	if err != nil {
		return err
	}

	// Map the image to a kernel device
	device, err := d.mapImage(pool, name)
	if err != nil {
		defer d.unlockImage(pool, name, lockID, locker)
		return err
	}

	log.Printf("Device: %s", device)

	// Remove image lock
	err = d.unlockImage(pool, name, lockID, locker)
	if err != nil {
		return err
	}

	return nil
}

//-----------------------------------------------------------------------------
// lockImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) lockImage(pool, name, lockID string) (string, error) {

	// Lock the image
	err := exec.Command(
		d.cmd["rbd"], "lock add",
		"--pool", pool,
		name, lockID,
	).Run()

	if err != nil {
		return "", errors.New("Unable to lock the image")
	}

	// List the locks
	out, err := exec.Command(
		d.cmd["rbd"], "lock list",
		"--pool", pool, name,
	).Output()

	if err != nil {
		return "", errors.New("Unable to list the image locks")
	}

	// Parse the locker ID
	lines := strings.Split(string(out), "\n")
	if len(lines) > 1 {
		for _, line := range lines[1:] {
			sub := lockRegex.FindStringSubmatch(line)
			if len(sub) == 2 {
				return sub[1], nil
			}
		}
	}

	return "", errors.New("Unable to parse locker ID")
}

//-----------------------------------------------------------------------------
// unlockImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) unlockImage(pool, name, lockID, locker string) error {

	// Unlock the image
	err := exec.Command(
		d.cmd["rbd"], "lock remove",
		name, lockID, locker,
	).Run()

	if err != nil {
		return errors.New("Unable to unlock the image")
	}

	return nil
}

//-----------------------------------------------------------------------------
// mapImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) mapImage(pool, name string) (string, error) {

	// Map the image to a kernel device
	out, err := exec.Command(
		d.cmd["rbd"], "map",
		"--pool", pool, name,
	).Output()

	if err != nil {
		return "", errors.New("Unable to map the image to a kernel device")
	}

	// Parse the device
	return string(out), nil
}

//-----------------------------------------------------------------------------
// unmapImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) unmapImage(device string) error {

	// Unmap the image from a kernel device
	err := exec.Command(
		d.cmd["rbd"], "unmap", device,
	).Run()

	if err != nil {
		return errors.New("Unable to unmap the image from " + device)
	}

	return nil
}
<commit_msg>Added makeFs function<commit_after>//-----------------------------------------------------------------------------
// Package membership:
//-----------------------------------------------------------------------------

package main

//-----------------------------------------------------------------------------
// Imports:
//-----------------------------------------------------------------------------

import (

	// Standard library:
	"errors"
	"log"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	// Community:
	"github.com/calavera/dkvolume"
)

//-----------------------------------------------------------------------------
// Package constant declarations factored into a block:
//-----------------------------------------------------------------------------

const (
	lockID = "dockerLock"
)

//-----------------------------------------------------------------------------
// Package variable declarations factored into a block:
//-----------------------------------------------------------------------------

var (
	nameRegex = regexp.MustCompile(`^(([-_.[:alnum:]]+)/)?([-_.[:alnum:]]+)(@([0-9]+))?$`)
	lockRegex = regexp.MustCompile(`^(client.[0-9]+) ` + lockID)
	commands  = [...]string{"rbd", "mkfs"}
)

//-----------------------------------------------------------------------------
// Structs definitions:
//-----------------------------------------------------------------------------

type rbdDriver struct {
	volRoot   string
	defPool   string
	defFsType string
	defSize   int
	cmd       map[string]string
}

//-----------------------------------------------------------------------------
// initDriver
//-----------------------------------------------------------------------------

func initDriver(volRoot, defPool, defFsType string, defSize int) rbdDriver {

	// Variables
	var err error
	cmd := make(map[string]string)

	// Search for binaries
	for _, i := range commands {
		cmd[i], err = exec.LookPath(i)
		if err != nil {
			log.Fatal("Make sure binary %s is in your PATH", i)
		}
	}

	// Initialize the struct
	driver := rbdDriver{
		volRoot:   volRoot,
		defPool:   defPool,
		defFsType: defFsType,
		defSize:   defSize,
		cmd:       cmd,
	}

	return driver
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Create
//
// Request:
//  { "Name": "volume_name" }
//  Instruct the plugin that the user wants to create a volume, given a user
//  specified volume name. The plugin does not need to actually manifest the
//  volume on the filesystem yet (until Mount is called).
//
// Response:
//  { "Err": null }
//  Respond with a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Create(r dkvolume.Request) dkvolume.Response {

	// Parse the docker --volume option
	pool, name, size, err := d.parsePoolNameSize(r.Name)
	if err != nil {
		log.Printf("ERROR: parsing volume: %s", err)
		return dkvolume.Response{Err: err.Error()}
	}

	mountpoint := filepath.Join(d.volRoot, pool, name)

	// Create RBD image if not exist
	if exists, err := d.imageExists(pool, name); !exists && err == nil {
		if err = d.createImage(pool, name, d.defFsType, size); err != nil {
			return dkvolume.Response{Err: err.Error()}
		}
	} else if err != nil {
		log.Printf("ERROR: checking for RBD Image: %s", err)
		return dkvolume.Response{Err: err.Error()}
	}

	log.Printf("Mountpoint: %s", mountpoint)

	return dkvolume.Response{}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Remove
//
// Request:
//  { "Name": "volume_name" }
//  Delete the specified volume from disk. This request is issued when a user
//  invokes docker rm -v to remove volumes associated with a container.
//
// Response:
//  { "Err": null }
//  Respond with a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Remove(r dkvolume.Request) dkvolume.Response {
	log.Printf("Remove: %s", r.Name)
	return dkvolume.Response{}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Path
//
// Request:
//  { "Name": "volume_name" }
//  Docker needs reminding of the path to the volume on the host.
//
// Response:
//  { "Mountpoint": "/path/to/directory/on/host", "Err": null }
//  Respond with the path on the host filesystem where the volume has been
//  made available, and/or a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Path(r dkvolume.Request) dkvolume.Response {
	log.Printf("Path: %s", r.Name)
	return dkvolume.Response{Mountpoint: "/path/to/directory/on/host"}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Mount
//
// Request:
//  { "Name": "volume_name" }
//  Docker requires the plugin to provide a volume, given a user specified
//  volume name. This is called once per container start.
//
// Response:
//  { "Mountpoint": "/path/to/directory/on/host", "Err": null }
//  Respond with the path on the host filesystem where the volume has been
//  made available, and/or a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Mount(r dkvolume.Request) dkvolume.Response {
	log.Printf("Mount: %s", r.Name)
	return dkvolume.Response{Mountpoint: "/path/to/directory/on/host"}
}

//-----------------------------------------------------------------------------
// POST /VolumeDriver.Unmount
//
// Request:
//  { "Name": "volume_name" }
//  Indication that Docker no longer is using the named volume. This is called
//  once per container stop. Plugin may deduce that it is safe to deprovision
//  it at this point.
//
// Response:
//  { "Err": null }
//  Respond with a string error if an error occurred.
//-----------------------------------------------------------------------------

func (d *rbdDriver) Unmount(r dkvolume.Request) dkvolume.Response {
	log.Printf("Umount: %s", r.Name)
	return dkvolume.Response{}
}

//-----------------------------------------------------------------------------
// parsePoolNameSize
//-----------------------------------------------------------------------------

func (d *rbdDriver) parsePoolNameSize(src string) (string, string, int, error) {

	sub := nameRegex.FindStringSubmatch(src)

	if len(sub) != 6 {
		return "", "", 0, errors.New("Unable to parse docker --volume option: %s" + src)
	}

	// Set defaults
	pool := d.defPool
	name := sub[3]
	size := d.defSize

	// Pool overwrite
	if sub[2] != "" {
		pool = sub[2]
	}

	// Size overwrite
	if sub[5] != "" {
		var err error
		size, err = strconv.Atoi(sub[5])
		if err != nil {
			size = d.defSize
		}
	}

	return pool, name, size, nil
}

//-----------------------------------------------------------------------------
// imageExists
//-----------------------------------------------------------------------------

func (d *rbdDriver) imageExists(pool, name string) (bool, error) {

	// List RBD images
	out, err := exec.Command(d.cmd["rbd"], "ls", pool).Output()
	if err != nil {
		return false, errors.New("Unable to list images")
	}

	// Parse the output
	list := strings.Split(string(out), "\n")
	for _, item := range list {
		if item == name {
			return true, nil
		}
	}

	return false, nil
}

//-----------------------------------------------------------------------------
// createImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) createImage(pool, name, fstype string, size int) error {

	// Create the image device
	err := exec.Command(
		d.cmd["rbd"], "create",
		"--pool", pool,
		"--size", strconv.Itoa(size),
		name,
	).Run()

	if err != nil {
		return errors.New("Unable to create the image device")
	}

	// Add image lock
	locker, err := d.lockImage(pool, name, lockID)
	if err != nil {
		return err
	}

	// Map the image to a kernel device
	device, err := d.mapImage(pool, name)
	if err != nil {
		defer d.unlockImage(pool, name, lockID, locker)
		return err
	}

	// Make the filesystem
	if err = d.makeFs(device, d.defFsType); err != nil {
		defer d.unmapImage(device)
		defer d.unlockImage(pool, name, lockID, locker)
		return err
	}

	// Unmap the image from kernel device
	if err = d.unmapImage(device); err != nil {
		return err
	}

	// Remove image lock
	if err = d.unlockImage(pool, name, lockID, locker); err != nil {
		return err
	}

	return nil
}

//-----------------------------------------------------------------------------
// lockImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) lockImage(pool, name, lockID string) (string, error) {

	// Lock the image
	err := exec.Command(
		d.cmd["rbd"], "lock add",
		"--pool", pool,
		name, lockID,
	).Run()

	if err != nil {
		return "", errors.New("Unable to lock the image")
	}

	// List the locks
	out, err := exec.Command(
		d.cmd["rbd"], "lock list",
		"--pool", pool, name,
	).Output()

	if err != nil {
		return "", errors.New("Unable to list the image locks")
	}

	// Parse the locker ID
	lines := strings.Split(string(out), "\n")
	if len(lines) > 1 {
		for _, line := range lines[1:] {
			sub := lockRegex.FindStringSubmatch(line)
			if len(sub) == 2 {
				return sub[1], nil
			}
		}
	}

	return "", errors.New("Unable to parse locker ID")
}

//-----------------------------------------------------------------------------
// unlockImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) unlockImage(pool, name, lockID, locker string) error {

	// Unlock the image
	err := exec.Command(
		d.cmd["rbd"], "lock remove",
		name, lockID, locker,
	).Run()

	if err != nil {
		return errors.New("Unable to unlock the image")
	}

	return nil
}

//-----------------------------------------------------------------------------
// mapImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) mapImage(pool, name string) (string, error) {

	// Map the image to a kernel device
	out, err := exec.Command(
		d.cmd["rbd"], "map",
		"--pool", pool, name,
	).Output()

	if err != nil {
		return "", errors.New("Unable to map the image to a kernel device")
	}

	// Parse the device
	return strings.TrimSpace(string(out)), nil
}

//-----------------------------------------------------------------------------
// unmapImage
//-----------------------------------------------------------------------------

func (d *rbdDriver) unmapImage(device string) error {

	// Unmap the image from a kernel device
	err := exec.Command(
		d.cmd["rbd"], "unmap", device,
	).Run()

	if err != nil {
		return errors.New("Unable to unmap the image from " + device)
	}

	return nil
}

//-----------------------------------------------------------------------------
// makeFs
//-----------------------------------------------------------------------------

func (d *rbdDriver) makeFs(device, fsType string) error {

	// Search for mkfs
	mkfs, err := exec.LookPath("mkfs." + d.defFsType)
	if err != nil {
		return errors.New("Unable to find mkfs." + d.defFsType)
	}

	// Make the file system
	if err = exec.Command(mkfs, device).Run(); err != nil {
		return errors.New("Unable to make file system on " + device)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"math"
	"os"
	"os/signal"
	"time"

	"github.com/bitly/go-simplejson"
	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/go-lifx/client"
	"github.com/ninjasphere/go-ninja"
	"github.com/ninjasphere/go-ninja/logger"
)

type Light struct {
	Id            string
	Name          string
	Bus           *ninja.DeviceBus
	OnOffBus      *ninja.ChannelBus
	colorBus      *ninja.ChannelBus
	brightnessBus *ninja.ChannelBus
	Batch         bool
	batchBus      *ninja.ChannelBus
	LightState    *LightState
	lightClient   *client.Light
}

// https://github.com/LIFX/lifx-gem/blob/master/lib/lifx/protocol/light.rb
type LightState struct {
	On             *bool
	Brightness     *uint16
	Hue            *uint16
	Saturation     *uint16
	TransitionTime *uint16
	XY             []float64
	ColorTemp      *uint16
}

var drivername = "driver-lifx"
var log = logger.GetLogger(drivername)

func (l *Light) GetJsonLightState() *simplejson.Json {
	st := l.LightState
	js := simplejson.New()
	js.Set("on", st.On)
	js.Set("bri", st.Brightness)
	js.Set("sat", st.Saturation)
	js.Set("hue", st.Hue)
	js.Set("ct", st.ColorTemp)
	js.Set("transitionTime", st.TransitionTime)
	js.Set("xy", st.XY)

	return js
}

func getOnOffBus(light *Light) *ninja.ChannelBus {
	methods := []string{"turnOn", "turnOff", "set"}
	events := []string{"state"}
	onOffBus, _ := light.Bus.AnnounceChannel("on-off", "on-off", methods, events, func(method string, payload *simplejson.Json) {
		log.Infof("got actuation, method is %s", method)
		spew.Dump(payload)
		if light.Batch == true {
			return
		}
		switch method {
		case "turnOn":
			light.turnOnOff(true)
		case "turnOff":
			light.refreshLightState()
			light.turnOnOff(false)
		case "set":
			state, _ := payload.GetIndex(0).Bool()
			light.turnOnOff(state)
		default:
			log.Criticalf("On-off got an unknown method %s", method)
			return
		}
	})

	return onOffBus
}

func getBrightBus(light *Light) *ninja.ChannelBus {
	methods := []string{"set"}
	events := []string{"state"}
	brightnessBus, _ := light.Bus.AnnounceChannel("brightness", "brightness", methods, events, func(method string, payload *simplejson.Json) {

		if light.Batch == true {
			return
		}

		switch method {
		case "set":
			brightness, _ := payload.GetIndex(0).Float64()
			light.setBrightness(brightness)

		default:
			log.Criticalf("Brightness got an unknown method %s", method)
			return
		}

	})

	return brightnessBus

}

func getColorBus(light *Light) *ninja.ChannelBus {
	methods := []string{"set"}
	events := []string{"state"}
	colorBus, _ := light.Bus.AnnounceChannel("color", "color", methods, events, func(method string, payload *simplejson.Json) {
		if light.Batch == true {
			return
		}
		switch method {
		case "set":
			mode, err := payload.Get("mode").String()
			if err != nil {
				log.Criticalf("No mode sent to color bus: %s", err)
			}
			light.setColor(payload, mode)
		default:
			log.Criticalf("Color got an unknown method %s", method)
		}
	})

	return colorBus
}

func NewLight(bus *ninja.DriverBus, client *client.Light) (*Light, error) { //TODO cut this down!
	lightState := createLightState()
	lightID := "1"
	light := &Light{ //TODO fix when lib gets updated
		Id:          lightID,
		Name:        "LiFX Bulb",
		LightState:  &lightState,
		Batch:       false,
		lightClient: client,
	}

	sigs, _ := simplejson.NewJson([]byte(`{
      "ninja:manufacturer": "Lifx",
      "ninja:productName": "Lifx",
      "manufacturer:productModelId": "Lifx",
      "ninja:productType": "Light",
      "ninja:thingType": "light"
  }`))

	deviceBus, _ := bus.AnnounceDevice(lightID, "light", "LiFX Bulb", sigs) //TODO fix when lib gets updated
	light.Bus = deviceBus
	light.OnOffBus = getOnOffBus(light)
	light.brightnessBus = getBrightBus(light)
	light.colorBus = getColorBus(light)
	light.batchBus = getBatchBus(light)

	return light, nil
}

func (l *Light) StartBatch() {
	l.Batch = true
}

func (l *Light) EndBatch() {
	l.Batch = false
	// l.User.SetLightState(l.Id, l.LightState) //TODO send actual state
	l.OnOffBus.SendEvent("state", l.GetJsonLightState())
}

func (l *Light) turnOnOff(state bool) {
	if state == true {
		l.lightClient.TurnOn()
	} else {
		l.lightClient.TurnOff()
	}

}

func (l *Light) setBrightness(fbrightness float64) {
	//TODO
}

func (l *Light) setColor(payload *simplejson.Json, mode string) {
	l.refreshLightState()
	switch mode {
	case "hue": //TODO less verbose plz
		if trans, e := payload.Get("transition").Int(); e == nil {
			l.setTransition(trans)
		}
		fhue, _ := payload.Get("hue").Float64()
		hue := uint16(fhue * math.MaxUint16)
		fsaturation, _ := payload.Get("saturation").Float64()
		saturation := uint16(fsaturation * math.MaxUint16)
		on := bool(true)
		l.LightState.Hue = &hue
		l.LightState.Saturation = &saturation
		l.LightState.On = &on
	case "xy":
		if trans, e := payload.Get("transition").Int(); e == nil {
			l.setTransition(trans)
		}
		x, _ := payload.Get("x").Float64()
		y, _ := payload.Get("y").Float64()
		xy := []float64{x, y}
		l.LightState.XY = xy
		l.LightState.Hue = nil
		l.LightState.Saturation = nil
		l.LightState.ColorTemp = nil
	case "temperature":
		if trans, e := payload.Get("transition").Int(); e == nil {
			l.setTransition(trans)
		}
		temp, _ := payload.Get("temperature").Float64()
		utemp := uint16(math.Floor(1000000 / temp))
		l.LightState.ColorTemp = &utemp
		l.LightState.XY = nil
		l.LightState.Hue = nil
		l.LightState.Saturation = nil
	default:
		log.Criticalf("Bad color mode: %s", mode)
		return
	}

	if !l.Batch {
		// l.User.SetLightState(l.Id, l.LightState) //TODO
		l.colorBus.SendEvent("state", l.GetJsonLightState())
	}

}

func (l *Light) setTransition(transTime int) {
	transTime = transTime / 1000 //LIFX transition time in seconds
	utranstime := uint16(transTime)
	l.LightState.TransitionTime = &utranstime
}

func (l *Light) setBatchColor(payload *simplejson.Json) {
	l.StartBatch()

	color := payload.Get("color")
	if color != nil {
		l.setColor(color, "hue")
	}

	if brightness, err := payload.Get("brightness").Float64(); err == nil {
		l.setBrightness(brightness)
	}

	if onoff, err := payload.Get("on-off").Bool(); err == nil {
		l.turnOnOff(onoff)
	}

	if transition, err := payload.Get("transition").Int(); err == nil {
		l.setTransition(transition)
	}

	l.EndBatch()
}

func createLightState() LightState {

	on := bool(false)
	brightness := uint16(0)
	saturation := uint16(0)
	hueVal := uint16(0)
	transitionTime := uint16(0)

	lightState := LightState{
		On:             &on,
		Brightness:     &brightness,
		Saturation:     &saturation,
		Hue:            &hueVal,
		TransitionTime: &transitionTime,
	}

	return lightState
}

func getCurDir() string {
	pwd, _ := os.Getwd()
	return pwd + "/"
}

func (l *Light) sendLightState() {

	// l.User.SetLightState(l.Id, l.LightState) #TODO
	l.OnOffBus.SendEvent("state", l.GetJsonLightState())
}

func (l *Light) refreshLightState() { //TODO

}

func blinkAllLights() {
	c := client.New()
	c.Discover()

	for i := 0; i < 3; i++ {
		for _, l := range c.Lights {
			l.TurnOff()
		}
		time.Sleep(1 * time.Second)
		for _, l := range c.Lights {
			l.TurnOn()
		}
		time.Sleep(1 * time.Second)
	}
}

func getBatchBus(light *Light) *ninja.ChannelBus {
	methods := []string{"setBatch"}
	events := []string{"state"}
	batchBus, _ := light.Bus.AnnounceChannel("core.batching", "core.batching", methods, events, func(method string, payload *simplejson.Json) {
		switch method {
		case "setBatch":
			light.setBatchColor(payload.GetIndex(0))
		default:
			log.Criticalf("Color got an unknown method %s", method)
			return
		}
	})

	return batchBus
}

func run() int {
	log.Infof("Starting " + drivername)

	conn, err := ninja.Connect("com.ninjablocks.lifx")
	_, err = conn.AnnounceDriver("com.ninjablocks.hue", drivername, getCurDir())
	if err != nil {
		log.HandleError(err, "Could not get driver bus")
	}

	blinkAllLights()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	// Block until a signal is received.
	s := <-c
	fmt.Println("Got signal:", s)

	return 0
}
<commit_msg>working demo<commit_after>package main

import (
	"fmt"

	"math"
	"os"
	"os/signal"
	"time"

	"github.com/bitly/go-simplejson"
	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/go-lifx/client"
	"github.com/ninjasphere/go-ninja"
	"github.com/ninjasphere/go-ninja/logger"
)

type Light struct {
	Id            string
	Name          string
	Bus           *ninja.DeviceBus
	OnOffBus      *ninja.ChannelBus
	colorBus      *ninja.ChannelBus
	brightnessBus *ninja.ChannelBus
	Batch         bool
	batchBus      *ninja.ChannelBus
	LightState    *LightState
	lightClient   *client.Light
}

// https://github.com/LIFX/lifx-gem/blob/master/lib/lifx/protocol/light.rb
type LightState struct {
	On             *bool
	Brightness     *uint16
	Hue            *uint16
	Saturation     *uint16
	TransitionTime *uint16
	XY             []float64
	ColorTemp      *uint16
}

var drivername = "driver-lifx"
var log = logger.GetLogger(drivername)

func (l *Light) GetJsonLightState() *simplejson.Json {
	st := l.LightState
	js := simplejson.New()
	js.Set("on", st.On)
	js.Set("bri", st.Brightness)
	js.Set("sat", st.Saturation)
	js.Set("hue", st.Hue)
	js.Set("ct", st.ColorTemp)
	js.Set("transitionTime", st.TransitionTime)
	js.Set("xy", st.XY)

	return js
}

func getOnOffBus(light *Light) *ninja.ChannelBus {
	methods := []string{"turnOn", "turnOff", "set"}
	events := []string{"state"}
	onOffBus, _ := light.Bus.AnnounceChannel("on-off", "on-off", methods, events, func(method string, payload *simplejson.Json) {
		log.Infof("got actuation, method is %s", method)
		spew.Dump(payload)
		if light.Batch == true {
			return
		}
		switch method {
		case "turnOn":
			light.turnOnOff(true)
		case "turnOff":
			light.refreshLightState()
			light.turnOnOff(false)
		case "set":
			state, _ := payload.GetIndex(0).Bool()
			light.turnOnOff(state)
		default:
			log.Criticalf("On-off got an unknown method %s", method)
			return
		}
	})

	return onOffBus
}

func getBrightBus(light *Light) *ninja.ChannelBus {
	methods := []string{"set"}
	events := []string{"state"}
	brightnessBus, _ := light.Bus.AnnounceChannel("brightness", "brightness", methods, events, func(method string, payload *simplejson.Json) {

		if light.Batch == true {
			return
		}

		switch method {
		case "set":
			brightness, _ := payload.GetIndex(0).Float64()
			light.setBrightness(brightness)

		default:
			log.Criticalf("Brightness got an unknown method %s", method)
			return
		}

	})

	return brightnessBus

}

func getColorBus(light *Light) *ninja.ChannelBus {
	methods := []string{"set"}
	events := []string{"state"}
	colorBus, _ := light.Bus.AnnounceChannel("color", "color", methods, events, func(method string, payload *simplejson.Json) {
		if light.Batch == true {
			return
		}
		switch method {
		case "set":
			mode, err := payload.Get("mode").String()
			if err != nil {
				log.Criticalf("No mode sent to color bus: %s", err)
			}
			light.setColor(payload, mode)
		default:
			log.Criticalf("Color got an unknown method %s", method)
		}
	})

	return colorBus
}

func NewLight(bus *ninja.DriverBus, client *client.Light) (*Light, error) { //TODO cut this down!
	lightState := createLightState()
	lightID := "1"
	light := &Light{ //TODO fix when lib gets updated
		Id:          lightID,
		Name:        "LiFX Bulb",
		LightState:  &lightState,
		Batch:       false,
		lightClient: client,
	}

	sigs, _ := simplejson.NewJson([]byte(`{
      "ninja:manufacturer": "Lifx",
      "ninja:productName": "Lifx",
      "manufacturer:productModelId": "Lifx",
      "ninja:productType": "Light",
      "ninja:thingType": "light"
  }`))

	deviceBus, _ := bus.AnnounceDevice(lightID, "light", "LiFX Bulb", sigs) //TODO fix when lib gets updated
	light.Bus = deviceBus
	light.OnOffBus = getOnOffBus(light)
	light.brightnessBus = getBrightBus(light)
	light.colorBus = getColorBus(light)
	light.batchBus = getBatchBus(light)

	return light, nil
}

func (l *Light) StartBatch() {
	l.Batch = true
}

func (l *Light) EndBatch() {
	l.Batch = false
	// l.User.SetLightState(l.Id, l.LightState) //TODO send actual state
	l.OnOffBus.SendEvent("state", l.GetJsonLightState())
}

func (l *Light) turnOnOff(state bool) {
	if state == true {
		l.lightClient.TurnOn()
	} else {
		l.lightClient.TurnOff()
	}

}

func (l *Light) setBrightness(fbrightness float64) {
	//TODO
}

func (l *Light) setColor(payload *simplejson.Json, mode string) {
	l.refreshLightState()
	switch mode {
	case "hue": //TODO less verbose plz
		if trans, e := payload.Get("transition").Int(); e == nil {
			l.setTransition(trans)
		}
		fhue, _ := payload.Get("hue").Float64()
		hue := uint16(fhue * math.MaxUint16)
		fsaturation, _ := payload.Get("saturation").Float64()
		saturation := uint16(fsaturation * math.MaxUint16)
		on := bool(true)
		l.LightState.Hue = &hue
		l.LightState.Saturation = &saturation
		l.LightState.On = &on
	case "xy":
		if trans, e := payload.Get("transition").Int(); e == nil {
			l.setTransition(trans)
		}
		x, _ := payload.Get("x").Float64()
		y, _ := payload.Get("y").Float64()
		xy := []float64{x, y}
		l.LightState.XY = xy
		l.LightState.Hue = nil
		l.LightState.Saturation = nil
		l.LightState.ColorTemp = nil
	case "temperature":
		if trans, e := payload.Get("transition").Int(); e == nil {
			l.setTransition(trans)
		}
		temp, _ := payload.Get("temperature").Float64()
		utemp := uint16(math.Floor(1000000 / temp))
		l.LightState.ColorTemp = &utemp
		l.LightState.XY = nil
		l.LightState.Hue = nil
		l.LightState.Saturation = nil
	default:
		log.Criticalf("Bad color mode: %s", mode)
		return
	}

	if !l.Batch {
		// l.User.SetLightState(l.Id, l.LightState) //TODO
		l.colorBus.SendEvent("state", l.GetJsonLightState())
	}

}

func (l *Light) setTransition(transTime int) {
	transTime = transTime / 1000 //LIFX transition time in seconds
	utranstime := uint16(transTime)
	l.LightState.TransitionTime = &utranstime
}

func (l *Light) setBatchColor(payload *simplejson.Json) {
	l.StartBatch()

	color := payload.Get("color")
	if color != nil {
		l.setColor(color, "hue")
	}

	if brightness, err := payload.Get("brightness").Float64(); err == nil {
		l.setBrightness(brightness)
	}

	if onoff, err := payload.Get("on-off").Bool(); err == nil {
		l.turnOnOff(onoff)
	}

	if transition, err := payload.Get("transition").Int(); err == nil {
		l.setTransition(transition)
	}

	l.EndBatch()
}

func createLightState() LightState {

	on := bool(false)
	brightness := uint16(0)
	saturation := uint16(0)
	hueVal := uint16(0)
	transitionTime := uint16(0)

	lightState := LightState{
		On:             &on,
		Brightness:     &brightness,
		Saturation:     &saturation,
		Hue:            &hueVal,
		TransitionTime: &transitionTime,
	}

	return lightState
}

func getCurDir() string {
	pwd, _ := os.Getwd()
	return pwd + "/"
}

func (l *Light) sendLightState() {

	// l.User.SetLightState(l.Id, l.LightState) #TODO
	l.OnOffBus.SendEvent("state", l.GetJsonLightState())
}

func (l *Light) refreshLightState() { //TODO

}

func blinkAllLights() {
	c := client.New()
	c.Discover()

	for i := 0; i < 3; i++ {
		for _, l := range c.Lights {
			l.TurnOff()
		}
		time.Sleep(1 * time.Second)
		for _, l := range c.Lights {
			l.TurnOn()
		}
		time.Sleep(1 * time.Second)
	}
}

func getBatchBus(light *Light) *ninja.ChannelBus {
	methods := []string{"setBatch"}
	events := []string{"state"}
	batchBus, _ := light.Bus.AnnounceChannel("core.batching", "core.batching", methods, events, func(method string, payload *simplejson.Json) {
		switch method {
		case "setBatch":
			light.setBatchColor(payload.GetIndex(0))
		default:
			log.Criticalf("Color got an unknown method %s", method)
			return
		}
	})

	return batchBus
}

func run() int {
	log.Infof("Starting " + drivername)

	conn, err := ninja.Connect("com.ninjablocks.lifx")
	bus, err := conn.AnnounceDriver("com.ninjablocks.lifx", drivername, getCurDir())
	if err != nil {
		log.HandleError(err, "Could not get driver bus")
	}

	lightClient := client.New()
	lightClient.Discover()
	for _, l := range lightClient.Lights {
		_, err := NewLight(bus, &l)
		if err != nil {
			log.Criticalf("Error creating light instance %s", err)
		}
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	// Block until a signal is received.
	s := <-c
	fmt.Println("Got signal:", s)

	return 0
}
<|endoftext|>


<commit_before>package models

import "errors"

var (
	ErrMessageAlreadyInTheChannel = errors.New("message is already in the channel")
	ErrIdIsNotSet                 = errors.New("Id is not set")
	ErrAccountIdIsNotSet          = errors.New("account id is not set")
	ErrOldIdIsNotSet              = errors.New("old id is not set")
	ErrNickIsNotSet               = errors.New("nick is not set")
	ErrGuestsAreNotAllowed        = errors.New("guests are not allowed")

	ErrMessageIdIsNotSet       = errors.New("message id is not set")
	ErrMessageIsNotSet         = errors.New("message is not set")
	ErrParentMessageIsNotSet   = errors.New("parent message is not set")
	ErrParentMessageIdIsNotSet = errors.New("parent message id is not set")
	ErrCreatorIdIsNotSet       = errors.New("creator id is not set")

	ErrChannelIsNotSet                = errors.New("channel is not set")
	ErrChannelIdIsNotSet              = errors.New("channel id is not set")
	ErrChannelContainerIsNotSet       = errors.New("channel container is not set")
	ErCouldntFindAccountIdFromContent = errors.New("couldnt find account id from content")
	ErrAccountIsAlreadyInTheChannel   = errors.New("account is already in the channel")

	ErrChannelParticipantIsNotSet             = errors.New("channel participant is not set")
	ErrCannotAddNewParticipantToPinnedChannel = errors.New("you can not add any participants to pinned activity channel")

	ErrChannelMessageIdIsNotSet        = errors.New("channel message id is not set")
	ErrChannelMessageUpdatedNotAllowed = errors.New("join/leave message update is not allowed")

	ErrNameIsNotSet       = errors.New("name is not set")
	ErrGroupNameIsNotSet  = errors.New("group name is not set")
	ErrLastSeenAtIsNotSet = errors.New("lastSeenAt is not set")
	ErrAddedAtIsNotSet    = errors.New("addedAt is not set")

	ErrRecipientsNotDefined = errors.New("recipients are not defined")
	ErrCannotOpenChannel    = errors.New("you can not open the channel")
	ErrSlugIsNotSet         = errors.New("slug is not set")

	ErrChannelOrMessageIdIsNotSet = errors.New("channelId/messageId is not set")

	ErrNotLoggedIn = errors.New("not logged in")
)
<commit_msg>Social: added new errors<commit_after>package models

import "errors"

var (
	ErrMessageAlreadyInTheChannel = errors.New("message is already in the channel")
	ErrIdIsNotSet                 = errors.New("Id is not set")
	ErrAccountIdIsNotSet          = errors.New("account id is not set")
	ErrOldIdIsNotSet              = errors.New("old id is not set")
	ErrNickIsNotSet               = errors.New("nick is not set")
	ErrGuestsAreNotAllowed        = errors.New("guests are not allowed")

	ErrMessageIdIsNotSet       = errors.New("message id is not set")
	ErrMessageIsNotSet         = errors.New("message is not set")
	ErrParentMessageIsNotSet   = errors.New("parent message is not set")
	ErrParentMessageIdIsNotSet = errors.New("parent message id is not set")
	ErrCreatorIdIsNotSet       = errors.New("creator id is not set")

	ErrChannelIsNotSet                = errors.New("channel is not set")
	ErrChannelIdIsNotSet              = errors.New("channel id is not set")
	ErrChannelContainerIsNotSet       = errors.New("channel container is not set")
	ErCouldntFindAccountIdFromContent = errors.New("couldnt find account id from content")
	ErrAccountIsAlreadyInTheChannel   = errors.New("account is already in the channel")

	ErrChannelParticipantIsNotSet             = errors.New("channel participant is not set")
	ErrCannotAddNewParticipantToPinnedChannel = errors.New("you can not add any participants to pinned activity channel")

	ErrChannelMessageIdIsNotSet        = errors.New("channel message id is not set")
	ErrChannelMessageUpdatedNotAllowed = errors.New("join/leave message update is not allowed")

	ErrNameIsNotSet       = errors.New("name is not set")
	ErrGroupNameIsNotSet  = errors.New("group name is not set")
	ErrLastSeenAtIsNotSet = errors.New("lastSeenAt is not set")
	ErrAddedAtIsNotSet    = errors.New("addedAt is not set")

	ErrRecipientsNotDefined = errors.New("recipients are not defined")
	ErrCannotOpenChannel    = errors.New("you can not open the channel")
	ErrSlugIsNotSet         = errors.New("slug is not set")

	ErrChannelOrMessageIdIsNotSet = errors.New("channelId/messageId is not set")

	ErrNotLoggedIn = errors.New("not logged in")

	ErrAccessDenied = errors.New("access denied")

	ErrRoleNotSet = errors.New("role not set")
)
<|endoftext|>


<commit_before>// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vitessdriver

import (
	"database/sql"
	"database/sql/driver"
	"fmt"
	"io"
	"net"
	"os"
	"reflect"
	"strings"
	"testing"
	"time"

	"google.golang.org/grpc"

	"github.com/youtube/vitess/go/vt/vtgate/grpcvtgateservice"

	topodatapb "github.com/youtube/vitess/go/vt/proto/topodata"
)

var (
	testAddress string
)

func TestMain(m *testing.M) {
	// fake service
	service := CreateFakeServer()

	// listen on a random port
	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		panic(fmt.Sprintf("Cannot listen: %v", err))
	}

	// Create a gRPC server and listen on the port
	server := grpc.NewServer()
	grpcvtgateservice.RegisterForTest(server, service)
	go server.Serve(listener)

	testAddress = listener.Addr().String()
	os.Exit(m.Run())
}

func TestDriver(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`, testAddress, int64(30*time.Second))
	db, err := sql.Open("vitess", connStr)
	if err != nil {
		t.Fatal(err)
	}
	r, err := db.Query("request1", int64(0))
	if err != nil {
		t.Fatal(err)
	}
	count := 0
	for r.Next() {
		count++
	}
	if count != 2 {
		t.Errorf("count: %d, want 2", count)
	}
	_ = db.Close()
}

func TestDial(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "replica", "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	wantc := &conn{
		Protocol:   "grpc",
		TabletType: "replica",
		Streaming:  false,
		Timeout:    30 * time.Second,
		tabletType: topodatapb.TabletType_REPLICA,
	}
	newc := *(c.(*conn))
	newc.Address = ""
	newc.vtgateConn = nil
	if !reflect.DeepEqual(&newc, wantc) {
		t.Errorf("conn: %+v, want %+v", &newc, wantc)
	}
	_ = c.Close()

	_, err = drv{}.Open(`{"protocol": "none"}`)
	want := "no dialer registered for VTGate protocol none"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}

	_, err = drv{}.Open(`{`)
	want = "unexpected end of JSON input"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestExec(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatal(err)
		}
		s, _ := c.Prepare(tc.requestName)
		if ni := s.NumInput(); ni != -1 {
			t.Errorf("got %d, want -1", ni)
		}
		r, err := s.Exec([]driver.Value{int64(0)})
		if err != nil {
			t.Error(err)
		}
		if v, _ := r.LastInsertId(); v != 72 {
			t.Errorf("insert id: %d, want 72", v)
		}
		if v, _ := r.RowsAffected(); v != 123 {
			t.Errorf("rows affected: %d, want 123", v)
		}
		_ = s.Close()

		s, _ = c.Prepare("none")
		_, err = s.Exec(nil)
		want := "no match for: none"
		if err == nil || !strings.Contains(err.Error(), want) {
			t.Errorf("err: %v, does not contain %s", err, want)
		}
		_ = c.Close()
	}
}

func TestExecStreamingNotAllowed(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "streaming": true, "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	s, _ := c.Prepare("request1")
	_, err = s.Exec([]driver.Value{int64(0)})
	want := "Exec not allowed for streaming connections"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, does not contain %s", err, want)
	}
}

func TestQuery(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatal(err)
		}
		s, _ := c.Prepare(tc.requestName)
		r, err := s.Query([]driver.Value{int64(0)})
		if err != nil {
			t.Fatal(err)
		}
		cols := r.Columns()
		wantCols := []string{
			"field1",
			"field2",
		}
		if !reflect.DeepEqual(cols, wantCols) {
			t.Fatalf("cols: %v, want %v", cols, wantCols)
		}
		row := make([]driver.Value, 2)
		count := 0
		for {
			err = r.Next(row)
			if err != nil {
				if err == io.EOF {
					break
				}
				t.Error(err)
			}
			count++
		}
		if count != 2 {
			t.Errorf("count: %d, want 2", count)
		}
		_ = s.Close()

		s, _ = c.Prepare("none")
		_, err = s.Query(nil)
		want := "no match for: none"
		if err == nil || !strings.Contains(err.Error(), want) {
			t.Errorf("err: %v, does not contain %s", err, want)
		}
		_ = c.Close()
	}
}

func TestQueryStreaming(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatal(err)
		}
		s, _ := c.Prepare(tc.requestName)
		r, err := s.Query([]driver.Value{int64(0)})
		if err != nil {
			t.Fatal(err)
		}
		cols := r.Columns()
		wantCols := []string{
			"field1",
			"field2",
		}
		if !reflect.DeepEqual(cols, wantCols) {
			t.Fatalf("cols: %v, want %v", cols, wantCols)
		}
		row := make([]driver.Value, 2)
		count := 0
		for {
			err = r.Next(row)
			if err != nil {
				if err == io.EOF {
					break
				}
				t.Fatal(err)
			}
			count++
		}
		if count != 2 {
			t.Errorf("count: %d, want 2", count)
		}
		_ = s.Close()
		_ = c.Close()
	}
}

func TestTx(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "master", "timeout": %d}`,
			requestName:    "txRequest",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "master", "timeout": %d}`,
			requestName:    "txRequestSpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatalf("%v: %v", tc.requestName, err)
		}
		tx, err := c.Begin()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		s, _ := c.Prepare(tc.requestName)
		_, err = s.Exec([]driver.Value{int64(0)})
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Commit()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Commit()
		want := "commit: not in transaction"
		if err == nil || !strings.Contains(err.Error(), want) {
			t.Errorf("case: %v err: %v, does not contain %s", tc.requestName, err, want)
		}
		_ = c.Close()

		c, err = drv{}.Open(connStr)
		if err != nil {
			t.Fatalf("%v: %v", tc.requestName, err)
		}
		tx, err = c.Begin()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		s, _ = c.Prepare(tc.requestName)
		_, err = s.Query([]driver.Value{int64(0)})
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Rollback()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Rollback()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		_ = c.Close()
	}
}

func TestTxExecStreamingNotAllowed(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "streaming": true, "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	_, err = c.Begin()
	want := "transaction not allowed for streaming connection"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, does not contain %s", err, want)
	}
	_ = c.Close()
}
<commit_msg>vitessdriver: Refactored tests for Open().<commit_after>// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vitessdriver

import (
	"database/sql"
	"database/sql/driver"
	"fmt"
	"io"
	"net"
	"os"
	"reflect"
	"strings"
	"testing"
	"time"

	"google.golang.org/grpc"

	"github.com/youtube/vitess/go/vt/vtgate/grpcvtgateservice"

	topodatapb "github.com/youtube/vitess/go/vt/proto/topodata"
)

var (
	testAddress string
)

// TestMain tests the Vitess Go SQL driver.
//
// Note that the queries used in the test are not valid SQL queries and don't
// have to be. The main point here is to test the interactions against a
// vtgate implementation (here: fakeVTGateService from fakeserver_test.go).
func TestMain(m *testing.M) {
	service := CreateFakeServer()

	// listen on a random port.
	listener, err := net.Listen("tcp", ":0")
	if err != nil {
		panic(fmt.Sprintf("Cannot listen: %v", err))
	}

	// Create a gRPC server and listen on the port.
	server := grpc.NewServer()
	grpcvtgateservice.RegisterForTest(server, service)
	go server.Serve(listener)

	testAddress = listener.Addr().String()
	os.Exit(m.Run())
}

func TestDriver(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`, testAddress, int64(30*time.Second))
	db, err := sql.Open("vitess", connStr)
	if err != nil {
		t.Fatal(err)
	}
	r, err := db.Query("request1", int64(0))
	if err != nil {
		t.Fatal(err)
	}
	count := 0
	for r.Next() {
		count++
	}
	if count != 2 {
		t.Errorf("count: %d, want 2", count)
	}
	_ = db.Close()
}

func TestOpen(t *testing.T) {
	connStr := fmt.Sprintf(`{"address": "%s", "tablet_type": "replica", "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	wantc := &conn{
		Configuration: Configuration{
			Protocol:   "grpc",
			TabletType: "replica",
			Streaming:  false,
			Timeout:    30 * time.Second,
		},
		tabletTypeProto: topodatapb.TabletType_REPLICA,
	}
	newc := *(c.(*conn))
	newc.Address = ""
	newc.vtgateConn = nil
	if !reflect.DeepEqual(&newc, wantc) {
		t.Errorf("conn: %+v, want %+v", &newc, wantc)
	}
}

func TestOpenShard(t *testing.T) {
	connStr := fmt.Sprintf(`{"address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "replica", "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	wantc := &conn{
		Configuration: Configuration{
			Protocol:   "grpc",
			Keyspace:   "ks1",
			Shard:      "0",
			TabletType: "replica",
			Streaming:  false,
			Timeout:    30 * time.Second,
		},
		tabletTypeProto: topodatapb.TabletType_REPLICA,
	}
	newc := *(c.(*conn))
	newc.Address = ""
	newc.vtgateConn = nil
	if !reflect.DeepEqual(&newc, wantc) {
		t.Errorf("conn: %+v, want %+v", &newc, wantc)
	}
}

func TestOpen_UnregisteredProtocol(t *testing.T) {
	_, err := drv{}.Open(`{"protocol": "none"}`)
	want := "no dialer registered for VTGate protocol none"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestOpen_InvalidJson(t *testing.T) {
	_, err := drv{}.Open(`{`)
	want := "unexpected end of JSON input"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestOpen_KeyspaceAndShardBelongTogether(t *testing.T) {
	_, err := drv{}.Open(`{"keyspace": "ks1"}`)
	want := "Always set both keyspace and shard or leave both empty."
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}

	_, err = drv{}.Open(`{"shard": "0"}`)
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestOpen_ValidTabletTypeRequired(t *testing.T) {
	_, err := drv{}.Open(`{"tablet_type": "foobar"}`)
	want := "unknown TabletType foobar"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, want %s", err, want)
	}
}

func TestExec(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatal(err)
		}
		s, _ := c.Prepare(tc.requestName)
		if ni := s.NumInput(); ni != -1 {
			t.Errorf("got %d, want -1", ni)
		}
		r, err := s.Exec([]driver.Value{int64(0)})
		if err != nil {
			t.Error(err)
		}
		if v, _ := r.LastInsertId(); v != 72 {
			t.Errorf("insert id: %d, want 72", v)
		}
		if v, _ := r.RowsAffected(); v != 123 {
			t.Errorf("rows affected: %d, want 123", v)
		}
		_ = s.Close()

		s, _ = c.Prepare("none")
		_, err = s.Exec(nil)
		want := "no match for: none"
		if err == nil || !strings.Contains(err.Error(), want) {
			t.Errorf("err: %v, does not contain %s", err, want)
		}
		_ = c.Close()
	}
}

func TestExecStreamingNotAllowed(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "streaming": true, "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	s, _ := c.Prepare("request1")
	_, err = s.Exec([]driver.Value{int64(0)})
	want := "Exec not allowed for streaming connections"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, does not contain %s", err, want)
	}
}

func TestQuery(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatal(err)
		}
		s, _ := c.Prepare(tc.requestName)
		r, err := s.Query([]driver.Value{int64(0)})
		if err != nil {
			t.Fatal(err)
		}
		cols := r.Columns()
		wantCols := []string{
			"field1",
			"field2",
		}
		if !reflect.DeepEqual(cols, wantCols) {
			t.Fatalf("cols: %v, want %v", cols, wantCols)
		}
		row := make([]driver.Value, 2)
		count := 0
		for {
			err = r.Next(row)
			if err != nil {
				if err == io.EOF {
					break
				}
				t.Error(err)
			}
			count++
		}
		if count != 2 {
			t.Errorf("count: %d, want 2", count)
		}
		_ = s.Close()

		s, _ = c.Prepare("none")
		_, err = s.Query(nil)
		want := "no match for: none"
		if err == nil || !strings.Contains(err.Error(), want) {
			t.Errorf("err: %v, does not contain %s", err, want)
		}
		_ = c.Close()
	}
}

func TestQueryStreaming(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "rdonly", "timeout": %d}`,
			requestName:    "request1SpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatal(err)
		}
		s, _ := c.Prepare(tc.requestName)
		r, err := s.Query([]driver.Value{int64(0)})
		if err != nil {
			t.Fatal(err)
		}
		cols := r.Columns()
		wantCols := []string{
			"field1",
			"field2",
		}
		if !reflect.DeepEqual(cols, wantCols) {
			t.Fatalf("cols: %v, want %v", cols, wantCols)
		}
		row := make([]driver.Value, 2)
		count := 0
		for {
			err = r.Next(row)
			if err != nil {
				if err == io.EOF {
					break
				}
				t.Fatal(err)
			}
			count++
		}
		if count != 2 {
			t.Errorf("count: %d, want 2", count)
		}
		_ = s.Close()
		_ = c.Close()
	}
}

func TestTx(t *testing.T) {
	var testcases = []struct {
		dataSourceName string
		requestName    string
	}{
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "tablet_type": "master", "timeout": %d}`,
			requestName:    "txRequest",
		},
		{
			dataSourceName: `{"protocol": "grpc", "address": "%s", "keyspace": "ks1", "shard": "0", "tablet_type": "master", "timeout": %d}`,
			requestName:    "txRequestSpecificShard",
		},
	}

	for _, tc := range testcases {
		connStr := fmt.Sprintf(tc.dataSourceName, testAddress, int64(30*time.Second))
		c, err := drv{}.Open(connStr)
		if err != nil {
			t.Fatalf("%v: %v", tc.requestName, err)
		}
		tx, err := c.Begin()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		s, _ := c.Prepare(tc.requestName)
		_, err = s.Exec([]driver.Value{int64(0)})
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Commit()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Commit()
		want := "commit: not in transaction"
		if err == nil || !strings.Contains(err.Error(), want) {
			t.Errorf("case: %v err: %v, does not contain %s", tc.requestName, err, want)
		}
		_ = c.Close()

		c, err = drv{}.Open(connStr)
		if err != nil {
			t.Fatalf("%v: %v", tc.requestName, err)
		}
		tx, err = c.Begin()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		s, _ = c.Prepare(tc.requestName)
		_, err = s.Query([]driver.Value{int64(0)})
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Rollback()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		err = tx.Rollback()
		if err != nil {
			t.Errorf("%v: %v", tc.requestName, err)
		}
		_ = c.Close()
	}
}

func TestTxExecStreamingNotAllowed(t *testing.T) {
	connStr := fmt.Sprintf(`{"protocol": "grpc", "address": "%s", "tablet_type": "rdonly", "streaming": true, "timeout": %d}`, testAddress, int64(30*time.Second))
	c, err := drv{}.Open(connStr)
	if err != nil {
		t.Fatal(err)
	}
	_, err = c.Begin()
	want := "transaction not allowed for streaming connection"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("err: %v, does not contain %s", err, want)
	}
	_ = c.Close()
}
<|endoftext|>


<commit_before>package polynomial

import (
	"github.com/ready-steady/quadrature"
)

var ruleCache map[uint]*rule = make(map[uint]*rule)

type rule struct {
	x []float64
	w []float64
}

func getRule(order uint) *rule {
	if rule, ok := ruleCache[order]; ok {
		return rule
	}
	x, w := quadrature.Legendre(order, -1.0, 1.0)
	rule := &rule{x, w}
	ruleCache[order] = rule
	return rule
}

func integrate(a, b float64, order uint, target func(float64) float64) float64 {
	value, rule := 0.0, getRule(order)
	for i := uint(0); i < order; i++ {
		x := ((a + b) + (b-a)*rule.x[i]) / 2.0
		w := (b - a) * rule.w[i] / 2.0
		value += w * target(x)
	}
	return value
}
<commit_msg>b/polynomial: simplify the scaling of quadrature rules<commit_after>package polynomial

import (
	"github.com/ready-steady/quadrature"
)

var ruleCache map[uint]*rule = make(map[uint]*rule)

type rule struct {
	x []float64
	w []float64
}

func getRule(order uint) *rule {
	if rule, ok := ruleCache[order]; ok {
		return rule
	}
	x, w := quadrature.Legendre(order, 0.0, 1.0)
	rule := &rule{x, w}
	ruleCache[order] = rule
	return rule
}

func integrate(a, b float64, order uint, target func(float64) float64) float64 {
	value, rule := 0.0, getRule(order)
	for i := uint(0); i < order; i++ {
		x := a + (b-a)*rule.x[i]
		w := (b - a) * rule.w[i]
		value += w * target(x)
	}
	return value
}
<|endoftext|>