<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/stumpyfr/udger"
)

func main() {
	if len(os.Args) != 3 {
		fmt.Println("Usage:\n\tgo run main.go ./udgerdb.dat \"Opera/9.50 (Nintendo DSi; Opera/507; U; en-US)\"")
		os.Exit(0)
	}

	u, err := udger.New(os.Args[1])
	if err != nil {
		fmt.Println("error: ", err)
		os.Exit(-1)
	}

	fmt.Println(len(u.Browsers), "browsers loaded")
	fmt.Println(len(u.OS), "OS loaded")
	fmt.Println(len(u.Devices), "device types loaded")
	fmt.Println("")

	ua, err := u.Lookup(os.Args[2])
	if err != nil {
		fmt.Println("error: ", err)
		os.Exit(-1)
	}

	fmt.Printf("%+v\n", ua)
}
<commit_msg>fix path<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/udger/udger"
)

func main() {
	if len(os.Args) != 3 {
		fmt.Println("Usage:\n\tgo run main.go ./udgerdb.dat \"Opera/9.50 (Nintendo DSi; Opera/507; U; en-US)\"")
		os.Exit(0)
	}

	u, err := udger.New(os.Args[1])
	if err != nil {
		fmt.Println("error: ", err)
		os.Exit(-1)
	}

	fmt.Println(len(u.Browsers), "browsers loaded")
	fmt.Println(len(u.OS), "OS loaded")
	fmt.Println(len(u.Devices), "device types loaded")
	fmt.Println("")

	ua, err := u.Lookup(os.Args[2])
	if err != nil {
		fmt.Println("error: ", err)
		os.Exit(-1)
	}

	fmt.Printf("%+v\n", ua)
}
<|endoftext|>


<commit_before>package sources

import (
	"net/http"
	"fmt"
	"encoding/json"
	"github.com/golang/glog"
	"bytes")

type DmrContainer struct {
	Name    string      `json:"name,omitempty"`
	Host    string      `json:"host"`
	DmrPort int         `json:"dmrPort"`
	Stats   *StatsEntry `json:"stats,omitempty"`
}

type DmrAttributeRequest struct {
	Operation 	string	`json:"operation"`
	Name      	string	`json:"name"`
	Pretty		int		`json:"json.pretty"`
}

type DmrResourceRequest struct {
	Operation 			string		`json:"operation"`
	IncludeRuntime      bool		`json:"include-runtime"`
	Address				[]string	`json:"address"`
	Pretty				int			`json:"json.pretty"`
}

type DmrResponse struct {
	Outcome 				string		`json:"outcome"`
	Result      			interface{}	`json:"result"`
	FailureDescription      string		`json:"failure-description"`
	RolledBacked      		bool		`json:"rolled-back"`
}

type WebResult struct {
	BytesReceived		int64		`json:"bytesReceived"`
	BytesSent			int64		`json:"bytesSent"`
	EnableLookups		string		`json:"enable-lookups"`
	Enabled				string		`json:"enabled"`
	ErrorCount			int			`json:"errorCount"`
	Executor			string		`json:"executor"`
	MaxConnections		int			`json:"max-connections"`
	MaxPostSize			int64		`json:"max-post-size"`
	MaxSavePostSize		int64		`json:"max-save-post-size"`
	MaxTime				int64		`json:"maxTime"`
	Name				string		`json:"name"`
	ProcessingTime		int64		`json:"processingTime"`
	Protocol			string		`json:"protocol"`
	ProxyName			string		`json:"proxy-name"`
	ProxyPort			string		`json:"proxy-port"`
	RedirectPort		int			`json:"redirect-port"`
	RequestCount		int64		`json:"requestCount"`
	Scheme				string		`json:"scheme"`
	Secure				string		`json:"secure"`
	SocketBinding		string		`json:"socket-binding"`
	SSL					string		`json:"ssl"`
	VirtualServer		string		`json:"virtual-server"`
}

func (self *DmrContainer) GetName() string {
	return self.Name
}

func (self *DmrContainer) GetStats() (*StatsEntry, error) {
	dmrRequest := DmrResourceRequest{
		Operation: "read-resource",
		IncludeRuntime: true,
		Address: []string{"subsystem", "undertow", "server", "default-server", "http-listener", "default"},
		Pretty: 1,
	}

	dmrResponse := DmrResponse{
		Result: WebResult{},
	}

	err := self.getStats(&dmrRequest, &dmrResponse)
	if err != nil {
		return nil, err
	}

	glog.Infof("outcome: %s, result: %s, failure: %s", dmrResponse.Outcome, dmrResponse.Result, dmrResponse.FailureDescription)

	return &StatsEntry{}, nil
}

func (self *DmrContainer) getStats(request interface{}, result interface{}) error {
	reqBody, err := json.Marshal(request)
	if err != nil {
		return err
	}

	url := fmt.Sprintf("http://%s:%d/management", self.Host, self.DmrPort)

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqBody))
	if err != nil {
		return err
	}

	req.Header.Add("Content-Type", "application/json")

	err = PostRequestAndGetValue(&http.Client{}, req, result)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Use old web subsystem.<commit_after>package sources

import (
	"net/http"
	"fmt"
	"encoding/json"
	"github.com/golang/glog"
	"bytes")

type DmrContainer struct {
	Name    string      `json:"name,omitempty"`
	Host    string      `json:"host"`
	DmrPort int         `json:"dmrPort"`
	Stats   *StatsEntry `json:"stats,omitempty"`
}

type DmrAttributeRequest struct {
	Operation 	string	`json:"operation"`
	Name      	string	`json:"name"`
	Pretty		int		`json:"json.pretty"`
}

type DmrResourceRequest struct {
	Operation 			string		`json:"operation"`
	IncludeRuntime      bool		`json:"include-runtime"`
	Address				[]string	`json:"address"`
	Pretty				int			`json:"json.pretty"`
}

type DmrResponse struct {
	Outcome 				string		`json:"outcome"`
	Result      			interface{}	`json:"result"`
	FailureDescription      string		`json:"failure-description"`
	RolledBacked      		bool		`json:"rolled-back"`
}

type WebResult struct {
	BytesReceived		int64		`json:"bytesReceived"`
	BytesSent			int64		`json:"bytesSent"`
	EnableLookups		string		`json:"enable-lookups"`
	Enabled				string		`json:"enabled"`
	ErrorCount			int			`json:"errorCount"`
	Executor			string		`json:"executor"`
	MaxConnections		int			`json:"max-connections"`
	MaxPostSize			int64		`json:"max-post-size"`
	MaxSavePostSize		int64		`json:"max-save-post-size"`
	MaxTime				int64		`json:"maxTime"`
	Name				string		`json:"name"`
	ProcessingTime		int64		`json:"processingTime"`
	Protocol			string		`json:"protocol"`
	ProxyName			string		`json:"proxy-name"`
	ProxyPort			string		`json:"proxy-port"`
	RedirectPort		int			`json:"redirect-port"`
	RequestCount		int64		`json:"requestCount"`
	Scheme				string		`json:"scheme"`
	Secure				string		`json:"secure"`
	SocketBinding		string		`json:"socket-binding"`
	SSL					string		`json:"ssl"`
	VirtualServer		string		`json:"virtual-server"`
}

func (self *DmrContainer) GetName() string {
	return self.Name
}

func (self *DmrContainer) GetStats() (*StatsEntry, error) {
	dmrRequest := DmrResourceRequest{
		Operation: "read-resource",
		IncludeRuntime: true,
		Address: []string{"subsystem", "web", "connector", "http"},
		Pretty: 1,
	}

	dmrResponse := DmrResponse{
		Result: WebResult{},
	}

	err := self.getStats(&dmrRequest, &dmrResponse)
	if err != nil {
		return nil, err
	}

	glog.Infof("outcome: %s, result: %s, failure: %s", dmrResponse.Outcome, dmrResponse.Result, dmrResponse.FailureDescription)

	return &StatsEntry{}, nil
}

func (self *DmrContainer) getStats(request interface{}, result interface{}) error {
	reqBody, err := json.Marshal(request)
	if err != nil {
		return err
	}

	url := fmt.Sprintf("http://%s:%d/management", self.Host, self.DmrPort)

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqBody))
	if err != nil {
		return err
	}

	req.Header.Add("Content-Type", "application/json")

	err = PostRequestAndGetValue(&http.Client{}, req, result)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package manta

import (
    "io/ioutil"
    "fmt"
	"github.com/dotabuff/manta/dota"
)

// Represents the state of a spawngroup
// String parts are almost never filled
// Flags are almost always SPAWN_GROUP_CREATE_CLIENT_ONLY_ENTITIES & SPAWN_GROUP_LOAD_STREAMING_DATA
type spawnGroup struct {
    worldName     string
    entLumpName   string
    entFilterName string
    handle        uint32 // used as an index to refer to spawngroups in non-load packets
    ownerHandle   uint32
    manifest      []byte
    flags         uint32
    tickCount     int32
    localName     string
    parentName    string
    complete      bool
}

func (sg *spawnGroup) writeFixture() {
    // [id]_[isComplete]_sg_manifest.raw
    fname := fmt.Sprintf("%d_%t_sg_manifest.raw", sg.handle, sg.complete);
    err := ioutil.WriteFile(fname, sg.manifest, 0644)

    if err != nil {
        _panicf("Error writing spawnGroup fixture, %s", err)
    }
}

// Parse a spawnGroup manifest
// Format: <1 bit IsLZSSCompressed | 24 bit length | Data>
func (sg *spawnGroup) parse() {
    reader := newReader(sg.manifest)

    isCompressed := reader.readBoolean()
    size := reader.readBits(24)
    data := reader.readBytes(int(size))

    if isCompressed {
        dataUnc, err := unlzss(data)
        if err != nil {
            _panicf("Error uncompressing spawnGroup data %s", err)
        }

        data = dataUnc
    }
}

func (p *Parser) onCNETMsg_SpawnGroup_Load(m *dota.CNETMsg_SpawnGroup_Load) error {
    sg := &spawnGroup{
        worldName     : m.GetWorldname(),
        entLumpName   : m.GetEntitylumpname(),
        entFilterName : m.GetEntityfiltername(),
        handle        : m.GetSpawngrouphandle(),
        ownerHandle   : m.GetSpawngroupownerhandle(),
        manifest      : m.GetSpawngroupmanifest(),
        flags         : m.GetFlags(),
        tickCount     : m.GetTickcount(),
        localName     : m.GetLocalnamefixup(),
        parentName    : m.GetParentnamefixup(),
        complete      : !m.GetManifestincomplete(),
	}

	p.spawnGroups[m.GetSpawngrouphandle()] = sg
	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_ManifestUpdate(m *dota.CNETMsg_SpawnGroup_ManifestUpdate) error {
    sg, ok := p.spawnGroups[m.GetSpawngrouphandle()]
    if !ok {
        _panicf("Unable to find spawngroup %d for update %d", m.GetSpawngrouphandle(), p.Tick)
    }

    // Current rationale:
    // - If the previous spawn group is complete, overrride it with the new one
    // - If it's incomplete, append the rest of the data
    // - Always update the completion status
    //
    // There might be a delta-update mechanism but the manifest decyphered first

    if sg.complete {
        sg.manifest = m.GetSpawngroupmanifest()
        sg.complete = !m.GetManifestincomplete()
    } else {
        sg.manifest = append(sg.manifest, m.GetSpawngroupmanifest()...)
        sg.complete = !m.GetManifestincomplete()
    }

	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_SetCreationTick(m *dota.CNETMsg_SpawnGroup_SetCreationTick) error {
    sg, ok := p.spawnGroups[m.GetSpawngrouphandle()]
    if !ok {
        _panicf("Unable to find spawngroup %d for tick update", m.GetSpawngrouphandle())
    }

    sg.tickCount = m.GetTickcount()

	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_Unload(m *dota.CNETMsg_SpawnGroup_Unload) error {
    _, ok := p.spawnGroups[m.GetSpawngrouphandle()]
    if ok {
        // It seems that spawn groups are not always present when being unloaded
        delete(p.spawnGroups, m.GetSpawngrouphandle())
    }

	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_LoadCompleted(m *dota.CNETMsg_SpawnGroup_LoadCompleted) error {
    _debugf("Info: LoadComplete message found") // This doesn't seem to get called at all
	return nil
}<commit_msg>Progress on spawngroup parsing<commit_after>package manta

import (
    "io/ioutil"
    "fmt"
	"github.com/dotabuff/manta/dota"
)

// Represents the state of a spawngroup
// String parts are almost never filled
// Flags are almost always SPAWN_GROUP_CREATE_CLIENT_ONLY_ENTITIES & SPAWN_GROUP_LOAD_STREAMING_DATA
type spawnGroup struct {
    worldName     string
    entLumpName   string
    entFilterName string
    handle        uint32 // used as an index to refer to spawngroups in non-load packets
    ownerHandle   uint32
    manifest      []byte
    flags         uint32
    tickCount     int32
    localName     string
    parentName    string
    complete      bool
}

func (sg *spawnGroup) writeFixture() {
    // [id]_[isComplete]_sg_manifest.raw
    fname := fmt.Sprintf("%d_%t_sg_manifest.raw", sg.handle, sg.complete);
    err := ioutil.WriteFile(fname, sg.manifest, 0644)

    if err != nil {
        _panicf("Error writing spawnGroup fixture, %s", err)
    }
}

// Parse a spawnGroup manifest
// Format: <1 bit IsLZSSCompressed | 24 bit length | Data>
// Data: <8 bit arrayLength | 0 | 8 bit ressourceStrings | 0 | 8 bit unkown | 0 | dataTypes * arrayLength | 0 | ... data ...>
func (sg *spawnGroup) parse() {
    reader := newReader(sg.manifest)

    isCompressed := reader.readBoolean()
    size := reader.readBits(24)
    data := reader.readBytes(int(size))

    if isCompressed {
        dataUnc, err := unlzss(data)
        if err != nil {
            _panicf("Error uncompressing spawnGroup data %s", err)
        }

        data = dataUnc
    }

    reader2 := newReader(data)
    iSize := reader2.readBits(8)

    // The actual size reading is probably just readUntilNullByte
    // @Todo: find a package that is larger that 256 entries to investigate this
    if iSize > 0 {
        null1 := reader2.readBits(8)
        ressourceStrings := reader2.readBits(8)
        null2 := reader2.readBits(8)
        unkown := reader2.readBits(8)
        null3 := reader2.readBits(8)

        // @Todo: decypher the rest of the package and add it to the spawnGroup struct
    }
}

func (p *Parser) onCNETMsg_SpawnGroup_Load(m *dota.CNETMsg_SpawnGroup_Load) error {
    sg := &spawnGroup{
        worldName     : m.GetWorldname(),
        entLumpName   : m.GetEntitylumpname(),
        entFilterName : m.GetEntityfiltername(),
        handle        : m.GetSpawngrouphandle(),
        ownerHandle   : m.GetSpawngroupownerhandle(),
        manifest      : m.GetSpawngroupmanifest(),
        flags         : m.GetFlags(),
        tickCount     : m.GetTickcount(),
        localName     : m.GetLocalnamefixup(),
        parentName    : m.GetParentnamefixup(),
        complete      : !m.GetManifestincomplete(),
	}

	p.spawnGroups[m.GetSpawngrouphandle()] = sg
	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_ManifestUpdate(m *dota.CNETMsg_SpawnGroup_ManifestUpdate) error {
    sg, ok := p.spawnGroups[m.GetSpawngrouphandle()]
    if !ok {
        _panicf("Unable to find spawngroup %d for update %d", m.GetSpawngrouphandle(), p.Tick)
    }

    // Invoke the parse method, the data should be added to the spawnGroup variable
    // when it is fully decyphered

    if sg.complete {
        sg.manifest = m.GetSpawngroupmanifest()
        sg.complete = !m.GetManifestincomplete()
	    sg.parse()
    } else {
        sg.manifest = m.GetSpawngroupmanifest()
        sg.complete = !m.GetManifestincomplete()
	    sg.parse()
    }

	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_SetCreationTick(m *dota.CNETMsg_SpawnGroup_SetCreationTick) error {
    sg, ok := p.spawnGroups[m.GetSpawngrouphandle()]
    if !ok {
        _panicf("Unable to find spawngroup %d for tick update", m.GetSpawngrouphandle())
    }

    sg.tickCount = m.GetTickcount()

	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_Unload(m *dota.CNETMsg_SpawnGroup_Unload) error {
    _, ok := p.spawnGroups[m.GetSpawngrouphandle()]
    if ok {
        // It seems that spawn groups are not always present when being unloaded
        delete(p.spawnGroups, m.GetSpawngrouphandle())
    }

	return nil
}

func (p *Parser) onCNETMsg_SpawnGroup_LoadCompleted(m *dota.CNETMsg_SpawnGroup_LoadCompleted) error {
    _debugf("Info: LoadComplete message found") // This doesn't seem to get called at all
	return nil
}<|endoftext|>


<commit_before>package replay

import (
	"fmt"
	"net/http"
)

// Replayer provides us with a mechanism to replay HTTP requests
type Replayer struct {
	req *http.Request

	writer http.ResponseWriter

	target *Target

	Errors chan error

	// Current play record
	Play Play

	// List of previous plays for request
	plays []Play
}

func NewReplayer(req *http.Request, w http.ResponseWriter) (*Replayer, error) {
	r := Replayer{
		req:    req,
		writer: w,
	}

	return r.init()
}

// Records request to replay it
func (r *Replayer) init() (*Replayer, error) {
	target, err := NewTarget(r.req)
	if err != nil {
		return nil, err
	}

	r.target = target

	return r, nil
}

// Reset the Replayer's state so it's ready to be replayed
func (r *Replayer) Stop() {
	r.plays = append(r.plays, r.Play)
	r.Play = Play{}
}

func (r *Replayer) Replay() (*http.Request, error) {
	return r.target.Request()
}

////
// http.ResponseWriter methods
////

func (r *Replayer) Header() http.Header {
	fmt.Printf("Getting headers")
	return r.writer.Header()
}

func (r *Replayer) Write(data []byte) (int, error) {
	// Don't write any data (this will be retried)
	if r.IsFailed() {
		return len(data), nil
	}

	fmt.Printf("Writing %d bytes\n", len(data))
	r.Play.Bytes += len(data)
	r.Play.Writes += 1
	return r.writer.Write(data)
}

func (r *Replayer) WriteHeader(status int) {
	r.Play.Status = status

	// This request is failing don't write out please ...
	if r.IsFailed() {
		return
	}

	r.writer.WriteHeader(status)
}

func (r *Replayer) GetError() error {
	if r.Play.Status >= 500 {
		return fmt.Errorf("Status code is %d", r.Play.Status)
	}

	return nil
}

func (r *Replayer) IsFailed() bool {
	return r.GetError() != nil
}
<commit_msg>Remove unnecessary logs<commit_after>package replay

import (
	"fmt"
	"net/http"
)

// Replayer provides us with a mechanism to replay HTTP requests
type Replayer struct {
	req *http.Request

	writer http.ResponseWriter

	target *Target

	Errors chan error

	// Current play record
	Play Play

	// List of previous plays for request
	plays []Play
}

func NewReplayer(req *http.Request, w http.ResponseWriter) (*Replayer, error) {
	r := Replayer{
		req:    req,
		writer: w,
	}

	return r.init()
}

// Records request to replay it
func (r *Replayer) init() (*Replayer, error) {
	target, err := NewTarget(r.req)
	if err != nil {
		return nil, err
	}

	r.target = target

	return r, nil
}

// Reset the Replayer's state so it's ready to be replayed
func (r *Replayer) Stop() {
	r.plays = append(r.plays, r.Play)
	r.Play = Play{}
}

func (r *Replayer) Replay() (*http.Request, error) {
	return r.target.Request()
}

////
// http.ResponseWriter methods
////

func (r *Replayer) Header() http.Header {
	return r.writer.Header()
}

func (r *Replayer) Write(data []byte) (int, error) {
	// Don't write any data (this will be retried)
	if r.IsFailed() {
		return len(data), nil
	}

	r.Play.Bytes += len(data)
	r.Play.Writes += 1
	return r.writer.Write(data)
}

func (r *Replayer) WriteHeader(status int) {
	r.Play.Status = status

	// This request is failing don't write out please ...
	if r.IsFailed() {
		return
	}

	r.writer.WriteHeader(status)
}

func (r *Replayer) GetError() error {
	if r.Play.Status >= 500 {
		return fmt.Errorf("Status code is %d", r.Play.Status)
	}

	return nil
}

func (r *Replayer) IsFailed() bool {
	return r.GetError() != nil
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Gravitational, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package trace implements utility functions for capturing logs
package trace

import (
	"regexp"

	log "github.com/sirupsen/logrus"

	"runtime"
)

const (
	// FileField is a field with code file added to structured traces
	FileField = "file"
	// FunctionField is a field with function name
	FunctionField = "func"
	// LevelField returns logging level as set by logrus
	LevelField = "level"
	// Component is a field that represents component - e.g. service or
	// function
	Component = "component"
)

// TextFormatter is logrus-compatible formatter and adds
// file and line details to every logged entry.
type TextFormatter struct {
	log.TextFormatter
}

// Format implements logrus.Formatter interface and adds file and line
func (tf *TextFormatter) Format(e *log.Entry) ([]byte, error) {
	if frameNo := findFrame(); frameNo != -1 {
		t := newTrace(frameNo, nil)
		new := e.WithFields(log.Fields{FileField: t.Loc(), FunctionField: t.FuncName()})
		new.Time = e.Time
		new.Level = e.Level
		new.Message = e.Message
		e = new
	}
	return (&tf.TextFormatter).Format(e)
}

// JSONFormatter implements logrus.Formatter interface and adds file and line
// properties to JSON entries
type JSONFormatter struct {
	log.JSONFormatter
}

// Format implements logrus.Formatter interface
func (j *JSONFormatter) Format(e *log.Entry) ([]byte, error) {
	if frameNo := findFrame(); frameNo != -1 {
		t := newTrace(frameNo, nil)
		new := e.WithFields(log.Fields{
			FileField:     t.Loc(),
			FunctionField: t.FuncName(),
		})
		new.Level = e.Level
		new.Message = e.Message
		e = new
	}
	return (&j.JSONFormatter).Format(e)
}

var r = regexp.MustCompile(`github\.com/(S|s)irupsen/logrus`)

func findFrame() int {
	for i := 3; i < 10; i++ {
		_, file, _, ok := runtime.Caller(i)
		if !ok {
			return -1
		}
		if !r.MatchString(file) {
			return i
		}
	}
	return -1
}
<commit_msg>JSONFormatter time fix<commit_after>/*
Copyright 2015 Gravitational, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package trace implements utility functions for capturing logs
package trace

import (
	"regexp"

	log "github.com/sirupsen/logrus"

	"runtime"
)

const (
	// FileField is a field with code file added to structured traces
	FileField = "file"
	// FunctionField is a field with function name
	FunctionField = "func"
	// LevelField returns logging level as set by logrus
	LevelField = "level"
	// Component is a field that represents component - e.g. service or
	// function
	Component = "component"
)

// TextFormatter is logrus-compatible formatter and adds
// file and line details to every logged entry.
type TextFormatter struct {
	log.TextFormatter
}

// Format implements logrus.Formatter interface and adds file and line
func (tf *TextFormatter) Format(e *log.Entry) ([]byte, error) {
	if frameNo := findFrame(); frameNo != -1 {
		t := newTrace(frameNo, nil)
		new := e.WithFields(log.Fields{FileField: t.Loc(), FunctionField: t.FuncName()})
		new.Time = e.Time
		new.Level = e.Level
		new.Message = e.Message
		e = new
	}
	return (&tf.TextFormatter).Format(e)
}

// JSONFormatter implements logrus.Formatter interface and adds file and line
// properties to JSON entries
type JSONFormatter struct {
	log.JSONFormatter
}

// Format implements logrus.Formatter interface
func (j *JSONFormatter) Format(e *log.Entry) ([]byte, error) {
	if frameNo := findFrame(); frameNo != -1 {
		t := newTrace(frameNo, nil)
		new := e.WithFields(log.Fields{
			FileField:     t.Loc(),
			FunctionField: t.FuncName(),
		})
		new.Time = e.Time
		new.Level = e.Level
		new.Message = e.Message
		e = new
	}
	return (&j.JSONFormatter).Format(e)
}

var r = regexp.MustCompile(`github\.com/(S|s)irupsen/logrus`)

func findFrame() int {
	for i := 3; i < 10; i++ {
		_, file, _, ok := runtime.Caller(i)
		if !ok {
			return -1
		}
		if !r.MatchString(file) {
			return i
		}
	}
	return -1
}
<|endoftext|>


<commit_before>/* This implements an alternative logger to the one found in the standard
 * library with support for more logging levels, formatters and outputs.
 * The main goal is to provide easy and flexible way to handle new outputs and formats
 * Author: Robert Zaremba
 *
 * https://github.com/scale-it/go-log
 */
package log

import (
	"errors"
	"fmt"
	"io"
	"log"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

// Represents how critical the logged
// message is.
type Level uint8

var Levels = struct {
	Trace   Level
	Debug   Level
	Info    Level
	Warning Level
	Error   Level
	Fatal   Level
}{0, 10, 20, 30, 40, 50}

// Verbose names of the levels
var levelStrings = map[Level]string{
	Levels.Trace:   "TRACE",
	Levels.Debug:   "DEBUG",
	Levels.Info:    "INFO",
	Levels.Warning: "WARN",
	Levels.Error:   "ERROR",
	Levels.Fatal:   "FATAL",
}

// Verbose and colored names of the levels
var levelCStrings = map[Level]string{
	Levels.Trace:   levelStrings[Levels.Trace],
	Levels.Debug:   levelStrings[Levels.Debug],
	Levels.Info:    AnsiEscape(MAGENTA, levelStrings[Levels.Info], OFF),
	Levels.Warning: AnsiEscape(YELLOW, levelStrings[Levels.Warning], OFF),
	Levels.Error:   AnsiEscape(RED, levelStrings[Levels.Error], OFF),
	Levels.Fatal:   AnsiEscape(RED, BOLD, levelStrings[Levels.Fatal], OFF),
}

// Returns an log Level which name match given string.
// If there is no such Level, then Levels.Debug is returned
func String2Level(level string) (Level, error) {
	if level == "" {
		return Levels.Debug, errors.New("level is empty")
	}
	for li, ls := range levelStrings {
		if ls == level {
			return li, nil
		}
	}
	return Levels.Debug, errors.New("Wrong log level " + level)
}

type Formatter interface {
	Format(Level, string) []byte
}

type output struct {
	writer io.Writer
	level  Level
	fmt    Formatter
}

// The Logger
type Logger struct {
	mtx     sync.Mutex
	outputs []output
}

// Instantiate a new Logger
func New() *Logger {
	return &Logger{sync.Mutex{}, make([]output, 0)}
}

//
// STANDARD FORMATTERS
// -------------------

type StdFormatter struct {
	Prefix  string // prefix to write at beginning of each line
	Flag    int    // format flags - based flags from std log package
	Colored bool   // use colored level names
}

func (this StdFormatter) Format(level Level, msg string) []byte {
	var slevel string
	var ok bool
	var out []string

	// adding time info
	if this.Flag&(log.Ldate|log.Ltime|log.Lmicroseconds) != 0 {
		now := time.Now()
		if this.Flag&log.Ldate != 0 {
			out = append(out, fmt.Sprintf("%v-%02d-%02d", now.Year(), now.Month(), now.Day()))
		}
		if this.Flag&(log.Lmicroseconds) != 0 {
			out = append(out, fmt.Sprintf("%02d:%02d:%02d.%06d", now.Hour(), now.Minute(), now.Second(), now.Nanosecond()/1000000))
		} else if this.Flag&(log.Ltime) != 0 {
			out = append(out, fmt.Sprintf("%02d:%02d:%02d", now.Hour(), now.Minute(), now.Second()))
		}

	}

	// adding level info
	if this.Colored {
		slevel, ok = levelCStrings[level]
	} else {
		slevel, ok = levelStrings[level]
	}
	if !ok {
		slevel = strconv.Itoa(int(level))
	}
	out = append(out, slevel)

	out = append(out, this.Prefix)

	// adding caller info. It's quiet exepnsive
	if this.Flag&(log.Lshortfile|log.Llongfile) != 0 {
		if _, file, line, ok := runtime.Caller(2); ok { // 2: calldepth
			if this.Flag&log.Lshortfile != 0 {
				for i := len(file) - 1; i > 0; i-- {
					if file[i] == '/' {
						file = file[i+1:]
						break
					}
				}
			}
			out = append(out, fmt.Sprintf("%s:%d", file, line))
		} else {
			out = append(out, "???")
		}
	}

	out = append(out, msg)
	return []byte(strings.Join(out, " "))
}

//
// LOGGER
// ------

// Loggers a message for the given level. Most callers will likely
// prefer to use one of the provided convenience functions.
func (this *Logger) Log(level Level, format string, v ...interface{}) {
	message := fmt.Sprintf(format+"\n", v...)
	// strTimestamp := getTimestamp()
	// strFinal := fmt.Sprintf("%s [%-5s] %s", strTimestamp, levelCStrings[level], message)

	this.mtx.Lock()
	defer this.mtx.Unlock()
	for _, output := range this.outputs {
		if output.level <= level {
			output.writer.Write(output.fmt.Format(output.level, message))
		}
	}
}

// Adds an ouput, specifying the maximum log Level
// you want to be written to this output. For instance,
// if you pass Warning for level, all logs of type
// Warning, Error, and Fatal would be logged to this output.
func (this *Logger) AddOutput(writer io.Writer, level Level, fm Formatter) {
	this.mtx.Lock()
	this.outputs = append(this.outputs, output{writer, level, fm})
	this.mtx.Unlock()
}

// Convenience function
func (this *Logger) Trace(format string, v ...interface{}) {
	// TODO: split the string
	this.Log(Levels.Trace, format, v...)
}

// Convenience function
func (this *Logger) Debug(format string, v ...interface{}) {
	this.Log(Levels.Debug, format, v...)
}

// Convenience function
func (this *Logger) Info(format string, v ...interface{}) {
	this.Log(Levels.Info, format, v...)
}

// Convenience function
func (this *Logger) Warning(format string, v ...interface{}) {
	this.Log(Levels.Warning, format, v...)
}

// Convenience function
func (this *Logger) Error(format string, v ...interface{}) {
	this.Log(Levels.Error, format, v...)
}

// Convenience function, will not terminate the program
func (this *Logger) Fatal(format string, v ...interface{}) {
	this.Log(Levels.Fatal, format, v...)
}
<commit_msg>Added formatted Logf method<commit_after>/* This implements an alternative logger to the one found in the standard
 * library with support for more logging levels, formatters and outputs.
 * The main goal is to provide easy and flexible way to handle new outputs and formats
 * Author: Robert Zaremba
 *
 * https://github.com/scale-it/go-log
 */
package log

import (
	"errors"
	"fmt"
	"io"
	"log"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

// Represents how critical the logged
// message is.
type Level uint8

var Levels = struct {
	Trace   Level
	Debug   Level
	Info    Level
	Warning Level
	Error   Level
	Fatal   Level
}{0, 10, 20, 30, 40, 50}

// Verbose names of the levels
var levelStrings = map[Level]string{
	Levels.Trace:   "TRACE",
	Levels.Debug:   "DEBUG",
	Levels.Info:    "INFO",
	Levels.Warning: "WARN",
	Levels.Error:   "ERROR",
	Levels.Fatal:   "FATAL",
}

// Verbose and colored names of the levels
var levelCStrings = map[Level]string{
	Levels.Trace:   levelStrings[Levels.Trace],
	Levels.Debug:   levelStrings[Levels.Debug],
	Levels.Info:    AnsiEscape(MAGENTA, levelStrings[Levels.Info], OFF),
	Levels.Warning: AnsiEscape(YELLOW, levelStrings[Levels.Warning], OFF),
	Levels.Error:   AnsiEscape(RED, levelStrings[Levels.Error], OFF),
	Levels.Fatal:   AnsiEscape(RED, BOLD, levelStrings[Levels.Fatal], OFF),
}

// Returns an log Level which name match given string.
// If there is no such Level, then Levels.Debug is returned
func String2Level(level string) (Level, error) {
	if level == "" {
		return Levels.Debug, errors.New("level is empty")
	}
	for li, ls := range levelStrings {
		if ls == level {
			return li, nil
		}
	}
	return Levels.Debug, errors.New("Wrong log level " + level)
}

type Formatter interface {
	Format(Level, string) []byte
}

type output struct {
	writer io.Writer
	level  Level
	fmt    Formatter
}

// The Logger
type Logger struct {
	mtx     sync.Mutex
	outputs []output
}

// Instantiate a new Logger
func New() *Logger {
	return &Logger{sync.Mutex{}, make([]output, 0)}
}

// Standard Formatter
type StdFormatter struct {
	Prefix  string // prefix to write at beginning of each line
	Flag    int    // format flags - based flags from std log package
	Colored bool   // use colored level names
}

func (this StdFormatter) Format(level Level, msg string) []byte {
	var slevel string
	var ok bool
	var out []string

	// adding time info
	if this.Flag&(log.Ldate|log.Ltime|log.Lmicroseconds) != 0 {
		now := time.Now()
		if this.Flag&log.Ldate != 0 {
			out = append(out, fmt.Sprintf("%v-%02d-%02d", now.Year(), now.Month(), now.Day()))
		}
		if this.Flag&(log.Lmicroseconds) != 0 {
			out = append(out, fmt.Sprintf("%02d:%02d:%02d.%06d", now.Hour(), now.Minute(), now.Second(), now.Nanosecond()/1000000))
		} else if this.Flag&(log.Ltime) != 0 {
			out = append(out, fmt.Sprintf("%02d:%02d:%02d", now.Hour(), now.Minute(), now.Second()))
		}

	}

	// adding level info
	if this.Colored {
		slevel, ok = levelCStrings[level]
	} else {
		slevel, ok = levelStrings[level]
	}
	if !ok {
		slevel = strconv.Itoa(int(level))
	}
	out = append(out, slevel)

	out = append(out, this.Prefix)

	// adding caller info. It's quiet exepnsive
	if this.Flag&(log.Lshortfile|log.Llongfile) != 0 {
		if _, file, line, ok := runtime.Caller(2); ok { // 2: calldepth
			if this.Flag&log.Lshortfile != 0 {
				for i := len(file) - 1; i > 0; i-- {
					if file[i] == '/' {
						file = file[i+1:]
						break
					}
				}
			}
			out = append(out, fmt.Sprintf("%s:%d", file, line))
		} else {
			out = append(out, "???")
		}
	}

	out = append(out, msg)
	return []byte(strings.Join(out, " "))
}

/* LOGGER
 * ------
 */

// Adds an ouput, specifying the maximum log Level
// you want to be written to this output. For instance,
// if you pass Warning for level, all logs of type
// Warning, Error, and Fatal would be logged to this output.
func (this *Logger) AddOutput(writer io.Writer, level Level, fm Formatter) {
	this.mtx.Lock()
	this.outputs = append(this.outputs, output{writer, level, fm})
	this.mtx.Unlock()
}

// Logs a message for the given level. Most callers will likely
// prefer to use one of the provided convenience functions (Debug, Info...).
func (this *Logger) Log(level Level, msg string) {
	this.mtx.Lock()
	defer this.mtx.Unlock()
	for _, output := range this.outputs {
		if output.level <= level {
			output.writer.Write(output.fmt.Format(output.level, msg))
		}
	}
}

// Logs a formatted message message for the given level.
// Wrapper around Log method
func (this *Logger) Logf(level Level, format string, v ...interface{}) {
	this.Log(level, fmt.Sprintf(format+"\n", v...))
}

// Convenience function
func (this *Logger) Trace(format string, v ...interface{}) {
	// TODO: split the string
	this.Log(Levels.Trace, fmt.Sprintf(format+"\n", v...))
}

// Convenience function
func (this *Logger) Debug(format string, v ...interface{}) {
	this.Log(Levels.Debug, fmt.Sprintf(format+"\n", v...))
}

// Convenience function
func (this *Logger) Info(format string, v ...interface{}) {
	this.Log(Levels.Info, fmt.Sprintf(format+"\n", v...))
}

// Convenience function
func (this *Logger) Warning(format string, v ...interface{}) {
	this.Log(Levels.Warning, fmt.Sprintf(format+"\n", v...))
}

// Convenience function
func (this *Logger) Error(format string, v ...interface{}) {
	this.Log(Levels.Error, fmt.Sprintf(format+"\n", v...))
}

// Convenience function, will not terminate the program
func (this *Logger) Fatal(format string, v ...interface{}) {
	this.Log(Levels.Fatal, fmt.Sprintf(format+"\n", v...))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"runtime/debug"
)

var (
	// Console output (can be disabled by changing)
	consoleOut io.Writer = os.Stderr
	// Loggers for file output
	debugLog  *log.Logger
	errorLog  *log.Logger
	outputLog *log.Logger
	logFile   *os.File
)

// Log error with format (no implicit newline)
func LogErrorf(format string, v ...interface{}) {
	fmt.Fprintf(consoleOut, format, v...)

	if errorLog != nil {
		errorLog.Printf(format, v...)
		// Also dump stack trace to log
		errorLog.Println(debug.Stack())
	}
}

// Log debug message with format (if verbose)
func LogDebugf(format string, v ...interface{}) {
	if GlobalOptions.Verbose {
		fmt.Fprintf(consoleOut, format, v...)
	}

	if GlobalOptions.Verbose || GlobalOptions.VerboseLog {
		if debugLog != nil {
			debugLog.Printf(format, v...)
		}
	}

}

// Log output message with format (if not quiet)
func Logf(format string, v ...interface{}) {
	if !GlobalOptions.Quiet {
		fmt.Fprintf(consoleOut, format, v...)

		if outputLog != nil {
			outputLog.Printf(format, v...)
		}
	}
}

// Log error message with newline
func LogError(msg string) {
	fmt.Fprintln(consoleOut, msg)

	if errorLog != nil {
		errorLog.Println(msg)
		// Also dump stack trace to log
		errorLog.Println(debug.Stack())
	}

}

// Log debug message with newline (if verbose)
func LogDebug(msg string) {
	if GlobalOptions.Verbose {
		fmt.Fprintln(consoleOut, msg)
	}

	if GlobalOptions.Verbose || GlobalOptions.VerboseLog {
		if debugLog != nil {
			debugLog.Println(msg)
		}
	}
}

// Log output message with newline (if not quiet)
func Log(msg string) {
	if !GlobalOptions.Quiet {
		fmt.Fprintln(consoleOut, msg)

		if outputLog != nil {
			outputLog.Println(msg)
		}
	}
}

func getLogFileHandle() *os.File {
	var logFileName string
	if GlobalOptions.LogFile != "" {
		logFileName = GlobalOptions.LogFile
	} else {
		usr, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		logFileName = filepath.Join(usr.HomeDir, "git-lob.log")
	}
	var err error
	logFile, err = os.OpenFile(logFileName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal(err)
	}
	return logFile
}

// Initialise logging, make sure GlobalOptions is initialised
func InitLogging() {

	if GlobalOptions.LogEnabled {
		const logFlags = log.Ldate | log.Ltime | log.Lshortfile
		f := getLogFileHandle()
		outputLog = log.New(f, "", logFlags)
		errorLog = log.New(f, "ERROR: ", logFlags)
		debugLog = log.New(f, "", logFlags)
	}
}
func ShutDownLogging() {
	if logFile != nil {
		logFile.Close()
	}

}
<commit_msg>Convert stack from []byte to string before logging<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"runtime/debug"
)

var (
	// Console output (can be disabled by changing)
	consoleOut io.Writer = os.Stderr
	// Loggers for file output
	debugLog  *log.Logger
	errorLog  *log.Logger
	outputLog *log.Logger
	logFile   *os.File
)

// Log error with format (no implicit newline)
func LogErrorf(format string, v ...interface{}) {
	fmt.Fprintf(consoleOut, format, v...)

	if errorLog != nil {
		errorLog.Printf(format, v...)
		// Also dump stack trace to log
		errorLog.Println(string(debug.Stack()))
	}
}

// Log debug message with format (if verbose)
func LogDebugf(format string, v ...interface{}) {
	if GlobalOptions.Verbose {
		fmt.Fprintf(consoleOut, format, v...)
	}

	if GlobalOptions.Verbose || GlobalOptions.VerboseLog {
		if debugLog != nil {
			debugLog.Printf(format, v...)
		}
	}

}

// Log output message with format (if not quiet)
func Logf(format string, v ...interface{}) {
	if !GlobalOptions.Quiet {
		fmt.Fprintf(consoleOut, format, v...)

		if outputLog != nil {
			outputLog.Printf(format, v...)
		}
	}
}

// Log error message with newline
func LogError(msg string) {
	fmt.Fprintln(consoleOut, msg)

	if errorLog != nil {
		errorLog.Println(msg)
		// Also dump stack trace to log
		errorLog.Println(debug.Stack())
	}

}

// Log debug message with newline (if verbose)
func LogDebug(msg string) {
	if GlobalOptions.Verbose {
		fmt.Fprintln(consoleOut, msg)
	}

	if GlobalOptions.Verbose || GlobalOptions.VerboseLog {
		if debugLog != nil {
			debugLog.Println(msg)
		}
	}
}

// Log output message with newline (if not quiet)
func Log(msg string) {
	if !GlobalOptions.Quiet {
		fmt.Fprintln(consoleOut, msg)

		if outputLog != nil {
			outputLog.Println(msg)
		}
	}
}

func getLogFileHandle() *os.File {
	var logFileName string
	if GlobalOptions.LogFile != "" {
		logFileName = GlobalOptions.LogFile
	} else {
		usr, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		logFileName = filepath.Join(usr.HomeDir, "git-lob.log")
	}
	var err error
	logFile, err = os.OpenFile(logFileName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal(err)
	}
	return logFile
}

// Initialise logging, make sure GlobalOptions is initialised
func InitLogging() {

	if GlobalOptions.LogEnabled {
		const logFlags = log.Ldate | log.Ltime | log.Lshortfile
		f := getLogFileHandle()
		outputLog = log.New(f, "", logFlags)
		errorLog = log.New(f, "ERROR: ", logFlags)
		debugLog = log.New(f, "", logFlags)
	}
}
func ShutDownLogging() {
	if logFile != nil {
		logFile.Close()
	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
)

// LogLevel identifies logging levels
type LogLevel int

// Definitions of log lgevels
const (
	Debug LogLevel = iota
	Info
	Warning
	Error
	Fatal
)

// Logger is the interface used for logging
type Logger interface {
	// Info loggs a message of info level
	Info(format string, a ...interface{})
	Warning(format string, a ...interface{})
	Error(format string, a ...interface{})
	Fatalf(format string, a ...interface{})
	Debug(format string, a ...interface{})

	Level(level LogLevel)
}

// NullLogger implements
type NullLogger struct{}

// Info in the null logger does nothing
func (nl NullLogger) Info(format string, a ...interface{}) {}

// Warning in the null logger does nothing
func (nl NullLogger) Warning(format string, a ...interface{}) {}

// Error in the null logger does nothing
func (nl NullLogger) Error(format string, a ...interface{}) {}

// Fatalf in the null logger does nothing
func (nl NullLogger) Fatalf(format string, a ...interface{}) {
	os.Exit(1)
}

// Debug in the null logger does nothing
func (nl NullLogger) Debug(format string, a ...interface{}) {}

// Level in the null logger does nothing
func (nl NullLogger) Level(level LogLevel) {}

// ConsoleLogger implements
type ConsoleLogger struct{}

// Debug in the null logger does nothing
func (nl ConsoleLogger) Debug(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// Info in the null logger does nothing
func (nl ConsoleLogger) Info(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// Warning in the null logger does nothing
func (nl ConsoleLogger) Warning(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// Error in the null logger does nothing
func (nl ConsoleLogger) Error(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// Fatalf in the null logger does nothing
func (nl ConsoleLogger) Fatalf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
	os.Exit(1)
}

// Level in the null logger does nothing
func (nl ConsoleLogger) Level(level LogLevel) {}
<commit_msg>Removed null logger and added a writer to normal logger<commit_after>package main

import (
	"fmt"
	"io"
	"os"
)

// LogLevel identifies logging levels
type LogLevel int

// Definitions of log lgevels
const (
	Debug LogLevel = iota
	Info
	Warning
	Error
)

// Logger is the interface used for logging
type Logger interface {
	// Info loggs a message of info level
	Info(format string, a ...interface{})
	Warning(format string, a ...interface{})
	Error(format string, a ...interface{})
	Fatalf(format string, a ...interface{})
	Debug(format string, a ...interface{})

	Level(level LogLevel)
}

// ConsoleLogger implements
type ConsoleLogger struct {
	W io.Writer
}

// SetOutput sets the output to w
func (nl *ConsoleLogger) SetOutput(w io.Writer) {
	nl.W = w
}

func (nl ConsoleLogger) output() io.Writer {
	if nl.W == nil {
		return os.Stderr
	}
	return nl.W
}

// Debug in the null logger does nothing
func (nl ConsoleLogger) Debug(format string, a ...interface{}) {
	fmt.Fprintf(nl.output(), format, a...)
}

// Info in the null logger does nothing
func (nl ConsoleLogger) Info(format string, a ...interface{}) {
	fmt.Fprintf(nl.output(), format, a...)
}

// Warning in the null logger does nothing
func (nl ConsoleLogger) Warning(format string, a ...interface{}) {
	fmt.Fprintf(nl.output(), format, a...)
}

// Error in the null logger does nothing
func (nl ConsoleLogger) Error(format string, a ...interface{}) {
	fmt.Fprintf(nl.output(), format, a...)
}

// Fatalf in the null logger does nothing
func (nl ConsoleLogger) Fatalf(format string, a ...interface{}) {
	fmt.Fprintf(nl.output(), format, a...)
	os.Exit(1)
}

// Level in the null logger does nothing
func (nl ConsoleLogger) Level(level LogLevel) {}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"os"
)

// These are the environmental variables that determine if we log, and if
// we log whether or not the log should go to a file.
const EnvLog = "TF_LOG"
const EnvLogFile = "TF_LOG_PATH"

// logOutput determines where we should send logs (if anywhere).
func logOutput() (logOutput io.Writer, err error) {
	logOutput = nil
	if os.Getenv(EnvLog) != "" {
		logOutput = os.Stderr

		if logPath := os.Getenv(EnvLogFile); logPath != "" {
			var err error
			logOutput, err = os.Create(logPath)
			if err != nil {
				return nil, err
			}
		}
	}

	return
}
<commit_msg>Improve comments in log.go<commit_after>package main

import (
	"io"
	"os"
)

// These are the environmental variables that determine if we log, and if
// we log whether or not the log should go to a file.
const EnvLog = "TF_LOG" //Set to True
const EnvLogFile = "TF_LOG_PATH" //Set to a file

// logOutput determines where we should send logs (if anywhere).
func logOutput() (logOutput io.Writer, err error) {
	logOutput = nil
	if os.Getenv(EnvLog) != "" {
		logOutput = os.Stderr

		if logPath := os.Getenv(EnvLogFile); logPath != "" {
			var err error
			logOutput, err = os.Create(logPath)
			if err != nil {
				return nil, err
			}
		}
	}

	return
}
<|endoftext|>


<commit_before>package gorivets

import (
	"container/list"
	"strconv"
	"time"
)

type (
	// Least Recently Used container interface. Defines basic methods for
	// different implementations (see sized and time-based below).
	//
	// Method calls should be guarded by synchronization primitives in
	// multi-thread environment, unless it's explicitly said "friendly"
	LRU interface {
		// Add an element to the LRU.
		Add(k, v interface{}, size int64)
		// returns the element and marks it as recently used
		Get(k interface{}) (interface{}, bool)
		// returns the element, but not marking it as used recently
		Peek(k interface{}) (interface{}, bool)

		// Deletes an element and call for callback if it is not nil
		// equivavalent to DeleteWithCallback(k, true)
		Delete(k interface{}) interface{}

		// Deletes an elementa and call callback function if callback==true and
		// the callback function was specified for the container
		DeleteWithCallback(k interface{}, callback bool) interface{}

		// Garbage collection call, can be needed for time restricted LRU
		Sweep()
		Clear()
		// Multithread: friendly
		Len() int
		// Multithread: friendly
		Size() int64
	}

	Lru struct {
		list     *list.List
		elements map[interface{}]*list.Element
		size     int64
		maxSize  int64
		callback LruCallback
	}

	element struct {
		key  interface{}
		val  interface{}
		size int64
	}

	lru_ttl struct {
		list     *list.List
		elements map[interface{}]*list.Element
		size     int64
		maxSize  int64
		duration time.Duration
		callback LruCallback
	}

	element_ttl struct {
		key       interface{}
		val       interface{}
		size      int64
		expiredOn time.Time
	}

	LruCallback func(k, v interface{})
)

func NewLRU(maxSize int64, callback LruCallback) LRU {
	if maxSize < 1 {
		panic("LRU size=" + strconv.FormatInt(maxSize, 10) + " should be positive.")
	}
	l := new(Lru)
	l.list = list.New()
	l.elements = make(map[interface{}]*list.Element)
	l.size = 0
	l.maxSize = maxSize
	l.callback = callback
	return l
}

func NewTtlLRU(maxSize int64, duration time.Duration, callback LruCallback) LRU {
	if maxSize < 1 {
		panic("LRU size=" + strconv.FormatInt(maxSize, 10) + " should be positive.")
	}
	l := new(lru_ttl)
	l.list = list.New()
	l.elements = make(map[interface{}]*list.Element)
	l.size = 0
	l.maxSize = maxSize
	l.callback = callback
	l.duration = duration
	return l
}

// =============================== Lru =======================================
func (lru *Lru) Add(k, v interface{}, size int64) {
	lru.Delete(k)
	e := &element{key: k, val: v, size: size}
	el := lru.list.PushBack(e)
	lru.elements[k] = el
	lru.size += size
	for lru.size > lru.maxSize && lru.deleteLast() {
		// left empty intentionally
	}
}

func (lru *Lru) Get(k interface{}) (interface{}, bool) {
	if e, ok := lru.elements[k]; ok {
		lru.list.MoveToBack(e)
		return e.Value.(*element).val, true
	}
	return nil, false
}

func (lru *Lru) Peek(k interface{}) (interface{}, bool) {
	e, ok := lru.elements[k]
	return e, ok
}

func (lru *Lru) Delete(k interface{}) interface{} {
	return lru.DeleteWithCallback(k, true)
}

func (lru *Lru) DeleteWithCallback(k interface{}, callback bool) interface{} {
	el, ok := lru.elements[k]
	if !ok {
		return nil
	}
	delete(lru.elements, k)
	e := lru.list.Remove(el).(*element)
	lru.size -= e.size
	if callback && lru.callback != nil {
		lru.callback(e.key, e.val)
	}
	return e.val
}

func (lru *Lru) Sweep() {
}

// Clear the cache. This method will not invoke callbacks for the deleted
// elements
func (lru *Lru) Clear() {
	lru.list.Init()
	lru.elements = make(map[interface{}]*list.Element)
	lru.size = 0
}

func (lru *Lru) Len() int {
	return len(lru.elements)
}

func (lru *Lru) Size() int64 {
	return lru.size
}

func (lru *Lru) deleteLast() bool {
	el := lru.list.Front()
	if el == nil {
		return false
	}
	e := el.Value.(*element)
	lru.Delete(e.key)
	return true
}

// ============================= lru_ttl =====================================
func (lru *lru_ttl) Add(k, v interface{}, size int64) {
	lru.Delete(k)
	now := time.Now()
	e := &element_ttl{key: k, val: v, size: size, expiredOn: now.Add(lru.duration)}
	el := lru.list.PushBack(e)
	lru.elements[k] = el
	lru.size += size
	for (lru.size > lru.maxSize || lru.lastExpired(now)) && lru.deleteLast() {
		// left empty intentionally
	}
}

func (lru *lru_ttl) Get(k interface{}) (interface{}, bool) {
	if e, ok := lru.elements[k]; ok {
		et := e.Value.(*element_ttl)
		et.expiredOn = time.Now().Add(lru.duration)
		lru.list.MoveToBack(e)
		return et.val, true
	}
	return nil, false
}

func (lru *lru_ttl) Peek(k interface{}) (interface{}, bool) {
	e, ok := lru.elements[k]
	return e, ok
}

func (lru *lru_ttl) Delete(k interface{}) interface{} {
	return lru.deleteWithCallback(k, true)
}

func (lru *lru_ttl) DeleteWithCallback(k interface{}, callback bool) interface{} {
	return lru.deleteWithCallback(k, callback)
}

func (lru *lru_ttl) delete(k interface{}) interface{} {
	return lru.deleteWithCallback(k, true)
}

func (lru *lru_ttl) deleteWithCallback(k interface{}, callback bool) interface{} {
	el, ok := lru.elements[k]
	if !ok {
		return nil
	}
	delete(lru.elements, k)
	e := lru.list.Remove(el).(*element_ttl)
	lru.size -= e.size
	if callback && lru.callback != nil {
		lru.callback(e.key, e.val)
	}
	return e.val
}

func (lru *lru_ttl) Sweep() {
	lru.timeCleanup()
}

// Clear the cache. This method will not invoke callbacks for the deleted
// elements
func (lru *lru_ttl) Clear() {
	lru.list.Init()
	lru.elements = make(map[interface{}]*list.Element)
	lru.size = 0
}

func (lru *lru_ttl) Len() int {
	return len(lru.elements)
}

func (lru *lru_ttl) Size() int64 {
	return lru.size
}

func (lru *lru_ttl) deleteLast() bool {
	el := lru.list.Front()
	if el == nil {
		return false
	}
	e := el.Value.(*element_ttl)
	lru.delete(e.key)
	return true
}

func (lru *lru_ttl) lastExpired(now time.Time) bool {
	el := lru.list.Front()
	if el == nil {
		return false
	}
	e := el.Value.(*element_ttl)
	return now.After(e.expiredOn)
}

func (lru *lru_ttl) timeCleanup() {
	now := time.Now()
	for lru.lastExpired(now) && lru.deleteLast() {
		// left empty intentionally
	}
}
<commit_msg>bug fixinig<commit_after>package gorivets

import (
	"container/list"
	"strconv"
	"time"
)

type (
	// Least Recently Used container interface. Defines basic methods for
	// different implementations (see sized and time-based below).
	//
	// Method calls should be guarded by synchronization primitives in
	// multi-thread environment, unless it's explicitly said "friendly"
	LRU interface {
		// Add an element to the LRU.
		Add(k, v interface{}, size int64)
		// returns the element and marks it as recently used
		Get(k interface{}) (interface{}, bool)
		// returns the element, but not marking it as used recently
		Peek(k interface{}) (interface{}, bool)

		// Deletes an element and call for callback if it is not nil
		// equivavalent to DeleteWithCallback(k, true)
		Delete(k interface{}) interface{}

		// Deletes an elementa and call callback function if callback==true and
		// the callback function was specified for the container
		DeleteWithCallback(k interface{}, callback bool) interface{}

		// Garbage collection call, can be needed for time restricted LRU
		Sweep()
		Clear()
		// Multithread: friendly
		Len() int
		// Multithread: friendly
		Size() int64
	}

	Lru struct {
		list     *list.List
		elements map[interface{}]*list.Element
		size     int64
		maxSize  int64
		callback LruCallback
	}

	element struct {
		key  interface{}
		val  interface{}
		size int64
	}

	lru_ttl struct {
		list     *list.List
		elements map[interface{}]*list.Element
		size     int64
		maxSize  int64
		duration time.Duration
		callback LruCallback
	}

	element_ttl struct {
		key       interface{}
		val       interface{}
		size      int64
		expiredOn time.Time
	}

	LruCallback func(k, v interface{})
)

func NewLRU(maxSize int64, callback LruCallback) LRU {
	if maxSize < 1 {
		panic("LRU size=" + strconv.FormatInt(maxSize, 10) + " should be positive.")
	}
	l := new(Lru)
	l.list = list.New()
	l.elements = make(map[interface{}]*list.Element)
	l.size = 0
	l.maxSize = maxSize
	l.callback = callback
	return l
}

func NewTtlLRU(maxSize int64, duration time.Duration, callback LruCallback) LRU {
	if maxSize < 1 {
		panic("LRU size=" + strconv.FormatInt(maxSize, 10) + " should be positive.")
	}
	l := new(lru_ttl)
	l.list = list.New()
	l.elements = make(map[interface{}]*list.Element)
	l.size = 0
	l.maxSize = maxSize
	l.callback = callback
	l.duration = duration
	return l
}

// =============================== Lru =======================================
func (lru *Lru) Add(k, v interface{}, size int64) {
	lru.Delete(k)
	e := &element{key: k, val: v, size: size}
	el := lru.list.PushBack(e)
	lru.elements[k] = el
	lru.size += size
	for lru.size > lru.maxSize && lru.deleteLast() {
		// left empty intentionally
	}
}

func (lru *Lru) Get(k interface{}) (interface{}, bool) {
	if e, ok := lru.elements[k]; ok {
		lru.list.MoveToBack(e)
		return e.Value.(*element).val, true
	}
	return nil, false
}

func (lru *Lru) Peek(k interface{}) (interface{}, bool) {
	if e, ok := lru.elements[k]; ok {
		return e.Value.(*element).val, true
	}
	return nil, false
}

func (lru *Lru) Delete(k interface{}) interface{} {
	return lru.DeleteWithCallback(k, true)
}

func (lru *Lru) DeleteWithCallback(k interface{}, callback bool) interface{} {
	el, ok := lru.elements[k]
	if !ok {
		return nil
	}
	delete(lru.elements, k)
	e := lru.list.Remove(el).(*element)
	lru.size -= e.size
	if callback && lru.callback != nil {
		lru.callback(e.key, e.val)
	}
	return e.val
}

func (lru *Lru) Sweep() {
}

// Clear the cache. This method will not invoke callbacks for the deleted
// elements
func (lru *Lru) Clear() {
	lru.list.Init()
	lru.elements = make(map[interface{}]*list.Element)
	lru.size = 0
}

func (lru *Lru) Len() int {
	return len(lru.elements)
}

func (lru *Lru) Size() int64 {
	return lru.size
}

func (lru *Lru) deleteLast() bool {
	el := lru.list.Front()
	if el == nil {
		return false
	}
	e := el.Value.(*element)
	lru.Delete(e.key)
	return true
}

// ============================= lru_ttl =====================================
func (lru *lru_ttl) Add(k, v interface{}, size int64) {
	lru.Delete(k)
	now := time.Now()
	e := &element_ttl{key: k, val: v, size: size, expiredOn: now.Add(lru.duration)}
	el := lru.list.PushBack(e)
	lru.elements[k] = el
	lru.size += size
	for (lru.size > lru.maxSize || lru.lastExpired(now)) && lru.deleteLast() {
		// left empty intentionally
	}
}

func (lru *lru_ttl) Get(k interface{}) (interface{}, bool) {
	if e, ok := lru.elements[k]; ok {
		et := e.Value.(*element_ttl)
		et.expiredOn = time.Now().Add(lru.duration)
		lru.list.MoveToBack(e)
		return et.val, true
	}
	return nil, false
}

func (lru *lru_ttl) Peek(k interface{}) (interface{}, bool) {
	if e, ok := lru.elements[k]; ok {
		et := e.Value.(*element_ttl)
		return et.val, true
	}
	return nil, false
}

func (lru *lru_ttl) Delete(k interface{}) interface{} {
	return lru.deleteWithCallback(k, true)
}

func (lru *lru_ttl) DeleteWithCallback(k interface{}, callback bool) interface{} {
	return lru.deleteWithCallback(k, callback)
}

func (lru *lru_ttl) delete(k interface{}) interface{} {
	return lru.deleteWithCallback(k, true)
}

func (lru *lru_ttl) deleteWithCallback(k interface{}, callback bool) interface{} {
	el, ok := lru.elements[k]
	if !ok {
		return nil
	}
	delete(lru.elements, k)
	e := lru.list.Remove(el).(*element_ttl)
	lru.size -= e.size
	if callback && lru.callback != nil {
		lru.callback(e.key, e.val)
	}
	return e.val
}

func (lru *lru_ttl) Sweep() {
	lru.timeCleanup()
}

// Clear the cache. This method will not invoke callbacks for the deleted
// elements
func (lru *lru_ttl) Clear() {
	lru.list.Init()
	lru.elements = make(map[interface{}]*list.Element)
	lru.size = 0
}

func (lru *lru_ttl) Len() int {
	return len(lru.elements)
}

func (lru *lru_ttl) Size() int64 {
	return lru.size
}

func (lru *lru_ttl) deleteLast() bool {
	el := lru.list.Front()
	if el == nil {
		return false
	}
	e := el.Value.(*element_ttl)
	lru.delete(e.key)
	return true
}

func (lru *lru_ttl) lastExpired(now time.Time) bool {
	el := lru.list.Front()
	if el == nil {
		return false
	}
	e := el.Value.(*element_ttl)
	return now.After(e.expiredOn)
}

func (lru *lru_ttl) timeCleanup() {
	now := time.Now()
	for lru.lastExpired(now) && lru.deleteLast() {
		// left empty intentionally
	}
}
<|endoftext|>


<commit_before>package mqttpubsub

import (
	"encoding/json"
	"fmt"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/brocaar/loraserver/models"
	"github.com/brocaar/lorawan"
	"github.com/eclipse/paho.mqtt.golang"
)

// Backend implements a MQTT pub-sub backend.
type Backend struct {
	conn         mqtt.Client
	txPacketChan chan models.TXPacket
	gateways     map[lorawan.EUI64]struct{}
	mutex        sync.RWMutex
}

// NewBackend creates a new Backend.
func NewBackend(server, username, password string) (*Backend, error) {
	b := Backend{
		txPacketChan: make(chan models.TXPacket),
		gateways:     make(map[lorawan.EUI64]struct{}),
	}

	opts := mqtt.NewClientOptions()
	opts.AddBroker(server)
	opts.SetUsername(username)
	opts.SetPassword(password)
	opts.SetOnConnectHandler(b.onConnected)
	opts.SetConnectionLostHandler(b.onConnectionLost)

	log.WithField("server", server).Info("backend/mqttpubsub: connecting to mqtt broker")
	b.conn = mqtt.NewClient(opts)
	if token := b.conn.Connect(); token.Wait() && token.Error() != nil {
		return nil, token.Error()
	}

	return &b, nil
}

// Close closes the backend.
func (b *Backend) Close() {
	b.conn.Disconnect(250) // wait 250 milisec to complete pending actions
}

// TXPacketChan returns the TXPacket channel.
func (b *Backend) TXPacketChan() chan models.TXPacket {
	return b.txPacketChan
}

// SubscribeGatewayTX subscribes the backend to the gateway TXPacket
// topic (packets the gateway needs to transmit).
func (b *Backend) SubscribeGatewayTX(mac lorawan.EUI64) error {
	defer b.mutex.Unlock()
	b.mutex.Lock()

	topic := fmt.Sprintf("gateway/%s/tx", mac.String())
	log.WithField("topic", topic).Info("backend/mqttpubsub: subscribing to topic")
	if token := b.conn.Subscribe(topic, 0, b.txPacketHandler); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	b.gateways[mac] = struct{}{}
	return nil
}

// UnSubscribeGatewayTX unsubscribes the backend from the gateway TXPacket
// topic.
func (b *Backend) UnSubscribeGatewayTX(mac lorawan.EUI64) error {
	defer b.mutex.Unlock()
	b.mutex.Lock()

	topic := fmt.Sprintf("gateway/%s/tx", mac.String())
	log.WithField("topic", topic).Info("backend/mqttpubsub: unsubscribing from topic")
	if token := b.conn.Unsubscribe(topic); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	delete(b.gateways, mac)
	return nil
}

// PublishGatewayRX publishes a RX packet to the MQTT broker.
func (b *Backend) PublishGatewayRX(mac lorawan.EUI64, rxPacket models.RXPacket) error {
	topic := fmt.Sprintf("gateway/%s/rx", mac.String())
	return b.publish(topic, rxPacket)
}

// PublishGatewayStats publishes a GatewayStatsPacket to the MQTT broker.
func (b *Backend) PublishGatewayStats(mac lorawan.EUI64, stats models.GatewayStatsPacket) error {
	topic := fmt.Sprintf("gateway/%s/stats", mac.String())
	return b.publish(topic, stats)
}

func (b *Backend) publish(topic string, v interface{}) error {
	bytes, err := json.Marshal(v)
	if err != nil {
		return err
	}
	log.WithField("topic", topic).Info("backend/mqttpubsub: publishing packet")
	if token := b.conn.Publish(topic, 0, false, bytes); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	return nil
}

func (b *Backend) txPacketHandler(c mqtt.Client, msg mqtt.Message) {
	log.WithField("topic", msg.Topic()).Info("backend/mqttpubsub: packet received")
	var txPacket models.TXPacket
	if err := json.Unmarshal(msg.Payload(), &txPacket); err != nil {
		log.Errorf("backend/mqttpubsub: decode tx packet error: %s", err)
		return
	}
	b.txPacketChan <- txPacket
}

func (b *Backend) onConnected(c mqtt.Client) {
	defer b.mutex.RUnlock()
	b.mutex.RLock()

	log.Info("backend/mqttpubsub: connected to mqtt broker")
	if len(b.gateways) > 0 {
		for {
			log.WithField("topic_count", len(b.gateways)).Info("backend/mqttpubsub: re-registering to gateway topics")
			topics := make(map[string]byte)
			for k := range b.gateways {
				topics[fmt.Sprintf("gateway/%s/tx", k)] = 0
			}
			if token := b.conn.SubscribeMultiple(topics, b.txPacketHandler); token.Wait() && token.Error() != nil {
				log.WithField("topic_count", len(topics)).Errorf("backend/mqttpubsub: subscribe multiple failed: %s", token.Error())
				time.Sleep(time.Second)
				continue
			}
			return
		}
	}
}

func (b *Backend) onConnectionLost(c mqtt.Client, reason error) {
	log.Errorf("backend/mqttpubsub: mqtt connection error: %s", reason)
}
<commit_msg>Update logging.<commit_after>package mqttpubsub

import (
	"encoding/json"
	"fmt"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/brocaar/loraserver/models"
	"github.com/brocaar/lorawan"
	"github.com/eclipse/paho.mqtt.golang"
)

// Backend implements a MQTT pub-sub backend.
type Backend struct {
	conn         mqtt.Client
	txPacketChan chan models.TXPacket
	gateways     map[lorawan.EUI64]struct{}
	mutex        sync.RWMutex
}

// NewBackend creates a new Backend.
func NewBackend(server, username, password string) (*Backend, error) {
	b := Backend{
		txPacketChan: make(chan models.TXPacket),
		gateways:     make(map[lorawan.EUI64]struct{}),
	}

	opts := mqtt.NewClientOptions()
	opts.AddBroker(server)
	opts.SetUsername(username)
	opts.SetPassword(password)
	opts.SetOnConnectHandler(b.onConnected)
	opts.SetConnectionLostHandler(b.onConnectionLost)

	log.WithField("server", server).Info("backend: connecting to mqtt broker")
	b.conn = mqtt.NewClient(opts)
	if token := b.conn.Connect(); token.Wait() && token.Error() != nil {
		return nil, token.Error()
	}

	return &b, nil
}

// Close closes the backend.
func (b *Backend) Close() {
	b.conn.Disconnect(250) // wait 250 milisec to complete pending actions
}

// TXPacketChan returns the TXPacket channel.
func (b *Backend) TXPacketChan() chan models.TXPacket {
	return b.txPacketChan
}

// SubscribeGatewayTX subscribes the backend to the gateway TXPacket
// topic (packets the gateway needs to transmit).
func (b *Backend) SubscribeGatewayTX(mac lorawan.EUI64) error {
	defer b.mutex.Unlock()
	b.mutex.Lock()

	topic := fmt.Sprintf("gateway/%s/tx", mac.String())
	log.WithField("topic", topic).Info("backend: subscribing to topic")
	if token := b.conn.Subscribe(topic, 0, b.txPacketHandler); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	b.gateways[mac] = struct{}{}
	return nil
}

// UnSubscribeGatewayTX unsubscribes the backend from the gateway TXPacket
// topic.
func (b *Backend) UnSubscribeGatewayTX(mac lorawan.EUI64) error {
	defer b.mutex.Unlock()
	b.mutex.Lock()

	topic := fmt.Sprintf("gateway/%s/tx", mac.String())
	log.WithField("topic", topic).Info("backend: unsubscribing from topic")
	if token := b.conn.Unsubscribe(topic); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	delete(b.gateways, mac)
	return nil
}

// PublishGatewayRX publishes a RX packet to the MQTT broker.
func (b *Backend) PublishGatewayRX(mac lorawan.EUI64, rxPacket models.RXPacket) error {
	topic := fmt.Sprintf("gateway/%s/rx", mac.String())
	return b.publish(topic, rxPacket)
}

// PublishGatewayStats publishes a GatewayStatsPacket to the MQTT broker.
func (b *Backend) PublishGatewayStats(mac lorawan.EUI64, stats models.GatewayStatsPacket) error {
	topic := fmt.Sprintf("gateway/%s/stats", mac.String())
	return b.publish(topic, stats)
}

func (b *Backend) publish(topic string, v interface{}) error {
	bytes, err := json.Marshal(v)
	if err != nil {
		return err
	}
	log.WithField("topic", topic).Info("backend: publishing packet")
	if token := b.conn.Publish(topic, 0, false, bytes); token.Wait() && token.Error() != nil {
		return token.Error()
	}
	return nil
}

func (b *Backend) txPacketHandler(c mqtt.Client, msg mqtt.Message) {
	log.WithField("topic", msg.Topic()).Info("backend: packet received")
	var txPacket models.TXPacket
	if err := json.Unmarshal(msg.Payload(), &txPacket); err != nil {
		log.Errorf("backend: decode tx packet error: %s", err)
		return
	}
	b.txPacketChan <- txPacket
}

func (b *Backend) onConnected(c mqtt.Client) {
	defer b.mutex.RUnlock()
	b.mutex.RLock()

	log.Info("backend: connected to mqtt broker")
	if len(b.gateways) > 0 {
		for {
			log.WithField("topic_count", len(b.gateways)).Info("backend: re-registering to gateway topics")
			topics := make(map[string]byte)
			for k := range b.gateways {
				topics[fmt.Sprintf("gateway/%s/tx", k)] = 0
			}
			if token := b.conn.SubscribeMultiple(topics, b.txPacketHandler); token.Wait() && token.Error() != nil {
				log.WithField("topic_count", len(topics)).Errorf("backend: subscribe multiple failed: %s", token.Error())
				time.Sleep(time.Second)
				continue
			}
			return
		}
	}
}

func (b *Backend) onConnectionLost(c mqtt.Client, reason error) {
	log.Errorf("backend: mqtt connection error: %s", reason)
}
<|endoftext|>


<commit_before>package play

import (
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
)

type Flash struct {
	Data, Out map[string]string
}

type Params url.Values

type Session map[string]string

type Request struct {
	*http.Request
}

type Response struct {
	Status      int
	ContentType string
	Headers     http.Header
	Cookies     []*http.Cookie

	out http.ResponseWriter
}

type Controller struct {
	Name       string
	Type       *ControllerType
	MethodType *MethodType

	Request  *Request
	Response *Response

	Flash      Flash                  // User cookie, cleared after each request.
	Session    Session                // Session, stored in cookie, signed.
	Params     Params                 // URL Query parameters
	Args       map[string]interface{} // Per-request scratch space.
	RenderArgs map[string]interface{} // Args passed to the template.
	Validation *Validation            // Data validation helpers
	Txn        *sql.Tx                // Nil by default, but may be used by the app / plugins
}

func NewController(w http.ResponseWriter, r *http.Request, ct *ControllerType) *Controller {
	flash := restoreFlash(r)
	values := r.URL.Query()

	// Add form values to params.
	if err := r.ParseForm(); err != nil {
		LOG.Println("Error parsing request body:", err)
	} else {
		for key, vals := range r.Form {
			for _, val := range vals {
				values.Add(key, val)
			}
		}
	}

	return &Controller{
		Name:    ct.Type.Name(),
		Type:    ct,
		Request: &Request{r},
		Response: &Response{
			Status:      200,
			ContentType: "",
			Headers:     w.Header(),
			out:         w,
		},

		Params:  Params(values),
		Flash:   flash,
		Session: restoreSession(r),
		RenderArgs: map[string]interface{}{
			"flash": flash.Data,
		},
		Validation: &Validation{
			Errors: restoreValidationErrors(r),
			keep:   false,
		},
	}
}

var (
	controllerType    = reflect.TypeOf(Controller{})
	controllerPtrType = reflect.TypeOf(&Controller{})
)

func NewAppController(w http.ResponseWriter, r *http.Request, controllerName, methodName string) (*Controller, reflect.Value) {
	var appControllerType *ControllerType = LookupControllerType(controllerName)
	if appControllerType == nil {
		LOG.Printf("E: Controller %s not found: %s", controllerName, r.URL)
		return nil, reflect.ValueOf(nil)
	}

	controller := NewController(w, r, appControllerType)
	appControllerPtr := initNewAppController(appControllerType.Type, controller)

	// Set the method being called.
	controller.MethodType = appControllerType.Method(methodName)
	if controller.MethodType == nil {
		LOG.Println("E: Failed to find method", methodName, "on Controller",
			controllerName)
		return nil, reflect.ValueOf(nil)
	}

	return controller, appControllerPtr
}

// This is a helper that initializes (zeros) a new app controller value.
// Generally, everything is set to its zero value, except:
// 1. Embedded controller pointers are newed up.
// 2. The play.Controller embedded type is set to the value provided.
// Returns a value representing a pointer to the new app controller.
func initNewAppController(appControllerType reflect.Type, c *Controller) reflect.Value {
	// It might be a multi-level embedding, so we have to create new controllers
	// at every level of the hierarchy.
	// ASSUME: the first field in each type is the way up to play.Controller.
	appControllerPtr := reflect.New(appControllerType)
	ptr := appControllerPtr
	for {
		var (
			embeddedField     reflect.Value = ptr.Elem().Field(0)
			embeddedFieldType reflect.Type  = embeddedField.Type()
		)

		// Check if it's the Play! controller.
		if embeddedFieldType == controllerType {
			embeddedField.Set(reflect.ValueOf(c).Elem())
			break
		} else if embeddedFieldType == controllerPtrType {
			embeddedField.Set(reflect.ValueOf(c))
			break
		}

		// If the embedded field is a pointer, then instantiate an object and set it.
		// (If it's not a pointer, then it's already initialized)
		if embeddedFieldType.Kind() == reflect.Ptr {
			embeddedField.Set(reflect.New(embeddedFieldType.Elem()))
			ptr = embeddedField
		} else {
			ptr = embeddedField.Addr()
		}
	}
	return appControllerPtr
}

func (c *Controller) FlashParams() {
	for key, vals := range c.Params {
		c.Flash.Out[key] = vals[0]
	}
}

func (c *Controller) SetCookie(cookie *http.Cookie) {
	http.SetCookie(c.Response.out, cookie)
}

// Invoke the given method, save headers/cookies to the response, and apply the
// result.  (e.g. render a template to the response)
func (c *Controller) Invoke(appControllerPtr reflect.Value, method reflect.Value, methodArgs []reflect.Value) {

	defer func() {
		if err := recover(); err != nil {
			handleInvocationPanic(c, err)
		}
	}()

	// Run the plugins.
	plugins.BeforeRequest(c)

	// Calculate the Result by running the interceptors and the action.
	resultValue := func() reflect.Value {
		// Call the BEFORE interceptors
		result := c.invokeInterceptors(BEFORE, appControllerPtr)
		if result != nil {
			return reflect.ValueOf(result)
		}

		// Invoke the action.
		resultValue := method.Call(methodArgs)[0]

		// Call the AFTER interceptors
		result = c.invokeInterceptors(AFTER, appControllerPtr)
		if result != nil {
			return reflect.ValueOf(result)
		}
		return resultValue
	}()

	plugins.AfterRequest(c)

	if resultValue.IsNil() {
		return
	}
	result := resultValue.Interface().(Result)

	// Store the flash.
	var flashValue string
	for key, value := range c.Flash.Out {
		flashValue += "\x00" + key + ":" + value + "\x00"
	}
	c.SetCookie(&http.Cookie{
		Name:  "PLAY_FLASH",
		Value: url.QueryEscape(flashValue),
		Path:  "/",
	})

	// Store the Validation errors
	var errorsValue string
	if c.Validation.keep {
		for _, error := range c.Validation.Errors {
			if error.Message != "" {
				errorsValue += "\x00" + error.Key + ":" + error.Message + "\x00"
			}
		}
	}
	c.SetCookie(&http.Cookie{
		Name:  "PLAY_ERRORS",
		Value: url.QueryEscape(errorsValue),
		Path:  "/",
	})

	// Store the session (and sign it).
	var sessionValue string
	for key, value := range c.Session {
		sessionValue += "\x00" + key + ":" + value + "\x00"
	}
	sessionData := url.QueryEscape(sessionValue)
	c.SetCookie(&http.Cookie{
		Name:  "PLAY_SESSION",
		Value: Sign(sessionData) + "-" + sessionData,
		Path:  "/",
	})

	// Apply the result, which generally results in the ResponseWriter getting written.
	result.Apply(c.Request, c.Response)
}

// This function handles a panic in an action invocation.
// It cleans up the stack trace, logs it, and displays an error page.
func handleInvocationPanic(c *Controller, err interface{}) {
	plugins.OnException(c, err)

	// Parse the filename and line from the originating line of app code.
	// /Users/robfig/code/gocode/src/play/samples/booking/app/controllers/hotels.go:191 (0x44735)
	stack := string(debug.Stack())
	appFrame := strings.Index(stack, BasePath)
	if appFrame == -1 {
		// How embarassing.
		LOG.Println(err, "\n", stack)
		c.Response.out.WriteHeader(500)
		c.Response.out.Write([]byte(stack))
		return
	}
	stackElement := stack[appFrame : appFrame+strings.Index(stack[appFrame:], "\n")]
	colonIndex := strings.LastIndex(stackElement, ":")
	filename := stackElement[:colonIndex]
	var line int
	fmt.Sscan(stackElement[colonIndex+1:], &line)

	// Log the trace starting at the app frame.
	LOG.Println(err, "\n", stack[appFrame:])

	// Show an error page.
	description := "Unspecified error"
	if err != nil {
		description = fmt.Sprintln(err)
	}
	c.Response.out.WriteHeader(500)
	c.Response.out.Write([]byte((&Error{
		Title:       "Panic",
		Path:        filename[len(BasePath):],
		Line:        line,
		Description: description,
		SourceLines: MustReadLines(filename),
	}).Html()))
}

func (c *Controller) invokeInterceptors(when InterceptTime, appControllerPtr reflect.Value) Result {
	var result Result
	for _, intc := range getInterceptors(when, appControllerPtr) {
		resultValue := intc.Invoke(appControllerPtr)
		if !resultValue.IsNil() {
			result = resultValue.Interface().(Result)
		}
		if when == BEFORE && result != nil {
			return result
		}
	}
	return result
}

func (c *Controller) Render(extraRenderArgs ...interface{}) Result {
	// Get the calling function name.
	pc, _, line, ok := runtime.Caller(1)
	if !ok {
		log.Println("Failed to get Caller information")
		return nil
	}
	// e.g. sample/app/controllers.(*Application).Index
	var fqViewName string = runtime.FuncForPC(pc).Name()
	var viewName string = fqViewName[strings.LastIndex(fqViewName, ".")+1 : len(fqViewName)]

	// Get the Template.
	template, err := templateLoader.Template(c.Name + "/" + viewName + ".html")
	if err != nil {
		// TODO: Instead of writing output directly, return an error Result
		if err, ok := err.(*Error); ok {
			c.Response.out.Write([]byte(err.Html()))
		} else {
			c.Response.out.Write([]byte(err.Error()))
		}
		return nil
	}

	// Get the extra RenderArgs passed in.
	if renderArgNames, ok := c.MethodType.RenderArgNames[line]; ok {
		if len(renderArgNames) == len(extraRenderArgs) {
			for i, extraRenderArg := range extraRenderArgs {
				c.RenderArgs[renderArgNames[i]] = extraRenderArg
			}
		} else {
			LOG.Println(len(renderArgNames), "RenderArg names found for",
				len(extraRenderArgs), "extra RenderArgs")
		}
	} else {
		LOG.Println("No RenderArg names found for Render call on line", line)
	}

	// Add Validation errors to RenderArgs.
	c.RenderArgs["errors"] = c.Validation.ErrorMap()

	return &RenderTemplateResult{
		Template:   template,
		RenderArgs: c.RenderArgs,
		Response:   c.Response,
	}
}

// Redirect to an action or to a URL.
//   c.Redirect(Controller.Action)
//   c.Redirect("/controller/action")
//   c.Redirect("/controller/%d/action", id)
func (c *Controller) Redirect(val interface{}, args ...interface{}) Result {
	if url, ok := val.(string); ok {
		if len(args) == 0 {
			return &RedirectToUrlResult{url}
		}
		return &RedirectToUrlResult{fmt.Sprintf(url, args...)}
	}
	return &RedirectToActionResult{val}
}

// Restore flash from a request.
func restoreFlash(req *http.Request) Flash {
	flash := Flash{
		Data: make(map[string]string),
		Out:  make(map[string]string),
	}
	if cookie, err := req.Cookie("PLAY_FLASH"); err == nil {
		ParseKeyValueCookie(cookie.Value, func(key, val string) {
			flash.Data[key] = val
		})
	}
	return flash
}

// Restore Validation.Errors from a request.
func restoreValidationErrors(req *http.Request) []*ValidationError {
	errors := make([]*ValidationError, 0, 5)
	if cookie, err := req.Cookie("PLAY_ERRORS"); err == nil {
		ParseKeyValueCookie(cookie.Value, func(key, val string) {
			errors = append(errors, &ValidationError{
				Key:     key,
				Message: val,
			})
		})
	}
	return errors
}

func restoreSession(req *http.Request) Session {
	session := make(map[string]string)
	cookie, err := req.Cookie("PLAY_SESSION")
	if err != nil {
		return Session(session)
	}

	// Separate the data from the signature.
	hyphen := strings.Index(cookie.Value, "-")
	if hyphen == -1 || hyphen >= len(cookie.Value)-1 {
		return Session(session)
	}
	sig, data := cookie.Value[:hyphen], cookie.Value[hyphen+1:]

	// Verify the signature.
	if Sign(data) != sig {
		LOG.Println("Session cookie signature failed")
		return Session(session)
	}

	ParseKeyValueCookie(data, func(key, val string) {
		session[key] = val
	})

	return Session(session)
}

func (f Flash) Error(msg string, args ...interface{}) {
	if len(args) == 0 {
		f.Out["error"] = msg
	} else {
		f.Out["error"] = fmt.Sprintf(msg, args)
	}
}

func (f Flash) Success(msg string, args ...interface{}) {
	if len(args) == 0 {
		f.Out["success"] = msg
	} else {
		f.Out["success"] = fmt.Sprintf(msg, args)
	}
}

func (p Params) Bind(valueType reflect.Type, key string) reflect.Value {
	return BindKey(p, valueType, key)
}

// Internal bookeeping

type ControllerType struct {
	Type    reflect.Type
	Methods []*MethodType
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
}

type MethodArg struct {
	Name string
	Type reflect.Type
}

func (ct *ControllerType) Method(name string) *MethodType {
	for _, method := range ct.Methods {
		if method.Name == name {
			return method
		}
	}
	return nil
}

var controllers = make(map[string]*ControllerType)

func RegisterController(c interface{}, methods []*MethodType) {
	// De-star the controller type
	// (e.g. given TypeOf((*Application)(nil)), want TypeOf(Application))
	var t reflect.Type = reflect.TypeOf(c)
	var elem reflect.Type = t.Elem()

	// De-star all of the method arg types too.
	for _, m := range methods {
		for _, arg := range m.Args {
			arg.Type = arg.Type.Elem()
		}
	}

	controllers[elem.Name()] = &ControllerType{Type: elem, Methods: methods}
	log.Printf("Registered controller: %s", elem.Name())
}

func LookupControllerType(name string) *ControllerType {
	return controllers[name]
}
<commit_msg>Fix to formatted flash messages<commit_after>package play

import (
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
)

type Flash struct {
	Data, Out map[string]string
}

type Params url.Values

type Session map[string]string

type Request struct {
	*http.Request
}

type Response struct {
	Status      int
	ContentType string
	Headers     http.Header
	Cookies     []*http.Cookie

	out http.ResponseWriter
}

type Controller struct {
	Name       string
	Type       *ControllerType
	MethodType *MethodType

	Request  *Request
	Response *Response

	Flash      Flash                  // User cookie, cleared after each request.
	Session    Session                // Session, stored in cookie, signed.
	Params     Params                 // URL Query parameters
	Args       map[string]interface{} // Per-request scratch space.
	RenderArgs map[string]interface{} // Args passed to the template.
	Validation *Validation            // Data validation helpers
	Txn        *sql.Tx                // Nil by default, but may be used by the app / plugins
}

func NewController(w http.ResponseWriter, r *http.Request, ct *ControllerType) *Controller {
	flash := restoreFlash(r)
	values := r.URL.Query()

	// Add form values to params.
	if err := r.ParseForm(); err != nil {
		LOG.Println("Error parsing request body:", err)
	} else {
		for key, vals := range r.Form {
			for _, val := range vals {
				values.Add(key, val)
			}
		}
	}

	return &Controller{
		Name:    ct.Type.Name(),
		Type:    ct,
		Request: &Request{r},
		Response: &Response{
			Status:      200,
			ContentType: "",
			Headers:     w.Header(),
			out:         w,
		},

		Params:  Params(values),
		Flash:   flash,
		Session: restoreSession(r),
		RenderArgs: map[string]interface{}{
			"flash": flash.Data,
		},
		Validation: &Validation{
			Errors: restoreValidationErrors(r),
			keep:   false,
		},
	}
}

var (
	controllerType    = reflect.TypeOf(Controller{})
	controllerPtrType = reflect.TypeOf(&Controller{})
)

func NewAppController(w http.ResponseWriter, r *http.Request, controllerName, methodName string) (*Controller, reflect.Value) {
	var appControllerType *ControllerType = LookupControllerType(controllerName)
	if appControllerType == nil {
		LOG.Printf("E: Controller %s not found: %s", controllerName, r.URL)
		return nil, reflect.ValueOf(nil)
	}

	controller := NewController(w, r, appControllerType)
	appControllerPtr := initNewAppController(appControllerType.Type, controller)

	// Set the method being called.
	controller.MethodType = appControllerType.Method(methodName)
	if controller.MethodType == nil {
		LOG.Println("E: Failed to find method", methodName, "on Controller",
			controllerName)
		return nil, reflect.ValueOf(nil)
	}

	return controller, appControllerPtr
}

// This is a helper that initializes (zeros) a new app controller value.
// Generally, everything is set to its zero value, except:
// 1. Embedded controller pointers are newed up.
// 2. The play.Controller embedded type is set to the value provided.
// Returns a value representing a pointer to the new app controller.
func initNewAppController(appControllerType reflect.Type, c *Controller) reflect.Value {
	// It might be a multi-level embedding, so we have to create new controllers
	// at every level of the hierarchy.
	// ASSUME: the first field in each type is the way up to play.Controller.
	appControllerPtr := reflect.New(appControllerType)
	ptr := appControllerPtr
	for {
		var (
			embeddedField     reflect.Value = ptr.Elem().Field(0)
			embeddedFieldType reflect.Type  = embeddedField.Type()
		)

		// Check if it's the Play! controller.
		if embeddedFieldType == controllerType {
			embeddedField.Set(reflect.ValueOf(c).Elem())
			break
		} else if embeddedFieldType == controllerPtrType {
			embeddedField.Set(reflect.ValueOf(c))
			break
		}

		// If the embedded field is a pointer, then instantiate an object and set it.
		// (If it's not a pointer, then it's already initialized)
		if embeddedFieldType.Kind() == reflect.Ptr {
			embeddedField.Set(reflect.New(embeddedFieldType.Elem()))
			ptr = embeddedField
		} else {
			ptr = embeddedField.Addr()
		}
	}
	return appControllerPtr
}

func (c *Controller) FlashParams() {
	for key, vals := range c.Params {
		c.Flash.Out[key] = vals[0]
	}
}

func (c *Controller) SetCookie(cookie *http.Cookie) {
	http.SetCookie(c.Response.out, cookie)
}

// Invoke the given method, save headers/cookies to the response, and apply the
// result.  (e.g. render a template to the response)
func (c *Controller) Invoke(appControllerPtr reflect.Value, method reflect.Value, methodArgs []reflect.Value) {

	defer func() {
		if err := recover(); err != nil {
			handleInvocationPanic(c, err)
		}
	}()

	// Run the plugins.
	plugins.BeforeRequest(c)

	// Calculate the Result by running the interceptors and the action.
	resultValue := func() reflect.Value {
		// Call the BEFORE interceptors
		result := c.invokeInterceptors(BEFORE, appControllerPtr)
		if result != nil {
			return reflect.ValueOf(result)
		}

		// Invoke the action.
		resultValue := method.Call(methodArgs)[0]

		// Call the AFTER interceptors
		result = c.invokeInterceptors(AFTER, appControllerPtr)
		if result != nil {
			return reflect.ValueOf(result)
		}
		return resultValue
	}()

	plugins.AfterRequest(c)

	if resultValue.IsNil() {
		return
	}
	result := resultValue.Interface().(Result)

	// Store the flash.
	var flashValue string
	for key, value := range c.Flash.Out {
		flashValue += "\x00" + key + ":" + value + "\x00"
	}
	c.SetCookie(&http.Cookie{
		Name:  "PLAY_FLASH",
		Value: url.QueryEscape(flashValue),
		Path:  "/",
	})

	// Store the Validation errors
	var errorsValue string
	if c.Validation.keep {
		for _, error := range c.Validation.Errors {
			if error.Message != "" {
				errorsValue += "\x00" + error.Key + ":" + error.Message + "\x00"
			}
		}
	}
	c.SetCookie(&http.Cookie{
		Name:  "PLAY_ERRORS",
		Value: url.QueryEscape(errorsValue),
		Path:  "/",
	})

	// Store the session (and sign it).
	var sessionValue string
	for key, value := range c.Session {
		sessionValue += "\x00" + key + ":" + value + "\x00"
	}
	sessionData := url.QueryEscape(sessionValue)
	c.SetCookie(&http.Cookie{
		Name:  "PLAY_SESSION",
		Value: Sign(sessionData) + "-" + sessionData,
		Path:  "/",
	})

	// Apply the result, which generally results in the ResponseWriter getting written.
	result.Apply(c.Request, c.Response)
}

// This function handles a panic in an action invocation.
// It cleans up the stack trace, logs it, and displays an error page.
func handleInvocationPanic(c *Controller, err interface{}) {
	plugins.OnException(c, err)

	// Parse the filename and line from the originating line of app code.
	// /Users/robfig/code/gocode/src/play/samples/booking/app/controllers/hotels.go:191 (0x44735)
	stack := string(debug.Stack())
	appFrame := strings.Index(stack, BasePath)
	if appFrame == -1 {
		// How embarassing.
		LOG.Println(err, "\n", stack)
		c.Response.out.WriteHeader(500)
		c.Response.out.Write([]byte(stack))
		return
	}
	stackElement := stack[appFrame : appFrame+strings.Index(stack[appFrame:], "\n")]
	colonIndex := strings.LastIndex(stackElement, ":")
	filename := stackElement[:colonIndex]
	var line int
	fmt.Sscan(stackElement[colonIndex+1:], &line)

	// Log the trace starting at the app frame.
	LOG.Println(err, "\n", stack[appFrame:])

	// Show an error page.
	description := "Unspecified error"
	if err != nil {
		description = fmt.Sprintln(err)
	}
	c.Response.out.WriteHeader(500)
	c.Response.out.Write([]byte((&Error{
		Title:       "Panic",
		Path:        filename[len(BasePath):],
		Line:        line,
		Description: description,
		SourceLines: MustReadLines(filename),
	}).Html()))
}

func (c *Controller) invokeInterceptors(when InterceptTime, appControllerPtr reflect.Value) Result {
	var result Result
	for _, intc := range getInterceptors(when, appControllerPtr) {
		resultValue := intc.Invoke(appControllerPtr)
		if !resultValue.IsNil() {
			result = resultValue.Interface().(Result)
		}
		if when == BEFORE && result != nil {
			return result
		}
	}
	return result
}

func (c *Controller) Render(extraRenderArgs ...interface{}) Result {
	// Get the calling function name.
	pc, _, line, ok := runtime.Caller(1)
	if !ok {
		log.Println("Failed to get Caller information")
		return nil
	}
	// e.g. sample/app/controllers.(*Application).Index
	var fqViewName string = runtime.FuncForPC(pc).Name()
	var viewName string = fqViewName[strings.LastIndex(fqViewName, ".")+1 : len(fqViewName)]

	// Get the Template.
	template, err := templateLoader.Template(c.Name + "/" + viewName + ".html")
	if err != nil {
		// TODO: Instead of writing output directly, return an error Result
		if err, ok := err.(*Error); ok {
			c.Response.out.Write([]byte(err.Html()))
		} else {
			c.Response.out.Write([]byte(err.Error()))
		}
		return nil
	}

	// Get the extra RenderArgs passed in.
	if renderArgNames, ok := c.MethodType.RenderArgNames[line]; ok {
		if len(renderArgNames) == len(extraRenderArgs) {
			for i, extraRenderArg := range extraRenderArgs {
				c.RenderArgs[renderArgNames[i]] = extraRenderArg
			}
		} else {
			LOG.Println(len(renderArgNames), "RenderArg names found for",
				len(extraRenderArgs), "extra RenderArgs")
		}
	} else {
		LOG.Println("No RenderArg names found for Render call on line", line)
	}

	// Add Validation errors to RenderArgs.
	c.RenderArgs["errors"] = c.Validation.ErrorMap()

	return &RenderTemplateResult{
		Template:   template,
		RenderArgs: c.RenderArgs,
		Response:   c.Response,
	}
}

// Redirect to an action or to a URL.
//   c.Redirect(Controller.Action)
//   c.Redirect("/controller/action")
//   c.Redirect("/controller/%d/action", id)
func (c *Controller) Redirect(val interface{}, args ...interface{}) Result {
	if url, ok := val.(string); ok {
		if len(args) == 0 {
			return &RedirectToUrlResult{url}
		}
		return &RedirectToUrlResult{fmt.Sprintf(url, args...)}
	}
	return &RedirectToActionResult{val}
}

// Restore flash from a request.
func restoreFlash(req *http.Request) Flash {
	flash := Flash{
		Data: make(map[string]string),
		Out:  make(map[string]string),
	}
	if cookie, err := req.Cookie("PLAY_FLASH"); err == nil {
		ParseKeyValueCookie(cookie.Value, func(key, val string) {
			flash.Data[key] = val
		})
	}
	return flash
}

// Restore Validation.Errors from a request.
func restoreValidationErrors(req *http.Request) []*ValidationError {
	errors := make([]*ValidationError, 0, 5)
	if cookie, err := req.Cookie("PLAY_ERRORS"); err == nil {
		ParseKeyValueCookie(cookie.Value, func(key, val string) {
			errors = append(errors, &ValidationError{
				Key:     key,
				Message: val,
			})
		})
	}
	return errors
}

func restoreSession(req *http.Request) Session {
	session := make(map[string]string)
	cookie, err := req.Cookie("PLAY_SESSION")
	if err != nil {
		return Session(session)
	}

	// Separate the data from the signature.
	hyphen := strings.Index(cookie.Value, "-")
	if hyphen == -1 || hyphen >= len(cookie.Value)-1 {
		return Session(session)
	}
	sig, data := cookie.Value[:hyphen], cookie.Value[hyphen+1:]

	// Verify the signature.
	if Sign(data) != sig {
		LOG.Println("Session cookie signature failed")
		return Session(session)
	}

	ParseKeyValueCookie(data, func(key, val string) {
		session[key] = val
	})

	return Session(session)
}

func (f Flash) Error(msg string, args ...interface{}) {
	if len(args) == 0 {
		f.Out["error"] = msg
	} else {
		f.Out["error"] = fmt.Sprintf(msg, args...)
	}
}

func (f Flash) Success(msg string, args ...interface{}) {
	if len(args) == 0 {
		f.Out["success"] = msg
	} else {
		f.Out["success"] = fmt.Sprintf(msg, args...)
	}
}

func (p Params) Bind(valueType reflect.Type, key string) reflect.Value {
	return BindKey(p, valueType, key)
}

// Internal bookeeping

type ControllerType struct {
	Type    reflect.Type
	Methods []*MethodType
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
}

type MethodArg struct {
	Name string
	Type reflect.Type
}

func (ct *ControllerType) Method(name string) *MethodType {
	for _, method := range ct.Methods {
		if method.Name == name {
			return method
		}
	}
	return nil
}

var controllers = make(map[string]*ControllerType)

func RegisterController(c interface{}, methods []*MethodType) {
	// De-star the controller type
	// (e.g. given TypeOf((*Application)(nil)), want TypeOf(Application))
	var t reflect.Type = reflect.TypeOf(c)
	var elem reflect.Type = t.Elem()

	// De-star all of the method arg types too.
	for _, m := range methods {
		for _, arg := range m.Args {
			arg.Type = arg.Type.Elem()
		}
	}

	controllers[elem.Name()] = &ControllerType{Type: elem, Methods: methods}
	log.Printf("Registered controller: %s", elem.Name())
}

func LookupControllerType(name string) *ControllerType {
	return controllers[name]
}
<|endoftext|>


<commit_before>package mssql

import (
	"fmt"
	"net"
	"time"
)

type timeoutConn struct {
	c             net.Conn
	timeout       time.Duration
	buf           *tdsBuffer
	packetPending bool
}

func NewTimeoutConn(conn net.Conn, timeout time.Duration) *timeoutConn {
	return &timeoutConn{
		c:       conn,
		timeout: timeout,
	}
}

func (c *timeoutConn) Read(b []byte) (n int, err error) {
	if c.buf != nil {
		if c.packetPending {
			c.packetPending = false
			err = c.buf.FinishPacket()
			if err != nil {
				err = fmt.Errorf("Cannot send handshake packet: %s", err.Error())
				return
			}
		}
		var packet uint8
		packet, err = c.buf.BeginRead()
		if err != nil {
			err = fmt.Errorf("Cannot read handshake packet: %s", err.Error())
			return
		}
		if packet != packPrelogin {
			err = fmt.Errorf("unexpected packet %d, expecting prelogin", packet)
			return
		}
		n, err = c.buf.Read(b)
		return
	}
	err = c.c.SetDeadline(time.Now().Add(c.timeout))
	if err != nil {
		return
	}
	return c.c.Read(b)
}

func (c *timeoutConn) Write(b []byte) (n int, err error) {
	if c.buf != nil {
		if !c.packetPending {
			c.buf.BeginPacket(packPrelogin)
			c.packetPending = true
		}
		n, err = c.buf.Write(b)
		if err != nil {
			return
		}
		return
	}
	err = c.c.SetDeadline(time.Now().Add(c.timeout))
	if err != nil {
		return
	}
	return c.c.Write(b)
}

func (c timeoutConn) Close() error {
	return c.c.Close()
}

func (c timeoutConn) LocalAddr() net.Addr {
	return c.c.LocalAddr()
}

func (c timeoutConn) RemoteAddr() net.Addr {
	return c.c.RemoteAddr()
}

func (c timeoutConn) SetDeadline(t time.Time) error {
	panic("Not implemented")
}

func (c timeoutConn) SetReadDeadline(t time.Time) error {
	panic("Not implemented")
}

func (c timeoutConn) SetWriteDeadline(t time.Time) error {
	panic("Not implemented")
}
<commit_msg>fix the azure ssl handshake bug<commit_after>package mssql

import (
	"fmt"
	"net"
	"time"
)

type timeoutConn struct {
	c             net.Conn
	timeout       time.Duration
	buf           *tdsBuffer
	packetPending bool
	continueRead  bool
}

func NewTimeoutConn(conn net.Conn, timeout time.Duration) *timeoutConn {
	return &timeoutConn{
		c:       conn,
		timeout: timeout,
	}
}

func (c *timeoutConn) Read(b []byte) (n int, err error) {
	if c.buf != nil {
		if c.packetPending {
			c.packetPending = false
			err = c.buf.FinishPacket()
			if err != nil {
				err = fmt.Errorf("Cannot send handshake packet: %s", err.Error())
				return
			}
			c.continueRead = false
		}
		if !c.continueRead {
			var packet uint8
			packet, err = c.buf.BeginRead()
			if err != nil {
				err = fmt.Errorf("Cannot read handshake packet: %s", err.Error())
				return
			}
			if packet != packPrelogin {
				err = fmt.Errorf("unexpected packet %d, expecting prelogin", packet)
				return
			}
			c.continueRead = true
		}
		n, err = c.buf.Read(b)
		return
	}
	err = c.c.SetDeadline(time.Now().Add(c.timeout))
	if err != nil {
		return
	}
	return c.c.Read(b)
}

func (c *timeoutConn) Write(b []byte) (n int, err error) {
	if c.buf != nil {
		if !c.packetPending {
			c.buf.BeginPacket(packPrelogin)
			c.packetPending = true
		}
		n, err = c.buf.Write(b)
		if err != nil {
			return
		}
		return
	}
	err = c.c.SetDeadline(time.Now().Add(c.timeout))
	if err != nil {
		return
	}
	return c.c.Write(b)
}

func (c timeoutConn) Close() error {
	return c.c.Close()
}

func (c timeoutConn) LocalAddr() net.Addr {
	return c.c.LocalAddr()
}

func (c timeoutConn) RemoteAddr() net.Addr {
	return c.c.RemoteAddr()
}

func (c timeoutConn) SetDeadline(t time.Time) error {
	panic("Not implemented")
}

func (c timeoutConn) SetReadDeadline(t time.Time) error {
	panic("Not implemented")
}

func (c timeoutConn) SetWriteDeadline(t time.Time) error {
	panic("Not implemented")
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"log"
	"time"

	"github.com/tebeka/selenium"
	"github.com/tebeka/selenium/chrome"
)

// A little experiment in documentation automation. The plan is to make it part
// of the build and automate screenshot creation. Right now, it is hard to run
// and it is not to be considered as an "official" part of deloominator code
// base.

func saveScreenshot(wd selenium.WebDriver, path string, filename string) {
	if err := wd.Get("http://localhost:3000" + path); err != nil {
		log.Fatalf("could not connect to application: %v", err)
	}

	if err := wd.MaximizeWindow(""); err != nil {
		log.Fatalf("could not maximize window: %v", err)
	}

	time.Sleep(1 * time.Second)

	output, err := wd.Screenshot()
	if err != nil {
		log.Fatalf("could not take screenshot of the playground: %v", err)
	}

	if err := ioutil.WriteFile("./img/"+filename, output, 0644); err != nil {
		log.Fatalf("could not write image: %v", err)
	}
}

func main() {
	chromeOptions := chrome.Capabilities{
		MobileEmulation: &chrome.MobileEmulation{
			DeviceMetrics: &chrome.DeviceMetrics{Width: 1200, Height: 1400},
		},
	}
	capabilities := selenium.Capabilities{
		"browserName":   "chrome",
		"chromeOptions": chromeOptions,
	}

	// Connect to the WebDriver instance running locally.
	wd, err := selenium.NewRemote(capabilities, "http://localhost:9515")
	if err != nil {
		log.Fatalf("could not connect to webdriver: %v", err)
	}
	defer func() {
		if err := wd.Quit(); err != nil {
			log.Printf("could not quit webdriver: %v", err)
		}
	}()

	saveScreenshot(wd, "/playground", "playground.png")
	saveScreenshot(wd, "/questions", "questions.png")
	saveScreenshot(wd, "/questions/1", "question.png")
}
<commit_msg>Minor changes to docs script<commit_after>package main

import (
	"io/ioutil"
	"log"
	"time"

	"github.com/tebeka/selenium"
	"github.com/tebeka/selenium/chrome"
)

// A little experiment in documentation automation. The plan is to make it part
// of the build and automate screenshot creation. Right now, it is hard to run
// and it is not to be considered as an "official" part of deloominator code
// base.

func saveScreenshot(wd selenium.WebDriver, path string, filename string) {
	if err := wd.Get("http://localhost:3000" + path); err != nil {
		log.Fatalf("could not connect to application: %v", err)
	}

	if err := wd.MaximizeWindow(""); err != nil {
		log.Printf("could not maximize window: %v", err)
		return
	}

	time.Sleep(1 * time.Second)

	output, err := wd.Screenshot()
	if err != nil {
		log.Printf("could not take screenshot for %s : %v", filename, err)
		return
	}

	if err := ioutil.WriteFile("./img/"+filename, output, 0644); err != nil {
		log.Printf("could not write image: %v", err)
		return
	}
}

func main() {
	chromeOptions := chrome.Capabilities{
		MobileEmulation: &chrome.MobileEmulation{
			DeviceMetrics: &chrome.DeviceMetrics{Width: 1200, Height: 1400},
		},
	}
	capabilities := selenium.Capabilities{
		"browserName":   "chrome",
		"chromeOptions": chromeOptions,
	}

	// Connect to the WebDriver instance running locally.
	wd, err := selenium.NewRemote(capabilities, "http://localhost:9515")
	if err != nil {
		log.Fatalf("could not connect to webdriver: %v", err)
	}
	defer func() {
		if err := wd.Quit(); err != nil {
			log.Printf("could not quit webdriver: %v", err)
		}
	}()

	saveScreenshot(wd, "/playground", "playground.png")
	saveScreenshot(wd, "/questions", "questions.png")
	saveScreenshot(wd, "/questions/1", "question.png")
}
<|endoftext|>