<commit_before>// package htm implements a hierarchical triangular mesh suitable for graphic display and querying.
package htm

import (
	"errors"
	"fmt"
	"time"

	"azul3d.org/lmath.v1"
)

// Tree represents a node in an HTM struct that can contain indices and be subdivided.
type Tree struct {
	Name string

	indices  [3]int
	vertices *[]lmath.Vec3

	T0 *Tree
	T1 *Tree
	T2 *Tree
	T3 *Tree
}

// NewTree returns an initialized node by the given name with the given index values.
func NewTree(name string, verts *[]lmath.Vec3, i0, i1, i2 int) *Tree {
	return &Tree{
		Name:     name,
		indices:  [3]int{i0, i1, i2},
		vertices: verts,
	}
}

// SubDivide calculates the midpoints of the node's triangle and produces four derivative triangles.
func (t *Tree) SubDivide(level int) {
	if len(t.Name) > level {
		return
	}

	i0, i1, i2 := t.indices[0], t.indices[1], t.indices[2]
	v0, v1, v2 := (*t.vertices)[i0], (*t.vertices)[i1], (*t.vertices)[i2]

	w0, _ := v1.Add(v2).Normalized()
	w1, _ := v0.Add(v2).Normalized()
	w2, _ := v0.Add(v1).Normalized()

	*t.vertices = append(*t.vertices, w0, w1, w2)

	l := len(*t.vertices)

	t.T0 = NewTree(t.Name+"0", t.vertices, i0, l-1, l-2)  // v0, w2, w1
	t.T1 = NewTree(t.Name+"1", t.vertices, i1, l-3, l-1)  // v1, w0, w2
	t.T2 = NewTree(t.Name+"2", t.vertices, i2, l-2, l-3)  // v2, w1, w0
	t.T3 = NewTree(t.Name+"3", t.vertices, l-3, l-2, l-1) // w0, w1, w2

	t.T0.SubDivide(level)
	t.T1.SubDivide(level)
	t.T2.SubDivide(level)
	t.T3.SubDivide(level)
}

// CollectIndices appends the current node's indices to the slice pointer unless it should recurse.
func (t *Tree) CollectIndices(indices *[]uint32) {
	if t.T0 == nil {
		*indices = append(*indices, uint32(t.indices[0]), uint32(t.indices[1]), uint32(t.indices[2]))
	} else {
		t.T0.CollectIndices(indices)
		t.T1.CollectIndices(indices)
		t.T2.CollectIndices(indices)
		t.T3.CollectIndices(indices)
	}
}

// Vertices returns a subset of the HTM's vertices that is not intended for
// use with this tree's indices.
func (t *Tree) Vertices() []lmath.Vec3 {
	var indices []uint32
	t.CollectIndices(&indices)

	var vertices []lmath.Vec3
	for _, i := range indices {
		vertices = append(vertices, (*t.vertices)[i])
	}
	return vertices
}

// HTM defines the initial octahedron and allows subdivision nodes.
type HTM struct {
	Vertices *[]lmath.Vec3

	S0, S1, S2, S3 *Tree
	N0, N1, N2, N3 *Tree
}

// New returns an HTM initialized with an initial octahedron.
func New() *HTM {
	verts := []lmath.Vec3{
		{0, 0, 1},
		{1, 0, 0},
		{0, 1, 0},
		{-1, 0, 0},
		{0, -1, 0},
		{0, 0, -1},
	}
	return &HTM{
		Vertices: &verts,

		S0: NewTree("S0", &verts, 1, 5, 2),
		S1: NewTree("S1", &verts, 2, 5, 3),
		S2: NewTree("S2", &verts, 3, 5, 4),
		S3: NewTree("S3", &verts, 4, 5, 1),
		N0: NewTree("N0", &verts, 1, 0, 4),
		N1: NewTree("N1", &verts, 4, 0, 3),
		N2: NewTree("N2", &verts, 3, 0, 2),
		N3: NewTree("N3", &verts, 2, 0, 1),
	}
}

// SubDivide starts a recursion along all root nodes.
func (h *HTM) SubDivide(level int) {
	h.S0.SubDivide(level)
	h.S1.SubDivide(level)
	h.S2.SubDivide(level)
	h.S3.SubDivide(level)
	h.N0.SubDivide(level)
	h.N1.SubDivide(level)
	h.N2.SubDivide(level)
	h.N3.SubDivide(level)
}

// Indices returns a flattened slice of all indices suitable for vertex lookup in native opengl calls.
func (h *HTM) Indices() []uint32 {
	var indices []uint32
	h.S0.CollectIndices(&indices)
	h.S1.CollectIndices(&indices)
	h.S2.CollectIndices(&indices)
	h.S3.CollectIndices(&indices)
	h.N0.CollectIndices(&indices)
	h.N1.CollectIndices(&indices)
	h.N2.CollectIndices(&indices)
	h.N3.CollectIndices(&indices)
	return indices
}

func (h *HTM) TexCoords() []float32 {
	return TexCoords(*h.Vertices)
}

// LookupByCart looks up which triangle a given object belongs to by it's given cartesian coordinates.
func (h *HTM) LookupByCart(v lmath.Vec3) (*Tree, error) {
	sch := Walker(v, h.S0, h.S1, h.S2, h.S3)
	nch := Walker(v, h.N0, h.N1, h.N2, h.N3)

	timeout := time.After(1 * time.Second)

	for sch != nil || nch != nil {
		select {
		case t, ok := <-sch:
			if ok {
				return t, nil
			} else {
				sch = nil
			}
		case t, ok := <-nch:
			if ok {
				return t, nil
			} else {
				nch = nil
			}
		case <-timeout:
			return nil, errors.New("Timed out while walking trees.")
		}
	}

	return nil, errors.New(fmt.Sprintf("Failed to lookup triangle by given cartesian coordinates: %v", v))
}

func Walk(t *Tree, v lmath.Vec3, ch chan *Tree) {
	if t == nil {
		panic("nil tree not allowed during walk.")
	}
	if !PointInside(t, v) {
		return
	}
	if t.T0 == nil {
		ch <- t
	} else {
		Walk(t.T0, v, ch)
		Walk(t.T1, v, ch)
		Walk(t.T2, v, ch)
		Walk(t.T3, v, ch)
	}
}

func Walker(v lmath.Vec3, trees ...*Tree) <-chan *Tree {
	ch := make(chan *Tree)
	go func() {
		for _, t := range trees {
			Walk(t, v, ch)
		}
		close(ch)
	}()
	return ch
}

func PointInside(t *Tree, v lmath.Vec3) bool {
	i0, i1, i2 := t.indices[0], t.indices[1], t.indices[2]
	v0, v1, v2 := (*t.vertices)[i0], (*t.vertices)[i1], (*t.vertices)[i2]
	a := v0.Cross(v1).Dot(v)
	b := v1.Cross(v2).Dot(v)
	c := v2.Cross(v0).Dot(v)
	return a > 0 && b > 0 && c > 0
}
<commit_msg>new intersect types<commit_after>// package htm implements a hierarchical triangular mesh suitable for graphic display and querying.
package htm

import (
	"errors"
	"fmt"
	"time"

	"azul3d.org/lmath.v1"
)

// Tree represents a node in an HTM struct that can contain indices and be subdivided.
type Tree struct {
	Name string

	indices  [3]int
	vertices *[]lmath.Vec3

	T0, T1, T2, T3 *Tree
}

// NewTree returns an initialized node by the given name with the given index values.
func NewTree(name string, verts *[]lmath.Vec3, i0, i1, i2 int) *Tree {
	return &Tree{
		Name:     name,
		indices:  [3]int{i0, i1, i2},
		vertices: verts,
	}
}

func (t *Tree) V0() lmath.Vec3 { return (*t.vertices)[t.indices[0]] }
func (t *Tree) V1() lmath.Vec3 { return (*t.vertices)[t.indices[1]] }
func (t *Tree) V2() lmath.Vec3 { return (*t.vertices)[t.indices[2]] }

// SubDivide calculates the midpoints of the node's triangle and produces four derivative triangles.
func (t *Tree) SubDivide(level int) {
	if len(t.Name) > level {
		return
	}

	i0, i1, i2 := t.indices[0], t.indices[1], t.indices[2]
	v0, v1, v2 := (*t.vertices)[i0], (*t.vertices)[i1], (*t.vertices)[i2]

	w0, _ := v1.Add(v2).Normalized()
	w1, _ := v0.Add(v2).Normalized()
	w2, _ := v0.Add(v1).Normalized()

	*t.vertices = append(*t.vertices, w0, w1, w2)

	l := len(*t.vertices)

	t.T0 = NewTree(t.Name+"0", t.vertices, i0, l-1, l-2)  // v0, w2, w1
	t.T1 = NewTree(t.Name+"1", t.vertices, i1, l-3, l-1)  // v1, w0, w2
	t.T2 = NewTree(t.Name+"2", t.vertices, i2, l-2, l-3)  // v2, w1, w0
	t.T3 = NewTree(t.Name+"3", t.vertices, l-3, l-2, l-1) // w0, w1, w2

	t.T0.SubDivide(level)
	t.T1.SubDivide(level)
	t.T2.SubDivide(level)
	t.T3.SubDivide(level)
}

// CollectIndices appends the current node's indices to the slice pointer unless it should recurse.
func (t *Tree) CollectIndices(indices *[]uint32) {
	if t.T0 == nil {
		*indices = append(*indices, uint32(t.indices[0]), uint32(t.indices[1]), uint32(t.indices[2]))
	} else {
		t.T0.CollectIndices(indices)
		t.T1.CollectIndices(indices)
		t.T2.CollectIndices(indices)
		t.T3.CollectIndices(indices)
	}
}

// Vertices returns a subset of the HTM's vertices that is not intended for
// use with this tree's indices.
func (t *Tree) Vertices() []lmath.Vec3 {
	var indices []uint32
	t.CollectIndices(&indices)

	var vertices []lmath.Vec3
	for _, i := range indices {
		vertices = append(vertices, (*t.vertices)[i])
	}
	return vertices
}

// HTM defines the initial octahedron and allows subdivision nodes.
type HTM struct {
	Vertices *[]lmath.Vec3

	S0, S1, S2, S3 *Tree
	N0, N1, N2, N3 *Tree
}

// New returns an HTM initialized with an initial octahedron.
func New() *HTM {
	verts := []lmath.Vec3{
		{0, 0, 1},
		{1, 0, 0},
		{0, 1, 0},
		{-1, 0, 0},
		{0, -1, 0},
		{0, 0, -1},
	}
	return &HTM{
		Vertices: &verts,

		S0: NewTree("S0", &verts, 1, 5, 2),
		S1: NewTree("S1", &verts, 2, 5, 3),
		S2: NewTree("S2", &verts, 3, 5, 4),
		S3: NewTree("S3", &verts, 4, 5, 1),
		N0: NewTree("N0", &verts, 1, 0, 4),
		N1: NewTree("N1", &verts, 4, 0, 3),
		N2: NewTree("N2", &verts, 3, 0, 2),
		N3: NewTree("N3", &verts, 2, 0, 1),
	}
}

// SubDivide starts a recursion along all root nodes.
func (h *HTM) SubDivide(level int) {
	h.S0.SubDivide(level)
	h.S1.SubDivide(level)
	h.S2.SubDivide(level)
	h.S3.SubDivide(level)
	h.N0.SubDivide(level)
	h.N1.SubDivide(level)
	h.N2.SubDivide(level)
	h.N3.SubDivide(level)
}

// Indices returns a flattened slice of all indices suitable for vertex lookup in native opengl calls.
func (h *HTM) Indices() []uint32 {
	var indices []uint32
	h.S0.CollectIndices(&indices)
	h.S1.CollectIndices(&indices)
	h.S2.CollectIndices(&indices)
	h.S3.CollectIndices(&indices)
	h.N0.CollectIndices(&indices)
	h.N1.CollectIndices(&indices)
	h.N2.CollectIndices(&indices)
	h.N3.CollectIndices(&indices)
	return indices
}

func (h *HTM) TexCoords() []float32 {
	return TexCoords(*h.Vertices)
}

// LookupByCart looks up which triangle a given object belongs to by it's given cartesian coordinates.
func (h *HTM) LookupByCart(v lmath.Vec3) (*Tree, error) {
	sch := Walker(v, h.S0, h.S1, h.S2, h.S3)
	nch := Walker(v, h.N0, h.N1, h.N2, h.N3)

	timeout := time.After(1 * time.Second)

	for sch != nil || nch != nil {
		select {
		case t, ok := <-sch:
			if ok {
				return t, nil
			} else {
				sch = nil
			}
		case t, ok := <-nch:
			if ok {
				return t, nil
			} else {
				nch = nil
			}
		case <-timeout:
			return nil, errors.New("Timed out while walking trees.")
		}
	}

	return nil, errors.New(fmt.Sprintf("Failed to lookup triangle by given cartesian coordinates: %v", v))
}

func Walk(t *Tree, v lmath.Vec3, ch chan *Tree) {
	if t == nil {
		panic("nil tree not allowed during walk.")
	}
	if !PointInside(t, v) {
		return
	}
	if t.T0 == nil {
		ch <- t
	} else {
		Walk(t.T0, v, ch)
		Walk(t.T1, v, ch)
		Walk(t.T2, v, ch)
		Walk(t.T3, v, ch)
	}
}

func Walker(v lmath.Vec3, trees ...*Tree) <-chan *Tree {
	ch := make(chan *Tree)
	go func() {
		for _, t := range trees {
			Walk(t, v, ch)
		}
		close(ch)
	}()
	return ch
}

func Walk2(t *Tree, ch chan *Tree) {
	if t == nil {
		panic("nil tree not allowed during walk.")
	}
	if t.T0 == nil {
		ch <- t
		return
	}

	// TODO(d) alternate walk that returns all trees
	// ch <- t.T0
	// ch <- t.T1
	// ch <- t.T2
	// ch <- t.T3

	Walk2(t.T0, ch)
	Walk2(t.T1, ch)
	Walk2(t.T2, ch)
	Walk2(t.T3, ch)
}

func Walker2(trees ...*Tree) <-chan *Tree {
	ch := make(chan *Tree)
	go func() {
		for _, t := range trees {
			Walk2(t, ch)
		}
		close(ch)
	}()
	return ch
}

func PointInside(t *Tree, v lmath.Vec3) bool {
	i0, i1, i2 := t.indices[0], t.indices[1], t.indices[2]
	v0, v1, v2 := (*t.vertices)[i0], (*t.vertices)[i1], (*t.vertices)[i2]
	a := v0.Cross(v1).Dot(v)
	b := v1.Cross(v2).Dot(v)
	c := v2.Cross(v0).Dot(v)
	return a > 0 && b > 0 && c > 0
}

type Sign int

const (
	Negative Sign = iota
	Zero
	Positive
	Mixed
)

type Coverage int

const (
	Inside Coverage = iota
	Partial
	Outside
)

// Constraint is a circular area, given by the plane slicing it off the sphere.
type Constraint struct {
	P lmath.Vec3
	D float64
}

func (c *Constraint) Test(t *Tree) Coverage {
	a0 := c.P.Dot(t.V0()) > c.D
	a1 := c.P.Dot(t.V1()) > c.D
	a2 := c.P.Dot(t.V2()) > c.D

	if a0 && a1 && a2 {
		return Inside
	} else if a0 || a1 || a2 {
		return Partial
	} else {
		// TODO(d) P center, LookupByCart needed to determine final fate.
		return Outside
	}
}

// Convex is a combination of constraints (logical AND of constraints).
type Convex []*Constraint

func (c Convex) Test(t *Tree) bool {
	for _, cn := range c {
		if cn.Test(t) == Outside {
			return false
		}
	}
	return true
}

func (c Convex) Sign() Sign {
	return Zero
}

// Domain is several convexes (logical OR of convexes).
type Domain []*Convex

func (d Domain) Test(t *Tree) bool {
	for _, cx := range d {
		if cx.Test(t) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2009 Thomas Jager <mail@jager.no>  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package irc

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

const (
	VERSION = "go-ircevent v2.0"
)

func (irc *Connection) readLoop() {
	br := bufio.NewReader(irc.socket)

	for {
		msg, err := br.ReadString('\n')
		if err != nil {
			irc.Error <- err
			break
		}

		irc.lastMessage = time.Now()
		msg = msg[0 : len(msg)-2] //Remove \r\n
		event := &Event{Raw: msg}
		if msg[0] == ':' {
			if i := strings.Index(msg, " "); i > -1 {
				event.Source = msg[1:i]
				msg = msg[i+1 : len(msg)]

			} else {
				irc.log.Printf("Misformed msg from server: %#s\n", msg)
			}

			if i, j := strings.Index(event.Source, "!"), strings.Index(event.Source, "@"); i > -1 && j > -1 {
				event.Nick = event.Source[0:i]
				event.User = event.Source[i+1 : j]
				event.Host = event.Source[j+1 : len(event.Source)]
			}
		}

		args := strings.SplitN(msg, " :", 2)
		if len(args) > 1 {
			event.Message = args[1]
		}

		args = strings.Split(args[0], " ")
		event.Code = strings.ToUpper(args[0])

		if len(args) > 1 {
			event.Arguments = args[1:len(args)]
		}
		/* XXX: len(args) == 0: args should be empty */

		irc.RunCallbacks(event)
	}

	irc.syncreader <- true
}

func (irc *Connection) writeLoop() {
	b, ok := <-irc.pwrite
	for ok {
		if b == "" || irc.socket == nil {
			break
		}
		irc.log.Printf("--> %s\n", b)
		_, err := irc.socket.Write([]byte(b))
		if err != nil {
			irc.log.Printf("%s\n", err)
			irc.Error <- err
			break
		}

		b, ok = <-irc.pwrite
	}
	irc.syncwriter <- true
}

//Pings the server if we have not recived any messages for 5 minutes
func (irc *Connection) pingLoop() {
	irc.ticker = time.NewTicker(1 * time.Minute)   //Tick every minute.
	irc.ticker2 = time.NewTicker(15 * time.Minute) //Tick every 15 minutes.
	for {
		select {
		case <-irc.ticker.C:
			//Ping if we haven't recived anything from the server within 4 minutes
			if time.Since(irc.lastMessage) >= (4 * time.Minute) {
				irc.SendRawf("PING %d", time.Now().UnixNano())
			}
		case <-irc.ticker2.C:
			//Ping every 15 minutes.
			irc.SendRawf("PING %d", time.Now().UnixNano())
			//Try to recapture nickname if it's not as configured.
			if irc.nick != irc.nickcurrent {
				irc.nickcurrent = irc.nick
				irc.SendRawf("NICK %s", irc.nick)
			}
		case <-irc.endping:
			irc.ticker.Stop()
			irc.ticker2.Stop()
			irc.syncpinger <- true
			return
		}
	}
}

func (irc *Connection) Cycle() {
	irc.SendRaw("QUIT")
	irc.Reconnect()
}

func (irc *Connection) Quit() {
	irc.quitting = true
	irc.SendRaw("QUIT")
}

func (irc *Connection) Join(channel string) {
	irc.pwrite <- fmt.Sprintf("JOIN %s\r\n", channel)
}

func (irc *Connection) Part(channel string) {
	irc.pwrite <- fmt.Sprintf("PART %s\r\n", channel)
}

func (irc *Connection) Notice(target, message string) {
	irc.pwrite <- fmt.Sprintf("NOTICE %s :%s\r\n", target, message)
}

func (irc *Connection) Noticef(target, format string, a ...interface{}) {
	irc.Notice(target, fmt.Sprintf(format, a...))
}

func (irc *Connection) Privmsg(target, message string) {
	irc.pwrite <- fmt.Sprintf("PRIVMSG %s :%s\r\n", target, message)
}

func (irc *Connection) Privmsgf(target, format string, a ...interface{}) {
	irc.Privmsg(target, fmt.Sprintf(format, a...))
}

func (irc *Connection) SendRaw(message string) {
	irc.pwrite <- fmt.Sprintf("%s\r\n", message)
}

func (irc *Connection) SendRawf(format string, a ...interface{}) {
	irc.SendRaw(fmt.Sprintf(format, a...))
}

func (irc *Connection) GetNick() string {
	return irc.nickcurrent
}

func (irc *Connection) Reconnect() error {
	close(irc.pwrite)
	close(irc.pread)
	irc.endping <- true
	irc.log.Printf("Syncing Threads\n")
	irc.log.Printf("Syncing Reader\n")
	<-irc.syncreader
	irc.log.Printf("Syncing Writer\n")
	<-irc.syncwriter
	irc.log.Printf("Syncing Pinger\n")
	<-irc.syncpinger
	irc.log.Printf("Syncing Threads Done\n")
	for {
		irc.log.Printf("Reconnecting to %s\n", irc.server)
		var err error
		irc.Connect(irc.server)
		if err == nil {
			break
		}
		irc.log.Printf("Error: %s\n", err)
	}
	return nil
}

func (irc *Connection) Loop() {
	for !irc.quitting {
		e := <-irc.Error
		if irc.quitting {
			break
		}
		irc.log.Printf("Error: %s\n", e)
		irc.Reconnect()
	}

	close(irc.pwrite)
	close(irc.pread)
	irc.endping <- true
	irc.log.Printf("Syncing Threads\n")
	irc.log.Printf("Syncing Reader\n")
	<-irc.syncreader
	irc.log.Printf("Syncing Writer\n")
	<-irc.syncwriter
	irc.log.Printf("Syncing Pinger\n")
	<-irc.syncpinger
	irc.log.Printf("Syncing Threads Done\n")
}

func (irc *Connection) Connect(server string) error {
	irc.server = server
	var err error
	irc.log.Printf("Connecting to %s\n", irc.server)
	if irc.UseTLS {
		irc.socket, err = tls.Dial("tcp", irc.server, irc.TLSConfig)
	} else {
		irc.socket, err = net.Dial("tcp", irc.server)
	}
	if err != nil {
		return err
	}
	irc.log.Printf("Connected to %s (%s)\n", irc.server, irc.socket.RemoteAddr())
	return irc.postConnect()
}

func (irc *Connection) postConnect() error {
	irc.pread = make(chan string, 100)
	irc.pwrite = make(chan string, 100)
	irc.Error = make(chan error, 10)
	irc.syncreader = make(chan bool)
	irc.syncwriter = make(chan bool)
	irc.syncpinger = make(chan bool)
	irc.endping = make(chan bool)
	go irc.readLoop()
	go irc.writeLoop()
	go irc.pingLoop()

	if len(irc.Password) > 0 {
		irc.pwrite <- fmt.Sprintf("PASS %s\r\n", irc.Password)
	}
	irc.pwrite <- fmt.Sprintf("NICK %s\r\n", irc.nick)
	irc.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", irc.user, irc.user)
	return nil
}

func IRC(nick, user string) *Connection {
	irc := new(Connection)
	irc.registered = false
	irc.pread = make(chan string, 100)
	irc.pwrite = make(chan string, 100)
	irc.Error = make(chan error)
	irc.nick = nick
	irc.user = user
	irc.VerboseCallbackHandler = false
	irc.log = log.New(os.Stdout, "", log.LstdFlags)
	irc.setupCallbacks()
	return irc
}
<commit_msg>Add Nick change function<commit_after>// Copyright 2009 Thomas Jager <mail@jager.no>  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package irc

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

const (
	VERSION = "go-ircevent v2.0"
)

func (irc *Connection) readLoop() {
	br := bufio.NewReader(irc.socket)

	for {
		msg, err := br.ReadString('\n')
		if err != nil {
			irc.Error <- err
			break
		}

		irc.lastMessage = time.Now()
		msg = msg[0 : len(msg)-2] //Remove \r\n
		event := &Event{Raw: msg}
		if msg[0] == ':' {
			if i := strings.Index(msg, " "); i > -1 {
				event.Source = msg[1:i]
				msg = msg[i+1 : len(msg)]

			} else {
				irc.log.Printf("Misformed msg from server: %#s\n", msg)
			}

			if i, j := strings.Index(event.Source, "!"), strings.Index(event.Source, "@"); i > -1 && j > -1 {
				event.Nick = event.Source[0:i]
				event.User = event.Source[i+1 : j]
				event.Host = event.Source[j+1 : len(event.Source)]
			}
		}

		args := strings.SplitN(msg, " :", 2)
		if len(args) > 1 {
			event.Message = args[1]
		}

		args = strings.Split(args[0], " ")
		event.Code = strings.ToUpper(args[0])

		if len(args) > 1 {
			event.Arguments = args[1:len(args)]
		}
		/* XXX: len(args) == 0: args should be empty */

		irc.RunCallbacks(event)
	}

	irc.syncreader <- true
}

func (irc *Connection) writeLoop() {
	b, ok := <-irc.pwrite
	for ok {
		if b == "" || irc.socket == nil {
			break
		}
		irc.log.Printf("--> %s\n", b)
		_, err := irc.socket.Write([]byte(b))
		if err != nil {
			irc.log.Printf("%s\n", err)
			irc.Error <- err
			break
		}

		b, ok = <-irc.pwrite
	}
	irc.syncwriter <- true
}

//Pings the server if we have not recived any messages for 5 minutes
func (irc *Connection) pingLoop() {
	irc.ticker = time.NewTicker(1 * time.Minute)   //Tick every minute.
	irc.ticker2 = time.NewTicker(15 * time.Minute) //Tick every 15 minutes.
	for {
		select {
		case <-irc.ticker.C:
			//Ping if we haven't recived anything from the server within 4 minutes
			if time.Since(irc.lastMessage) >= (4 * time.Minute) {
				irc.SendRawf("PING %d", time.Now().UnixNano())
			}
		case <-irc.ticker2.C:
			//Ping every 15 minutes.
			irc.SendRawf("PING %d", time.Now().UnixNano())
			//Try to recapture nickname if it's not as configured.
			if irc.nick != irc.nickcurrent {
				irc.nickcurrent = irc.nick
				irc.SendRawf("NICK %s", irc.nick)
			}
		case <-irc.endping:
			irc.ticker.Stop()
			irc.ticker2.Stop()
			irc.syncpinger <- true
			return
		}
	}
}

func (irc *Connection) Cycle() {
	irc.SendRaw("QUIT")
	irc.Reconnect()
}

func (irc *Connection) Quit() {
	irc.quitting = true
	irc.SendRaw("QUIT")
}

func (irc *Connection) Join(channel string) {
	irc.pwrite <- fmt.Sprintf("JOIN %s\r\n", channel)
}

func (irc *Connection) Part(channel string) {
	irc.pwrite <- fmt.Sprintf("PART %s\r\n", channel)
}

func (irc *Connection) Notice(target, message string) {
	irc.pwrite <- fmt.Sprintf("NOTICE %s :%s\r\n", target, message)
}

func (irc *Connection) Noticef(target, format string, a ...interface{}) {
	irc.Notice(target, fmt.Sprintf(format, a...))
}

func (irc *Connection) Privmsg(target, message string) {
	irc.pwrite <- fmt.Sprintf("PRIVMSG %s :%s\r\n", target, message)
}

func (irc *Connection) Privmsgf(target, format string, a ...interface{}) {
	irc.Privmsg(target, fmt.Sprintf(format, a...))
}

func (irc *Connection) SendRaw(message string) {
	irc.pwrite <- fmt.Sprintf("%s\r\n", message)
}

func (irc *Connection) SendRawf(format string, a ...interface{}) {
	irc.SendRaw(fmt.Sprintf(format, a...))
}

func (irc *Connection) Nick(n string) {
	irc.nick = n
	irc.SendRawf("NICK %s", n)
}

func (irc *Connection) GetNick() string {
	return irc.nickcurrent
}

func (irc *Connection) Reconnect() error {
	close(irc.pwrite)
	close(irc.pread)
	irc.endping <- true
	irc.log.Printf("Syncing Threads\n")
	irc.log.Printf("Syncing Reader\n")
	<-irc.syncreader
	irc.log.Printf("Syncing Writer\n")
	<-irc.syncwriter
	irc.log.Printf("Syncing Pinger\n")
	<-irc.syncpinger
	irc.log.Printf("Syncing Threads Done\n")
	for {
		irc.log.Printf("Reconnecting to %s\n", irc.server)
		var err error
		irc.Connect(irc.server)
		if err == nil {
			break
		}
		irc.log.Printf("Error: %s\n", err)
	}
	return nil
}

func (irc *Connection) Loop() {
	for !irc.quitting {
		e := <-irc.Error
		if irc.quitting {
			break
		}
		irc.log.Printf("Error: %s\n", e)
		irc.Reconnect()
	}

	close(irc.pwrite)
	close(irc.pread)
	irc.endping <- true
	irc.log.Printf("Syncing Threads\n")
	irc.log.Printf("Syncing Reader\n")
	<-irc.syncreader
	irc.log.Printf("Syncing Writer\n")
	<-irc.syncwriter
	irc.log.Printf("Syncing Pinger\n")
	<-irc.syncpinger
	irc.log.Printf("Syncing Threads Done\n")
}

func (irc *Connection) Connect(server string) error {
	irc.server = server
	var err error
	irc.log.Printf("Connecting to %s\n", irc.server)
	if irc.UseTLS {
		irc.socket, err = tls.Dial("tcp", irc.server, irc.TLSConfig)
	} else {
		irc.socket, err = net.Dial("tcp", irc.server)
	}
	if err != nil {
		return err
	}
	irc.log.Printf("Connected to %s (%s)\n", irc.server, irc.socket.RemoteAddr())
	return irc.postConnect()
}

func (irc *Connection) postConnect() error {
	irc.pread = make(chan string, 100)
	irc.pwrite = make(chan string, 100)
	irc.Error = make(chan error, 10)
	irc.syncreader = make(chan bool)
	irc.syncwriter = make(chan bool)
	irc.syncpinger = make(chan bool)
	irc.endping = make(chan bool)
	go irc.readLoop()
	go irc.writeLoop()
	go irc.pingLoop()

	if len(irc.Password) > 0 {
		irc.pwrite <- fmt.Sprintf("PASS %s\r\n", irc.Password)
	}
	irc.pwrite <- fmt.Sprintf("NICK %s\r\n", irc.nick)
	irc.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", irc.user, irc.user)
	return nil
}

func IRC(nick, user string) *Connection {
	irc := new(Connection)
	irc.registered = false
	irc.pread = make(chan string, 100)
	irc.pwrite = make(chan string, 100)
	irc.Error = make(chan error)
	irc.nick = nick
	irc.user = user
	irc.VerboseCallbackHandler = false
	irc.log = log.New(os.Stdout, "", log.LstdFlags)
	irc.setupCallbacks()
	return irc
}
<|endoftext|>


<commit_before>package db

import (
	"strings"
	"testing"

	"github.com/gtfierro/hod/config"
	turtle "github.com/gtfierro/hod/goraptor"
	"github.com/gtfierro/hod/query"
)

func TestDBQuery(t *testing.T) {
	cfg, err := config.ReadConfig("testhodconfig.yaml")
	if err != nil {
		t.Error(err)
		return
	}
	cfg.DBPath = "test_databases/testdb"
	db, err := NewDB(cfg)
	defer db.Close()
	if err != nil {
		t.Error(err)
		return
	}
	for _, test := range []struct {
		query   string
		results []ResultMap
	}{
		{
			"SELECT ?x WHERE { ?x rdf:type brick:Room . };",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#room_1")}},
		},
		{
			"SELECT ?x WHERE { ?x rdf:type <http://buildsys.org/ontologies/Brick#Room> . };",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#room_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds+ ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy+ ?ahu .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds+ ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds? ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy/bf:isFedBy? ?ahu .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds* ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#ahu_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy* ?ahu .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#ahu_1")}},
		},
		{
			"SELECT ?vav ?room WHERE { ?vav rdf:type brick:VAV . ?room rdf:type brick:Room . ?zone rdf:type brick:HVAC_Zone . ?vav bf:feeds+ ?zone . ?room bf:isPartOf ?zone . }; ",
			[]ResultMap{{"?room": turtle.ParseURI("http://buildsys.org/ontologies/building_example#room_1"), "?vav": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?sensor WHERE { ?sensor rdf:type/rdfs:subClassOf* brick:Zone_Temperature_Sensor . };",
			[]ResultMap{{"?sensor": turtle.ParseURI("http://buildsys.org/ontologies/building_example#ztemp_1")}},
		},
		{
			"SELECT ?s ?p WHERE { ?s ?p brick:Zone_Temperature_Sensor . ?s rdfs:subClassOf brick:Zone_Temperature_Sensor . };",
			[]ResultMap{
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Average_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Coldest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Highest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Lowest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Warmest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
			},
		},
	} {
		q, e := query.Parse(strings.NewReader(test.query))
		if e != nil {
			t.Error(test.query, e)
			continue
		}
		result := db.RunQuery(q)
		if !compareResultMapList(test.results, result.Rows) {
			t.Errorf("Results for %s had\n %+v\nexpected\n %+v", test.query, result.Rows, test.results)
			return
		}
	}
}

func TestDBQueryBerkeley(t *testing.T) {
	cfg, err := config.ReadConfig("testhodconfig.yaml")
	if err != nil {
		t.Error(err)
		return
	}
	cfg.DBPath = "test_databases/berkeleytestdb"
	db, err := NewDB(cfg)
	defer db.Close()
	if err != nil {
		t.Error(err)
		return
	}
	for _, test := range []struct {
		query       string
		resultCount int
	}{
		{
			"COUNT ?x WHERE { ?x rdf:type brick:Room . };",
			243,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds ?x .};",
			240,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds+ ?x .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy+ ?ahu .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds ?x .};",
			240,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds+ ?x .};",
			240,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds? ?x .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy/bf:isFedBy? ?ahu .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds* ?x .};",
			485,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy* ?ahu .};",
			485,
		},
		{
			"COUNT ?vav ?room WHERE { ?vav rdf:type brick:VAV . ?room rdf:type brick:Room . ?zone rdf:type brick:HVAC_Zone . ?vav bf:feeds+ ?zone . ?room bf:isPartOf ?zone . }; ",
			243,
		},
		{
			"COUNT ?sensor WHERE { ?sensor rdf:type/rdfs:subClassOf* brick:Zone_Temperature_Sensor . };",
			232,
		},
		{
			"COUNT ?sensor ?room WHERE { ?sensor rdf:type/rdfs:subClassOf* brick:Zone_Temperature_Sensor . ?vav rdf:type brick:VAV . ?zone rdf:type brick:HVAC_Zone . ?room rdf:type brick:Room . ?vav bf:feeds+ ?zone . ?zone bf:hasPart ?room . { ?sensor bf:isPointOf ?vav . OR ?sensor bf:isPointOf ?room .} };",
			232,
		},
	} {
		q, e := query.Parse(strings.NewReader(test.query))
		if e != nil {
			t.Error(test.query, e)
			continue
		}
		result := db.RunQuery(q)
		if result.Count != test.resultCount {
			t.Errorf("Results for %s had %d expected %d", test.query, result.Count, test.resultCount)
			return
		}
	}
}

func BenchmarkQueryPerformance1(b *testing.B) {
	cfg, err := config.ReadConfig("testhodconfig.yaml")
	if err != nil {
		b.Error(err)
		return
	}
	cfg.DBPath = "test_databases/berkeleytestdb"
	db, err := NewDB(cfg)
	defer db.Close()
	if err != nil {
		b.Error(err)
		return
	}
	benchmarks := []struct {
		name  string
		query string
	}{
		{"SimpleSubjectVarTriple", "SELECT ?x WHERE { ?x rdf:type brick:Room . };"},
		{"LongerQuery1", "SELECT ?vav ?room WHERE { ?vav rdf:type brick:VAV . ?room rdf:type brick:Room . ?zone rdf:type brick:HVAC_Zone . ?vav bf:feeds+ ?zone . ?room bf:isPartOf ?zone . }; "},
		{"LooseQuery", "SELECT ?pred ?obj WHERE {   ?vav rdf:type brick:VAV .    ?vav ?pred ?obj .  } ;"},
	}

	for _, bm := range benchmarks {
		b.Run(bm.name, func(b *testing.B) {
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				q, e := query.Parse(strings.NewReader(bm.query))
				if e != nil {
					b.Error(e)
				}
				db.RunQuery(q)
			}
		})
	}
}
<commit_msg>correct the test<commit_after>package db

import (
	"strings"
	"testing"

	"github.com/gtfierro/hod/config"
	turtle "github.com/gtfierro/hod/goraptor"
	"github.com/gtfierro/hod/query"
)

func TestDBQuery(t *testing.T) {
	cfg, err := config.ReadConfig("testhodconfig.yaml")
	if err != nil {
		t.Error(err)
		return
	}
	cfg.DBPath = "test_databases/testdb"
	db, err := NewDB(cfg)
	defer db.Close()
	if err != nil {
		t.Error(err)
		return
	}
	for _, test := range []struct {
		query   string
		results []ResultMap
	}{
		{
			"SELECT ?x WHERE { ?x rdf:type brick:Room . };",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#room_1")}},
		},
		{
			"SELECT ?x WHERE { ?x rdf:type <http://buildsys.org/ontologies/Brick#Room> . };",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#room_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds+ ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy+ ?ahu .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds+ ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds? ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy/bf:isFedBy? ?ahu .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds* ?x .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#ahu_1")}},
		},
		{
			"SELECT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy* ?ahu .};",
			[]ResultMap{{"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#hvaczone_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}, {"?x": turtle.ParseURI("http://buildsys.org/ontologies/building_example#ahu_1")}},
		},
		{
			"SELECT ?vav ?room WHERE { ?vav rdf:type brick:VAV . ?room rdf:type brick:Room . ?zone rdf:type brick:HVAC_Zone . ?vav bf:feeds+ ?zone . ?room bf:isPartOf ?zone . }; ",
			[]ResultMap{{"?room": turtle.ParseURI("http://buildsys.org/ontologies/building_example#room_1"), "?vav": turtle.ParseURI("http://buildsys.org/ontologies/building_example#vav_1")}},
		},
		{
			"SELECT ?sensor WHERE { ?sensor rdf:type/rdfs:subClassOf* brick:Zone_Temperature_Sensor . };",
			[]ResultMap{{"?sensor": turtle.ParseURI("http://buildsys.org/ontologies/building_example#ztemp_1")}},
		},
		{
			"SELECT ?s ?p WHERE { ?s ?p brick:Zone_Temperature_Sensor . ?s rdfs:subClassOf brick:Zone_Temperature_Sensor . };",
			[]ResultMap{
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Average_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Coldest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Highest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Lowest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
				{"?s": turtle.ParseURI("http://buildsys.org/ontologies/Brick#Warmest_Zone_Temperature_Sensor"), "?p": turtle.ParseURI("http://www.w3.org/2000/01/rdf-schema#subClassOf")},
			},
		},
	} {
		q, e := query.Parse(strings.NewReader(test.query))
		if e != nil {
			t.Error(test.query, e)
			continue
		}
		result := db.RunQuery(q)
		if !compareResultMapList(test.results, result.Rows) {
			t.Errorf("Results for %s had\n %+v\nexpected\n %+v", test.query, result.Rows, test.results)
			return
		}
	}
}

func TestDBQueryBerkeley(t *testing.T) {
	cfg, err := config.ReadConfig("testhodconfig.yaml")
	if err != nil {
		t.Error(err)
		return
	}
	cfg.DBPath = "test_databases/berkeleytestdb"
	db, err := NewDB(cfg)
	defer db.Close()
	if err != nil {
		t.Error(err)
		return
	}
	for _, test := range []struct {
		query       string
		resultCount int
	}{
		{
			"COUNT ?x WHERE { ?x rdf:type brick:Room . };",
			243,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds ?x .};",
			240,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds+ ?x .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy+ ?ahu .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds ?x .};",
			240,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds+ ?x .};",
			240,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds/bf:feeds? ?x .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy/bf:isFedBy? ?ahu .};",
			480,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?ahu bf:feeds* ?x .};",
			485,
		},
		{
			"COUNT ?x WHERE { ?ahu rdf:type brick:AHU . ?x bf:isFedBy* ?ahu .};",
			485,
		},
		{
			"COUNT ?vav ?room WHERE { ?vav rdf:type brick:VAV . ?room rdf:type brick:Room . ?zone rdf:type brick:HVAC_Zone . ?vav bf:feeds+ ?zone . ?room bf:isPartOf ?zone . }; ",
			243,
		},
		{
			"COUNT ?sensor WHERE { ?sensor rdf:type/rdfs:subClassOf* brick:Zone_Temperature_Sensor . };",
			232,
		},
		{
			"COUNT ?sensor ?room WHERE { ?sensor rdf:type/rdfs:subClassOf* brick:Zone_Temperature_Sensor . ?vav rdf:type brick:VAV . ?zone rdf:type brick:HVAC_Zone . ?room rdf:type brick:Room . ?vav bf:feeds+ ?zone . ?zone bf:hasPart ?room . { ?sensor bf:isPointOf ?vav . OR ?sensor bf:isPointOf ?room .} };",
			0,
		},
	} {
		q, e := query.Parse(strings.NewReader(test.query))
		if e != nil {
			t.Error(test.query, e)
			continue
		}
		result := db.RunQuery(q)
		if result.Count != test.resultCount {
			t.Errorf("Results for %s had %d expected %d", test.query, result.Count, test.resultCount)
			return
		}
	}
}

func BenchmarkQueryPerformance1(b *testing.B) {
	cfg, err := config.ReadConfig("testhodconfig.yaml")
	if err != nil {
		b.Error(err)
		return
	}
	cfg.DBPath = "test_databases/berkeleytestdb"
	db, err := NewDB(cfg)
	defer db.Close()
	if err != nil {
		b.Error(err)
		return
	}
	benchmarks := []struct {
		name  string
		query string
	}{
		{"SimpleSubjectVarTriple", "SELECT ?x WHERE { ?x rdf:type brick:Room . };"},
		{"LongerQuery1", "SELECT ?vav ?room WHERE { ?vav rdf:type brick:VAV . ?room rdf:type brick:Room . ?zone rdf:type brick:HVAC_Zone . ?vav bf:feeds+ ?zone . ?room bf:isPartOf ?zone . }; "},
		{"LooseQuery", "SELECT ?pred ?obj WHERE {   ?vav rdf:type brick:VAV .    ?vav ?pred ?obj .  } ;"},
	}

	for _, bm := range benchmarks {
		b.Run(bm.name, func(b *testing.B) {
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				q, e := query.Parse(strings.NewReader(bm.query))
				if e != nil {
					b.Error(e)
				}
				db.RunQuery(q)
			}
		})
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"
)

func main() {
	args := os.Args
	if len(args) >= 2 {
		c := strings.Split(args[1], ":")
		if len(c) == 2 {
			ns := c[0]
			cmd := c[1]
			rargs := args[2:]
			switch ns {
			case "create":
				create(cmd, rargs)
			case "db":
				db(cmd, rargs)
			}
		}
	}
}

func create(cmd string, args []string) {
	switch cmd {
	case "migration":
		if len(args) > 0 {
			createMigration(args[0])
		}
	}
}

func createMigration(name string) {
	if name == "" {
		return
	}
	do := func() string {
		dbDir := "migrations"

		err := os.MkdirAll(dbDir, 0777)
		if err != nil {
			return err.Error()
		}
		ts := time.Now().Unix()
		fileName := fmt.Sprintf("%s/%d_%s.go", dbDir, ts, name)
		structName := fmt.Sprintf("%s_%d", name, ts)
		template := fmt.Sprintf(migrationTemplate, structName, structName, structName)
		err = ioutil.WriteFile(fileName, []byte(template), 0644)
		if err != nil {
			return err.Error()
		}
		return fmt.Sprintf("created migration %s", fileName)
	}
	log.Println(do())
}

func db(cmd string, args []string) {
	switch cmd {
	case "migrate":
		dbMigrate()
	}
}

func dbMigrate() {

}

var migrationTemplate = `package migrations

import (
	"github.com/eaigner/hood"
)

type %v struct {}

func (migration *%v) Up(hood *hood.Hood) {
	// implement
}

func (migration *%v) Down(hood *hood.Hood) {
	// implement
}`
<commit_msg>create migrations directory in cwd<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"
)

func main() {
	args := os.Args
	if len(args) >= 2 {
		c := strings.Split(args[1], ":")
		if len(c) == 2 {
			ns := c[0]
			cmd := c[1]
			rargs := args[2:]
			switch ns {
			case "create":
				create(cmd, rargs)
			case "db":
				db(cmd, rargs)
			}
		}
	}
}

func create(cmd string, args []string) {
	switch cmd {
	case "migration":
		if len(args) > 0 {
			createMigration(args[0])
		}
	}
}

func createMigration(name string) {
	if name == "" {
		return
	}
	do := func() string {
		pwd, err := os.Getwd()
		if err != nil {
			return err.Error()
		}
		migrationsDir := pwd + "/migrations"
		err = os.MkdirAll(migrationsDir, 0777)
		if err != nil {
			return err.Error()
		}
		ts := time.Now().Unix()
		fileName := fmt.Sprintf("%s/%d_%s.go", migrationsDir, ts, name)
		structName := fmt.Sprintf("%s_%d", name, ts)
		template := fmt.Sprintf(migrationTemplate, structName, structName, structName)
		err = ioutil.WriteFile(fileName, []byte(template), 0644)
		if err != nil {
			return err.Error()
		}
		return fmt.Sprintf("created migration %s", fileName)
	}
	log.Println(do())
}

func db(cmd string, args []string) {
	switch cmd {
	case "migrate":
		dbMigrate()
	}
}

func dbMigrate() {

}

var migrationTemplate = `package migrations

import (
	"github.com/eaigner/hood"
)

type %v struct {}

func (migration *%v) Up(hood *hood.Hood) {
	// implement
}

func (migration *%v) Down(hood *hood.Hood) {
	// implement
}`
<|endoftext|>


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

package gojwe

import (
	"bytes"
	"compress/flate"
	"crypto"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"strings"
)

type Algorithm string

const (
	ALG_RSA_OAEP     = Algorithm("RSA-OAEP")
	ALG_RSA_OAEP_256 = Algorithm("RSA-OAEP-256")
	ALG_RSA1_5       = Algorithm("RSA1_5")
	ALG_A128KW       = Algorithm("A128KW")
	ALG_A256KW       = Algorithm("A256KW")
)

type EncryptionMethod string

const (
	ENC_A128CBC_HS256_v7 = EncryptionMethod("A128CBC+HS256")
	ENC_A256CBC_HS512_v7 = EncryptionMethod("A256CBC+H512")
	ENC_A128CBC_HS256    = EncryptionMethod("A128CBC-HS256")
	ENC_A256CBC_HS512    = EncryptionMethod("A256CBC-HS512")
	ENC_A128GCM          = EncryptionMethod("A128GCM")
	ENC_A256GCM          = EncryptionMethod("A256GCM")
)

func VerifyAndDecryptDraft7(jwe string, key crypto.PrivateKey) ([]byte, error) {
	return verifyAndDecrypt(7, jwe, key)
}

// Verify and decrypt a JWE object
func VerifyAndDecrypt(jwe string, key crypto.PrivateKey) ([]byte, error) {
	return verifyAndDecrypt(28, jwe, key)
}

func verifyAndDecrypt(draft int, jwe string, key crypto.PrivateKey) ([]byte, error) {
	parts := strings.Split(jwe, ".")
	if len(parts) != 5 {
		return nil, errors.New("Wrong number of parts")
	}

	// decode the JWE header
	var header struct {
		Alg Algorithm        `json:"alg"`
		Enc EncryptionMethod `json:"enc"`
		Zip string           `json:"zip"`
	}
	data, err := safeDecode(parts[0])
	if err != nil {
		return nil, fmt.Errorf("Malformed header: %v", err)
	}
	err = json.Unmarshal(data, &header)
	if err != nil {
		return nil, fmt.Errorf("Failed to decode header: %v", err)
	}

	var encryptionKey []byte
	encryptionKeyData, err := safeDecode(parts[1])
	if err != nil {
		return nil, fmt.Errorf("Malformed encryption key: %v", err)
	}

	// decode the encryption key
	switch header.Alg {
	case ALG_RSA_OAEP, ALG_RSA_OAEP_256:
		rsaKey, ok := key.(*rsa.PrivateKey)
		if !ok {
			return nil, fmt.Errorf("Expected an RSA private key. Got %T", key)
		}

		var h hash.Hash
		if header.Alg == ALG_RSA_OAEP {
			h = sha1.New()
		} else if header.Alg == ALG_RSA_OAEP_256 {
			h = sha256.New()
		} else {
			panic("Logic error with algorithm " + header.Alg)
		}

		encryptionKey, err = rsa.DecryptOAEP(h, rand.Reader, rsaKey, encryptionKeyData, nil)
		if err != nil {
			return nil, fmt.Errorf("Failed to decrypt encryption key: %v", err)
		}

	case ALG_RSA1_5:
		rsaKey, ok := key.(*rsa.PrivateKey)
		if !ok {
			return nil, fmt.Errorf("Expected RSA private key. Got %T", key)
		}

		encryptionKey, err = rsa.DecryptPKCS1v15(rand.Reader, rsaKey, encryptionKeyData)
		if err != nil {
			return nil, fmt.Errorf("Failed to decrypt encryption key: %v", err)
		}

	case ALG_A128KW, ALG_A256KW:
		aesKey, ok := key.([]byte)
		if !ok {
			return nil, fmt.Errorf("Expected shared symmetric key ([]byte). Got %T", key)
		}

		encryptionKey, err = AesKeyUnwrap(aesKey, encryptionKeyData)
		if err != nil {
			return nil, fmt.Errorf("Failed to unwrap key: %v", err)
		}

	default:
		return nil, fmt.Errorf("Unsupported ALG keytype %s", header.Alg)
	}

	// decode IV
	iv, err := safeDecode(parts[2])
	if err != nil {
		return nil, fmt.Errorf("Malformed IV: %v", err)
	}

	// decode cipher text
	cipherText, err := safeDecode(parts[3])
	if err != nil {
		return nil, fmt.Errorf("Malformed cipher text: %v", err)
	}

	// decode authtag
	authTag, err := safeDecode(parts[4])
	if err != nil {
		return nil, fmt.Errorf("Malformed authtag: %v", err)
	}

	// decrypt and verify cipher text
	var plainText []byte

	switch header.Enc {
	case ENC_A128CBC_HS256:
		encKey, macKey := encryptionKey[16:], encryptionKey[:16]

		// verify authtag
		hm := hmac.New(sha256.New, macKey)
		io.WriteString(hm, parts[0])
		hm.Write(iv)
		hm.Write(cipherText)
		var scratch [8]byte
		binary.BigEndian.PutUint64(scratch[:], uint64(len(parts[0]))*8)
		hm.Write(scratch[:])
		signature := hm.Sum(nil)
		signature = signature[:len(signature)/2]
		if !hmac.Equal(authTag, signature) {
			return nil, errors.New("Integrity check failed")
		}

		// decrypt the ciphertext (in-place)
		block, err := aes.NewCipher(encKey)
		if err != nil {
			return nil, fmt.Errorf("Failed to create an AES block cipher: %v", err)
		}

		c := cipher.NewCBCDecrypter(block, iv)
		c.CryptBlocks(cipherText, cipherText)
		plainText = cipherText

		// remove PCKS#7 padding
		padding := int(plainText[len(plainText)-1])
		plainText = plainText[:len(plainText)-padding]

	case ENC_A128CBC_HS256_v7, ENC_A256CBC_HS512_v7:
		// derive keys
		var encSize, macSize int
		var hfunc func() hash.Hash
		if header.Enc == ENC_A128CBC_HS256_v7 {
			encSize, macSize = 128, 256
			hfunc = sha256.New
		} else if header.Enc == ENC_A256CBC_HS512_v7 {
			encSize, macSize = 256, 512
			hfunc = sha512.New
		} else {
			panic("Bad ENC logic for type: " + header.Enc)
		}

		encKey, macKey := concatKDF(encryptionKey, string(header.Enc), encSize, macSize)

		// verify authtag
		hm := hmac.New(hfunc, macKey)
		io.WriteString(hm, parts[0])
		io.WriteString(hm, ".")
		io.WriteString(hm, parts[1])
		io.WriteString(hm, ".")
		io.WriteString(hm, parts[2])
		io.WriteString(hm, ".")
		io.WriteString(hm, parts[3])
		if !hmac.Equal(authTag, hm.Sum(nil)) {
			return nil, errors.New("Integrity check failed")
		}

		// decrpyt ciphertext (in-place)
		block, err := aes.NewCipher(encKey)
		if err != nil {
			return nil, fmt.Errorf("Failed to create an AES block cipher: %v", err)
		}

		c := cipher.NewCBCDecrypter(block, iv)
		c.CryptBlocks(cipherText, cipherText)
		plainText = cipherText

		// remove PCKS#7 padding
		padding := int(plainText[len(plainText)-1])
		plainText = plainText[:len(plainText)-padding]

	case ENC_A128GCM, ENC_A256GCM:
		var additionalData []byte
		if draft < 10 {
			// create the "additional data" for the GCM cipher
			buffer := new(bytes.Buffer)
			buffer.WriteString(parts[0])
			buffer.WriteRune('.')
			buffer.WriteString(parts[1])
			if draft < 9 {
				buffer.WriteRune('.')
				buffer.WriteString(parts[2])
			}
			additionalData = buffer.Bytes()
		} else {
			additionalData = []byte(parts[0])
		}

		// create the authenticating cipher
		block, err := aes.NewCipher(encryptionKey)
		if err != nil {
			return nil, fmt.Errorf("Failed to create an AES block cipher: %v", err)
		}
		c, err := cipher.NewGCM(block)
		if err != nil {
			return nil, fmt.Errorf("Failed to create GCM cipher: %v", err)
		}

		// decrypt the cipher text (in-place)
		_, err = c.Open(cipherText[:0], iv, append(cipherText, authTag...), additionalData)
		if err != nil {
			return nil, fmt.Errorf("Failed to decrypt: %v", err)
		}
		plainText = cipherText

	default:
		return nil, fmt.Errorf("Unsupported ENC keytype %s", header.Enc)
	}

	// need to deflate plain text?
	if header.Zip == "DEF" {
		plainText, err = ioutil.ReadAll(flate.NewReader(bytes.NewReader(plainText)))
		if err != nil {
			return nil, fmt.Errorf("Failed to inflate plain text: %v", err)
		}
	}

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

package gojwe

import (
	"bytes"
	"compress/flate"
	"crypto"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"strings"
)

type Algorithm string

const (
	ALG_RSA_OAEP     = Algorithm("RSA-OAEP")
	ALG_RSA_OAEP_256 = Algorithm("RSA-OAEP-256")
	ALG_RSA1_5       = Algorithm("RSA1_5")
	ALG_A128KW       = Algorithm("A128KW")
	ALG_A256KW       = Algorithm("A256KW")
)

type EncryptionMethod string

const (
	ENC_A128CBC_HS256_v7 = EncryptionMethod("A128CBC+HS256")
	ENC_A256CBC_HS512_v7 = EncryptionMethod("A256CBC+H512")
	ENC_A128CBC_HS256    = EncryptionMethod("A128CBC-HS256")
	ENC_A256CBC_HS512    = EncryptionMethod("A256CBC-HS512")
	ENC_A128GCM          = EncryptionMethod("A128GCM")
	ENC_A256GCM          = EncryptionMethod("A256GCM")
)

func VerifyAndDecryptDraft7(jwe string, key crypto.PrivateKey) ([]byte, error) {
	return verifyAndDecrypt(7, jwe, key)
}

// Verify and decrypt a JWE object
func VerifyAndDecrypt(jwe string, key crypto.PrivateKey) ([]byte, error) {
	return verifyAndDecrypt(28, jwe, key)
}

func verifyAndDecrypt(draft int, jwe string, key crypto.PrivateKey) ([]byte, error) {
	parts := strings.Split(jwe, ".")
	if len(parts) != 5 {
		return nil, errors.New("Wrong number of parts")
	}

	// decode the JWE header
	var header struct {
		Alg Algorithm        `json:"alg"`
		Enc EncryptionMethod `json:"enc"`
		Zip string           `json:"zip"`
	}
	data, err := safeDecode(parts[0])
	if err != nil {
		return nil, fmt.Errorf("Malformed header: %v", err)
	}
	err = json.Unmarshal(data, &header)
	if err != nil {
		return nil, fmt.Errorf("Failed to decode header: %v", err)
	}

	var encryptionKey []byte
	encryptionKeyData, err := safeDecode(parts[1])
	if err != nil {
		return nil, fmt.Errorf("Malformed encryption key: %v", err)
	}

	// decode the encryption key
	switch header.Alg {
	case ALG_RSA_OAEP, ALG_RSA_OAEP_256:
		rsaKey, ok := key.(*rsa.PrivateKey)
		if !ok {
			return nil, fmt.Errorf("Expected an RSA private key. Got %T", key)
		}

		var h hash.Hash
		if header.Alg == ALG_RSA_OAEP {
			h = sha1.New()
		} else if header.Alg == ALG_RSA_OAEP_256 {
			h = sha256.New()
		} else {
			panic("Logic error with algorithm " + header.Alg)
		}

		encryptionKey, err = rsa.DecryptOAEP(h, rand.Reader, rsaKey, encryptionKeyData, nil)
		if err != nil {
			return nil, fmt.Errorf("Failed to decrypt encryption key: %v", err)
		}

	case ALG_RSA1_5:
		rsaKey, ok := key.(*rsa.PrivateKey)
		if !ok {
			return nil, fmt.Errorf("Expected RSA private key. Got %T", key)
		}

		encryptionKey, err = rsa.DecryptPKCS1v15(rand.Reader, rsaKey, encryptionKeyData)
		if err != nil {
			return nil, fmt.Errorf("Failed to decrypt encryption key: %v", err)
		}

	case ALG_A128KW, ALG_A256KW:
		aesKey, ok := key.([]byte)
		if !ok {
			return nil, fmt.Errorf("Expected shared symmetric key ([]byte). Got %T", key)
		}

		encryptionKey, err = AesKeyUnwrap(aesKey, encryptionKeyData)
		if err != nil {
			return nil, fmt.Errorf("Failed to unwrap key: %v", err)
		}

	default:
		return nil, fmt.Errorf("Unsupported ALG keytype %s", header.Alg)
	}

	// decode IV
	iv, err := safeDecode(parts[2])
	if err != nil {
		return nil, fmt.Errorf("Malformed IV: %v", err)
	}

	// decode cipher text
	cipherText, err := safeDecode(parts[3])
	if err != nil {
		return nil, fmt.Errorf("Malformed cipher text: %v", err)
	}

	// decode authtag
	authTag, err := safeDecode(parts[4])
	if err != nil {
		return nil, fmt.Errorf("Malformed authtag: %v", err)
	}

	// decrypt and verify cipher text
	var plainText []byte

	switch header.Enc {
	case ENC_A128CBC_HS256, ENC_A256CBC_HS512:
		var encKey, macKey []byte
		var hfunc func() hash.Hash
		if header.Enc == ENC_A128CBC_HS256 {
			encKey, macKey = encryptionKey[16:], encryptionKey[:16]
			hfunc = sha256.New
		} else if header.Enc == ENC_A256CBC_HS512 {
			encKey, macKey = encryptionKey[32:], encryptionKey[:32]
			hfunc = sha512.New
		} else {
			panic("Bad ENC logic for " + header.Enc)
		}

		// verify authtag
		hm := hmac.New(hfunc, macKey)
		io.WriteString(hm, parts[0])
		hm.Write(iv)
		hm.Write(cipherText)
		var scratch [8]byte
		binary.BigEndian.PutUint64(scratch[:], uint64(len(parts[0]))*8)
		hm.Write(scratch[:])
		signature := hm.Sum(nil)
		signature = signature[:len(signature)/2]
		if !hmac.Equal(authTag, signature) {
			return nil, errors.New("Integrity check failed")
		}

		// decrypt the ciphertext (in-place)
		block, err := aes.NewCipher(encKey)
		if err != nil {
			return nil, fmt.Errorf("Failed to create an AES block cipher: %v", err)
		}

		c := cipher.NewCBCDecrypter(block, iv)
		c.CryptBlocks(cipherText, cipherText)
		plainText = cipherText

		// remove PCKS#7 padding
		padding := int(plainText[len(plainText)-1])
		plainText = plainText[:len(plainText)-padding]

	case ENC_A128CBC_HS256_v7, ENC_A256CBC_HS512_v7:
		// derive keys
		var encSize, macSize int
		var hfunc func() hash.Hash
		if header.Enc == ENC_A128CBC_HS256_v7 {
			encSize, macSize = 128, 256
			hfunc = sha256.New
		} else if header.Enc == ENC_A256CBC_HS512_v7 {
			encSize, macSize = 256, 512
			hfunc = sha512.New
		} else {
			panic("Bad ENC logic for type: " + header.Enc)
		}

		encKey, macKey := concatKDF(encryptionKey, string(header.Enc), encSize, macSize)

		// verify authtag
		hm := hmac.New(hfunc, macKey)
		io.WriteString(hm, parts[0])
		io.WriteString(hm, ".")
		io.WriteString(hm, parts[1])
		io.WriteString(hm, ".")
		io.WriteString(hm, parts[2])
		io.WriteString(hm, ".")
		io.WriteString(hm, parts[3])
		if !hmac.Equal(authTag, hm.Sum(nil)) {
			return nil, errors.New("Integrity check failed")
		}

		// decrpyt ciphertext (in-place)
		block, err := aes.NewCipher(encKey)
		if err != nil {
			return nil, fmt.Errorf("Failed to create an AES block cipher: %v", err)
		}

		c := cipher.NewCBCDecrypter(block, iv)
		c.CryptBlocks(cipherText, cipherText)
		plainText = cipherText

		// remove PCKS#7 padding
		padding := int(plainText[len(plainText)-1])
		plainText = plainText[:len(plainText)-padding]

	case ENC_A128GCM, ENC_A256GCM:
		var additionalData []byte
		if draft < 10 {
			// create the "additional data" for the GCM cipher
			buffer := new(bytes.Buffer)
			buffer.WriteString(parts[0])
			buffer.WriteRune('.')
			buffer.WriteString(parts[1])
			if draft < 9 {
				buffer.WriteRune('.')
				buffer.WriteString(parts[2])
			}
			additionalData = buffer.Bytes()
		} else {
			additionalData = []byte(parts[0])
		}

		// create the authenticating cipher
		block, err := aes.NewCipher(encryptionKey)
		if err != nil {
			return nil, fmt.Errorf("Failed to create an AES block cipher: %v", err)
		}
		c, err := cipher.NewGCM(block)
		if err != nil {
			return nil, fmt.Errorf("Failed to create GCM cipher: %v", err)
		}

		// decrypt the cipher text (in-place)
		_, err = c.Open(cipherText[:0], iv, append(cipherText, authTag...), additionalData)
		if err != nil {
			return nil, fmt.Errorf("Failed to decrypt: %v", err)
		}
		plainText = cipherText

	default:
		return nil, fmt.Errorf("Unsupported ENC keytype %s", header.Enc)
	}

	// need to deflate plain text?
	if header.Zip == "DEF" {
		plainText, err = ioutil.ReadAll(flate.NewReader(bytes.NewReader(plainText)))
		if err != nil {
			return nil, fmt.Errorf("Failed to inflate plain text: %v", err)
		}
	}

	return plainText, nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"encoding/json"
	"strconv"

	"github.com/boltdb/bolt"
)

type bTrack struct {
	//AlbumArtist    string
	DiscNumber     uint8
	TrackNumber    uint8
	DurationMillis string
	EstimatedSize  string
	ID             string
	PlayCount      uint32
	Title          string
	Year           int
}

func refreshLibrary() {
	//db, err := bolt.Open(fullDbPath(), 0600, nil)
	//checkErr(err)
	//defer db.Close()

	tracks, err := gm.ListTracks()
	checkErr(err)
	err = db.Update(func(tx *bolt.Tx) error {
		tx.DeleteBucket([]byte("Library"))

		lib, err := tx.CreateBucketIfNotExists([]byte("Library"))
		checkErr(err)
		for _, t := range tracks {
			artist, err := lib.CreateBucketIfNotExists([]byte(t.Artist))
			checkErr(err)
			if t.Album == "" {
				t.Album = "Unknown Album"
			}
			album, err := artist.CreateBucketIfNotExists([]byte(t.Album))
			checkErr(err)

			//id, _ := album.NextSequence()

			bt := bTrack{t.DiscNumber, t.TrackNumber, t.DurationMillis,
				t.EstimatedSize, t.ID, t.PlayCount, t.Title, t.Year}
			//trackNumber, _ := album.NextSequence()
			buf, err := json.Marshal(bt)
			checkErr(err)
			var key string
			if t.TrackNumber < 10 {
				key = strconv.Itoa(int(t.DiscNumber)) + "0" + strconv.Itoa(int(t.TrackNumber))
			} else {
				key = strconv.Itoa(int(t.DiscNumber)) + strconv.Itoa(int(t.TrackNumber))
			}

			err = album.Put([]byte(key), buf)
			checkErr(err)

		}

		return nil
	})

}

func itob(v uint64) []byte {
	b := make([]byte, 2)
	binary.BigEndian.PutUint16(b, uint16(v))
	return b
}
<commit_msg>Fix types<commit_after>package main

import (
	"encoding/binary"
	"encoding/json"
	"strconv"

	"github.com/boltdb/bolt"
)

type bTrack struct {
	//AlbumArtist    string
	DiscNumber     float64 //uint8
	TrackNumber    float64 //uint8
	DurationMillis string
	EstimatedSize  string
	ID             string
	PlayCount      float64
	Title          string
	Year           float64
}

func refreshLibrary() {
	//db, err := bolt.Open(fullDbPath(), 0600, nil)
	//checkErr(err)
	//defer db.Close()

	tracks, err := gm.ListTracks()
	checkErr(err)
	err = db.Update(func(tx *bolt.Tx) error {
		tx.DeleteBucket([]byte("Library"))

		lib, err := tx.CreateBucketIfNotExists([]byte("Library"))
		checkErr(err)
		for _, t := range tracks {
			artist, err := lib.CreateBucketIfNotExists([]byte(t.Artist))
			checkErr(err)
			if t.Album == "" {
				t.Album = "Unknown Album"
			}
			album, err := artist.CreateBucketIfNotExists([]byte(t.Album))
			checkErr(err)

			//id, _ := album.NextSequence()

			bt := bTrack{t.DiscNumber, t.TrackNumber, t.DurationMillis,
				t.EstimatedSize, t.ID, t.PlayCount, t.Title, t.Year}
			//trackNumber, _ := album.NextSequence()
			buf, err := json.Marshal(bt)
			checkErr(err)
			var key string
			if t.TrackNumber < 10 {
				key = strconv.Itoa(int(t.DiscNumber)) + "0" + strconv.Itoa(int(t.TrackNumber))
			} else {
				key = strconv.Itoa(int(t.DiscNumber)) + strconv.Itoa(int(t.TrackNumber))
			}

			err = album.Put([]byte(key), buf)
			checkErr(err)

		}

		return nil
	})

}

func itob(v uint64) []byte {
	b := make([]byte, 2)
	binary.BigEndian.PutUint16(b, uint16(v))
	return b
}
<|endoftext|>


<commit_before>package log

import (
	"errors"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
	"sync/atomic"
)

var pid = os.Getpid()
var currentSeverity Severity

// Severity implementation is borrowed from glog, uses sync/atomic int32
type Severity int32

const (
	SeverityInfo Severity = iota
	SeverityWarn
	SeverityError
	SeverityFatal
)

var severityName = map[Severity]string{
	SeverityInfo:  "INFO",
	SeverityWarn:  "WARN",
	SeverityError: "ERROR",
	SeverityFatal: "FATAL",
}

// get returns the value of the severity.
func (s *Severity) Get() Severity {
	return Severity(atomic.LoadInt32((*int32)(s)))
}

// set sets the value of the severity.
func (s *Severity) Set(val Severity) {
	atomic.StoreInt32((*int32)(s), int32(val))
}

// less returns if this severity is greater than passed severity
func (s *Severity) Gt(val Severity) bool {
	return s.Get() > val
}

func (s Severity) String() string {
	n, ok := severityName[s]
	if !ok {
		return "UNKNOWN SEVERITY"
	}
	return n
}

func SeverityFromString(s string) (Severity, error) {
	s = strings.ToUpper(s)
	for k, val := range severityName {
		if val == s {
			return k, nil
		}
	}
	return -1, fmt.Errorf("unsupported severity: %s", s)
}

// Logger is a unified interface for all loggers.
type Logger interface {
	Infof(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})

	Writer(Severity) io.Writer
}

// Logging configuration to be passed to all loggers during initialization.
type LogConfig struct {
	Name string
}

func (c LogConfig) String() string {
	return fmt.Sprintf("LogConfig(Name=%v)", c.Name)
}

// SetSeverity sets current logging severity. Acceptable values are SeverityInfo, SeverityWarn, SeverityError, SeverityFatal
func SetSeverity(s Severity) {
	currentSeverity.Set(s)
}

// GetSeverity returns currently set severity.
func GetSeverity() Severity {
	return currentSeverity
}

// Logging initialization, must be called at the beginning of your cool app.
func Init(logConfigs []*LogConfig) error {
	for _, config := range logConfigs {
		l, err := NewLogger(config)
		if err != nil {
			return err
		}
		logger.add(l)
	}
	return nil
}

// Make a proper logger from a given configuration.
func NewLogger(config *LogConfig) (Logger, error) {
	switch config.Name {
	case "console":
		return NewConsoleLogger(config)
	case "syslog":
		return NewSysLogger(config)
	}
	return nil, errors.New(fmt.Sprintf("Unknown logger: %v", config))
}

// GetLogger returns global logger
func GetLogger() Logger {
	return logger
}

// Infof logs to the INFO log.
func Infof(format string, args ...interface{}) {
	infof(1, logger.info, format, args...)
}

// Warningf logs to the WARNING and INFO logs.
func Warningf(format string, args ...interface{}) {
	warningf(1, logger.warn, format, args...)
}

// Errorf logs to the ERROR, WARNING, and INFO logs.
func Errorf(format string, args ...interface{}) {
	errorf(1, logger.warn, format, args...)
}

// Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
// including a stack trace of all running goroutines, then calls os.Exit(255).
func Fatalf(format string, args ...interface{}) {
	fatalf(1, logger.fatal, format, args...)
}

func infof(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityInfo) {
		return
	}
	writeMessage(depth+1, w, SeverityInfo, format, args...)
}

func warningf(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityWarn) {
		return
	}
	writeMessage(depth+1, w, SeverityWarn, format, args...)
}

func errorf(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityError) {
		return
	}
	writeMessage(depth+1, w, SeverityError, format, args...)
}

func fatalf(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityFatal) {
		return
	}
	writeMessage(depth+1, w, SeverityFatal, format, args...)
	stacks := stackTraces()
	io.WriteString(w, stacks)
}

func writeMessage(depth int, w io.Writer, sev Severity, format string, args ...interface{}) {
	file, line := callerInfo(depth + 1)
	io.WriteString(w, fmt.Sprintf("%s PID:%d [%s:%d] %s", sev, pid, file, line, fmt.Sprintf(format, args...)))
}

// Return stack traces of all the running goroutines.
func stackTraces() string {
	trace := make([]byte, 100000)
	nbytes := runtime.Stack(trace, true)
	return string(trace[:nbytes])
}

// Return a file name and a line number.
func callerInfo(depth int) (string, int) {
	_, file, line, ok := runtimeCaller(depth + 1) // number of frames to the user's call.

	if !ok {
		file = "unknown"
		line = 0
	} else {
		slashPosition := strings.LastIndex(file, "/")
		if slashPosition >= 0 {
			file = file[slashPosition+1:]
		}
	}

	return file, line
}

// runtime functions for mocking
var runtimeCaller = runtime.Caller

var exit = func() {
	os.Exit(255)
}
<commit_msg>Errorf must use err writer<commit_after>package log

import (
	"errors"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
	"sync/atomic"
)

var pid = os.Getpid()
var currentSeverity Severity

// Severity implementation is borrowed from glog, uses sync/atomic int32
type Severity int32

const (
	SeverityInfo Severity = iota
	SeverityWarn
	SeverityError
	SeverityFatal
)

var severityName = map[Severity]string{
	SeverityInfo:  "INFO",
	SeverityWarn:  "WARN",
	SeverityError: "ERROR",
	SeverityFatal: "FATAL",
}

// get returns the value of the severity.
func (s *Severity) Get() Severity {
	return Severity(atomic.LoadInt32((*int32)(s)))
}

// set sets the value of the severity.
func (s *Severity) Set(val Severity) {
	atomic.StoreInt32((*int32)(s), int32(val))
}

// less returns if this severity is greater than passed severity
func (s *Severity) Gt(val Severity) bool {
	return s.Get() > val
}

func (s Severity) String() string {
	n, ok := severityName[s]
	if !ok {
		return "UNKNOWN SEVERITY"
	}
	return n
}

func SeverityFromString(s string) (Severity, error) {
	s = strings.ToUpper(s)
	for k, val := range severityName {
		if val == s {
			return k, nil
		}
	}
	return -1, fmt.Errorf("unsupported severity: %s", s)
}

// Logger is a unified interface for all loggers.
type Logger interface {
	Infof(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})

	Writer(Severity) io.Writer
}

// Logging configuration to be passed to all loggers during initialization.
type LogConfig struct {
	Name string
}

func (c LogConfig) String() string {
	return fmt.Sprintf("LogConfig(Name=%v)", c.Name)
}

// SetSeverity sets current logging severity. Acceptable values are SeverityInfo, SeverityWarn, SeverityError, SeverityFatal
func SetSeverity(s Severity) {
	currentSeverity.Set(s)
}

// GetSeverity returns currently set severity.
func GetSeverity() Severity {
	return currentSeverity
}

// Logging initialization, must be called at the beginning of your cool app.
func Init(logConfigs []*LogConfig) error {
	for _, config := range logConfigs {
		l, err := NewLogger(config)
		if err != nil {
			return err
		}
		logger.add(l)
	}
	return nil
}

// Make a proper logger from a given configuration.
func NewLogger(config *LogConfig) (Logger, error) {
	switch config.Name {
	case "console":
		return NewConsoleLogger(config)
	case "syslog":
		return NewSysLogger(config)
	}
	return nil, errors.New(fmt.Sprintf("Unknown logger: %v", config))
}

// GetLogger returns global logger
func GetLogger() Logger {
	return logger
}

// Infof logs to the INFO log.
func Infof(format string, args ...interface{}) {
	infof(1, logger.info, format, args...)
}

// Warningf logs to the WARNING and INFO logs.
func Warningf(format string, args ...interface{}) {
	warningf(1, logger.warn, format, args...)
}

// Errorf logs to the ERROR, WARNING, and INFO logs.
func Errorf(format string, args ...interface{}) {
	errorf(1, logger.err, format, args...)
}

// Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
// including a stack trace of all running goroutines, then calls os.Exit(255).
func Fatalf(format string, args ...interface{}) {
	fatalf(1, logger.fatal, format, args...)
}

func infof(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityInfo) {
		return
	}
	writeMessage(depth+1, w, SeverityInfo, format, args...)
}

func warningf(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityWarn) {
		return
	}
	writeMessage(depth+1, w, SeverityWarn, format, args...)
}

func errorf(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityError) {
		return
	}
	writeMessage(depth+1, w, SeverityError, format, args...)
}

func fatalf(depth int, w io.Writer, format string, args ...interface{}) {
	if currentSeverity.Gt(SeverityFatal) {
		return
	}
	writeMessage(depth+1, w, SeverityFatal, format, args...)
	stacks := stackTraces()
	io.WriteString(w, stacks)
}

func writeMessage(depth int, w io.Writer, sev Severity, format string, args ...interface{}) {
	file, line := callerInfo(depth + 1)
	io.WriteString(w, fmt.Sprintf("%s PID:%d [%s:%d] %s", sev, pid, file, line, fmt.Sprintf(format, args...)))
}

// Return stack traces of all the running goroutines.
func stackTraces() string {
	trace := make([]byte, 100000)
	nbytes := runtime.Stack(trace, true)
	return string(trace[:nbytes])
}

// Return a file name and a line number.
func callerInfo(depth int) (string, int) {
	_, file, line, ok := runtimeCaller(depth + 1) // number of frames to the user's call.

	if !ok {
		file = "unknown"
		line = 0
	} else {
		slashPosition := strings.LastIndex(file, "/")
		if slashPosition >= 0 {
			file = file[slashPosition+1:]
		}
	}

	return file, line
}

// runtime functions for mocking
var runtimeCaller = runtime.Caller

var exit = func() {
	os.Exit(255)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/btcsuite/btcd/connmgr"
	"github.com/btcsuite/btclog"
	"github.com/jrick/logrotate/rotator"
	"github.com/lightninglabs/neutrino"

	"github.com/lightningnetwork/lightning-onion"
	"github.com/lightningnetwork/lnd/autopilot"
	"github.com/lightningnetwork/lnd/build"
	"github.com/lightningnetwork/lnd/chainntnfs"
	"github.com/lightningnetwork/lnd/channeldb"
	"github.com/lightningnetwork/lnd/contractcourt"
	"github.com/lightningnetwork/lnd/discovery"
	"github.com/lightningnetwork/lnd/htlcswitch"
	"github.com/lightningnetwork/lnd/lnrpc/signrpc"
	"github.com/lightningnetwork/lnd/lnwallet"
	"github.com/lightningnetwork/lnd/routing"
	"github.com/lightningnetwork/lnd/signal"
	"github.com/lightningnetwork/lnd/sweep"
)

// Loggers per subsystem.  A single backend logger is created and all subsystem
// loggers created from it will write to the backend.  When adding new
// subsystems, add the subsystem logger variable here and to the
// subsystemLoggers map.
//
// Loggers can not be used before the log rotator has been initialized with a
// log file.  This must be performed early during application startup by
// calling initLogRotator.
var (
	logWriter = &build.LogWriter{}

	// backendLog is the logging backend used to create all subsystem
	// loggers.  The backend must not be used before the log rotator has
	// been initialized, or data races and/or nil pointer dereferences will
	// occur.
	backendLog = btclog.NewBackend(logWriter)

	// logRotator is one of the logging outputs.  It should be closed on
	// application shutdown.
	logRotator *rotator.Rotator

	ltndLog = build.NewSubLogger("LTND", backendLog.Logger)
	lnwlLog = build.NewSubLogger("LNWL", backendLog.Logger)
	peerLog = build.NewSubLogger("PEER", backendLog.Logger)
	discLog = build.NewSubLogger("DISC", backendLog.Logger)
	rpcsLog = build.NewSubLogger("RPCS", backendLog.Logger)
	srvrLog = build.NewSubLogger("SRVR", backendLog.Logger)
	ntfnLog = build.NewSubLogger("NTFN", backendLog.Logger)
	chdbLog = build.NewSubLogger("CHDB", backendLog.Logger)
	fndgLog = build.NewSubLogger("FNDG", backendLog.Logger)
	hswcLog = build.NewSubLogger("HSWC", backendLog.Logger)
	utxnLog = build.NewSubLogger("UTXN", backendLog.Logger)
	brarLog = build.NewSubLogger("BRAR", backendLog.Logger)
	cmgrLog = build.NewSubLogger("CMGR", backendLog.Logger)
	crtrLog = build.NewSubLogger("CRTR", backendLog.Logger)
	btcnLog = build.NewSubLogger("BTCN", backendLog.Logger)
	atplLog = build.NewSubLogger("ATPL", backendLog.Logger)
	cnctLog = build.NewSubLogger("CNCT", backendLog.Logger)
	sphxLog = build.NewSubLogger("SPHX", backendLog.Logger)
	swprLog = build.NewSubLogger("SWPR", backendLog.Logger)
	sgnrLog = build.NewSubLogger("SGNR", backendLog.Logger)
)

// Initialize package-global logger variables.
func init() {
	lnwallet.UseLogger(lnwlLog)
	discovery.UseLogger(discLog)
	chainntnfs.UseLogger(ntfnLog)
	channeldb.UseLogger(chdbLog)
	htlcswitch.UseLogger(hswcLog)
	connmgr.UseLogger(cmgrLog)
	routing.UseLogger(crtrLog)
	neutrino.UseLogger(btcnLog)
	autopilot.UseLogger(atplLog)
	contractcourt.UseLogger(cnctLog)
	sphinx.UseLogger(sphxLog)
	signal.UseLogger(ltndLog)
	sweep.UseLogger(swprLog)
	signrpc.UseLogger(sgnrLog)
}

// subsystemLoggers maps each subsystem identifier to its associated logger.
var subsystemLoggers = map[string]btclog.Logger{
	"LTND": ltndLog,
	"LNWL": lnwlLog,
	"PEER": peerLog,
	"DISC": discLog,
	"RPCS": rpcsLog,
	"SRVR": srvrLog,
	"NTFN": ntfnLog,
	"CHDB": chdbLog,
	"FNDG": fndgLog,
	"HSWC": hswcLog,
	"UTXN": utxnLog,
	"BRAR": brarLog,
	"CMGR": cmgrLog,
	"CRTR": crtrLog,
	"BTCN": btcnLog,
	"ATPL": atplLog,
	"CNCT": cnctLog,
	"SPHX": sphxLog,
	"SWPR": swprLog,
	"SGNR": sgnrLog,
}

// initLogRotator initializes the logging rotator to write logs to logFile and
// create roll files in the same directory.  It must be called before the
// package-global log rotator variables are used.
func initLogRotator(logFile string, MaxLogFileSize int, MaxLogFiles int) {
	logDir, _ := filepath.Split(logFile)
	err := os.MkdirAll(logDir, 0700)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
		os.Exit(1)
	}
	r, err := rotator.New(logFile, int64(MaxLogFileSize*1024), false, MaxLogFiles)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
		os.Exit(1)
	}

	pr, pw := io.Pipe()
	go r.Run(pr)

	logWriter.RotatorPipe = pw
	logRotator = r
}

// setLogLevel sets the logging level for provided subsystem.  Invalid
// subsystems are ignored.  Uninitialized subsystems are dynamically created as
// needed.
func setLogLevel(subsystemID string, logLevel string) {
	// Ignore invalid subsystems.
	logger, ok := subsystemLoggers[subsystemID]
	if !ok {
		return
	}

	// Defaults to info if the log level is invalid.
	level, _ := btclog.LevelFromString(logLevel)
	logger.SetLevel(level)
}

// setLogLevels sets the log level for all subsystem loggers to the passed
// level. It also dynamically creates the subsystem loggers as needed, so it
// can be used to initialize the logging system.
func setLogLevels(logLevel string) {
	// Configure all sub-systems with the new logging level.  Dynamically
	// create loggers as needed.
	for subsystemID := range subsystemLoggers {
		setLogLevel(subsystemID, logLevel)
	}
}

// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string

// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
	return c()
}

// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
	return logClosure(c)
}
<commit_msg>log: wire up the new WalletKit logger<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/btcsuite/btcd/connmgr"
	"github.com/btcsuite/btclog"
	"github.com/jrick/logrotate/rotator"
	"github.com/lightninglabs/neutrino"

	"github.com/lightningnetwork/lightning-onion"
	"github.com/lightningnetwork/lnd/autopilot"
	"github.com/lightningnetwork/lnd/build"
	"github.com/lightningnetwork/lnd/chainntnfs"
	"github.com/lightningnetwork/lnd/channeldb"
	"github.com/lightningnetwork/lnd/contractcourt"
	"github.com/lightningnetwork/lnd/discovery"
	"github.com/lightningnetwork/lnd/htlcswitch"
	"github.com/lightningnetwork/lnd/lnrpc/signrpc"
	"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
	"github.com/lightningnetwork/lnd/lnwallet"
	"github.com/lightningnetwork/lnd/routing"
	"github.com/lightningnetwork/lnd/signal"
	"github.com/lightningnetwork/lnd/sweep"
)

// Loggers per subsystem.  A single backend logger is created and all subsystem
// loggers created from it will write to the backend.  When adding new
// subsystems, add the subsystem logger variable here and to the
// subsystemLoggers map.
//
// Loggers can not be used before the log rotator has been initialized with a
// log file.  This must be performed early during application startup by
// calling initLogRotator.
var (
	logWriter = &build.LogWriter{}

	// backendLog is the logging backend used to create all subsystem
	// loggers.  The backend must not be used before the log rotator has
	// been initialized, or data races and/or nil pointer dereferences will
	// occur.
	backendLog = btclog.NewBackend(logWriter)

	// logRotator is one of the logging outputs.  It should be closed on
	// application shutdown.
	logRotator *rotator.Rotator

	ltndLog = build.NewSubLogger("LTND", backendLog.Logger)
	lnwlLog = build.NewSubLogger("LNWL", backendLog.Logger)
	peerLog = build.NewSubLogger("PEER", backendLog.Logger)
	discLog = build.NewSubLogger("DISC", backendLog.Logger)
	rpcsLog = build.NewSubLogger("RPCS", backendLog.Logger)
	srvrLog = build.NewSubLogger("SRVR", backendLog.Logger)
	ntfnLog = build.NewSubLogger("NTFN", backendLog.Logger)
	chdbLog = build.NewSubLogger("CHDB", backendLog.Logger)
	fndgLog = build.NewSubLogger("FNDG", backendLog.Logger)
	hswcLog = build.NewSubLogger("HSWC", backendLog.Logger)
	utxnLog = build.NewSubLogger("UTXN", backendLog.Logger)
	brarLog = build.NewSubLogger("BRAR", backendLog.Logger)
	cmgrLog = build.NewSubLogger("CMGR", backendLog.Logger)
	crtrLog = build.NewSubLogger("CRTR", backendLog.Logger)
	btcnLog = build.NewSubLogger("BTCN", backendLog.Logger)
	atplLog = build.NewSubLogger("ATPL", backendLog.Logger)
	cnctLog = build.NewSubLogger("CNCT", backendLog.Logger)
	sphxLog = build.NewSubLogger("SPHX", backendLog.Logger)
	swprLog = build.NewSubLogger("SWPR", backendLog.Logger)
	sgnrLog = build.NewSubLogger("SGNR", backendLog.Logger)
	wlktLog = build.NewSubLogger("WLKT", backendLog.Logger)
)

// Initialize package-global logger variables.
func init() {
	lnwallet.UseLogger(lnwlLog)
	discovery.UseLogger(discLog)
	chainntnfs.UseLogger(ntfnLog)
	channeldb.UseLogger(chdbLog)
	htlcswitch.UseLogger(hswcLog)
	connmgr.UseLogger(cmgrLog)
	routing.UseLogger(crtrLog)
	neutrino.UseLogger(btcnLog)
	autopilot.UseLogger(atplLog)
	contractcourt.UseLogger(cnctLog)
	sphinx.UseLogger(sphxLog)
	signal.UseLogger(ltndLog)
	sweep.UseLogger(swprLog)
	signrpc.UseLogger(sgnrLog)
	walletrpc.UseLogger(wlktLog)
}

// subsystemLoggers maps each subsystem identifier to its associated logger.
var subsystemLoggers = map[string]btclog.Logger{
	"LTND": ltndLog,
	"LNWL": lnwlLog,
	"PEER": peerLog,
	"DISC": discLog,
	"RPCS": rpcsLog,
	"SRVR": srvrLog,
	"NTFN": ntfnLog,
	"CHDB": chdbLog,
	"FNDG": fndgLog,
	"HSWC": hswcLog,
	"UTXN": utxnLog,
	"BRAR": brarLog,
	"CMGR": cmgrLog,
	"CRTR": crtrLog,
	"BTCN": btcnLog,
	"ATPL": atplLog,
	"CNCT": cnctLog,
	"SPHX": sphxLog,
	"SWPR": swprLog,
	"SGNR": sgnrLog,
	"WLKT": wlktLog,
}

// initLogRotator initializes the logging rotator to write logs to logFile and
// create roll files in the same directory.  It must be called before the
// package-global log rotator variables are used.
func initLogRotator(logFile string, MaxLogFileSize int, MaxLogFiles int) {
	logDir, _ := filepath.Split(logFile)
	err := os.MkdirAll(logDir, 0700)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err)
		os.Exit(1)
	}
	r, err := rotator.New(logFile, int64(MaxLogFileSize*1024), false, MaxLogFiles)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err)
		os.Exit(1)
	}

	pr, pw := io.Pipe()
	go r.Run(pr)

	logWriter.RotatorPipe = pw
	logRotator = r
}

// setLogLevel sets the logging level for provided subsystem.  Invalid
// subsystems are ignored.  Uninitialized subsystems are dynamically created as
// needed.
func setLogLevel(subsystemID string, logLevel string) {
	// Ignore invalid subsystems.
	logger, ok := subsystemLoggers[subsystemID]
	if !ok {
		return
	}

	// Defaults to info if the log level is invalid.
	level, _ := btclog.LevelFromString(logLevel)
	logger.SetLevel(level)
}

// setLogLevels sets the log level for all subsystem loggers to the passed
// level. It also dynamically creates the subsystem loggers as needed, so it
// can be used to initialize the logging system.
func setLogLevels(logLevel string) {
	// Configure all sub-systems with the new logging level.  Dynamically
	// create loggers as needed.
	for subsystemID := range subsystemLoggers {
		setLogLevel(subsystemID, logLevel)
	}
}

// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string

// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
	return c()
}

// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
	return logClosure(c)
}
<|endoftext|>


<commit_before>package raft

type LogType uint8

const (
	// Commands are applied to a user FSM
	LogCommand LogType = iota

	// Noop is used to assert leadership
	LogNoop
)

// Log entries are replicated to all members of the Raft cluster
// and form the heart of the replicated state machine.
type Log struct {
	Index uint64
	Term  uint64
	Type  LogType
	Data  []byte
}

// LogStore is used to provide an interface for storing
// and retrieving logs in a durable fashion
type LogStore interface {
	// Returns the last index written. 0 for no entries.
	LastIndex() (uint64, error)

	// Gets a log entry at a given index
	GetLog(index uint64, log *Log) error

	// Stores a log entry
	StoreLog(log *Log) error

	// Deletes a range of log entries. The range is inclusive.
	DeleteRange(min, max uint64) error
}
<commit_msg>Adding two new log types<commit_after>package raft

type LogType uint8

const (
	// Commands are applied to a user FSM
	LogCommand LogType = iota

	// Noop is used to assert leadership
	LogNoop

	// Used to add a new peer
	LogAddPeer

	// Used to remove an existing peer
	LogRemovePeer
)

// Log entries are replicated to all members of the Raft cluster
// and form the heart of the replicated state machine.
type Log struct {
	Index uint64
	Term  uint64
	Type  LogType
	Data  []byte
}

// LogStore is used to provide an interface for storing
// and retrieving logs in a durable fashion
type LogStore interface {
	// Returns the last index written. 0 for no entries.
	LastIndex() (uint64, error)

	// Gets a log entry at a given index
	GetLog(index uint64, log *Log) error

	// Stores a log entry
	StoreLog(log *Log) error

	// Deletes a range of log entries. The range is inclusive.
	DeleteRange(min, max uint64) error
}
<|endoftext|>


<commit_before>package summer

import (
	"log"
	"os"
)

type LogLevel int

const (
	DebugLevel LogLevel = iota
	InfoLevel
	WarnLevel
	ErrorLevel
	PanicLevel
	FatalLevel
)

var logger = NewSimpleLog("summer", InfoLevel)

type SimpleLogger struct {
	level LogLevel
}

func NewSimpleLogger(logLevel LogLevel) *SimpleLogger {
	return &SimpleLogger{logLevel}
}
func (sl *SimpleLogger) Module(module string) *SimpleLog {
	return &SimpleLog{log: log.New(os.Stderr, "["+module+"]", log.LstdFlags), level: sl.level}
}

type SimpleLog struct {
	log   *log.Logger
	level LogLevel
}

func NewSimpleLog(module string, logLevel LogLevel) *SimpleLog {
	return &SimpleLog{log: log.New(os.Stderr, "["+module+"]", log.LstdFlags), level: InfoLevel}
}
func (sl *SimpleLog) SetLevel(logLevel LogLevel) *SimpleLog {
	sl.level = logLevel
	return sl
}
func SetLogLevel(logLevel LogLevel) {
	logger.SetLevel(logLevel)
}
func (log *SimpleLog) Debug(args ...interface{}) {
	if DebugLevel < log.level {
		return
	}
	log.log.Println(args)
}
func (log *SimpleLog) Error(args ...interface{}) {
	if ErrorLevel < log.level {
		return
	}
	log.log.Println(args)
}
func (log *SimpleLog) Println(args ...interface{}) {
	log.log.Println(args)
}
func (log *SimpleLog) Warn(args ...interface{}) {
	if WarnLevel < log.level {
		return
	}
	log.log.Println(args)
}

func (log *SimpleLog) Panic(args ...interface{}) {
	if PanicLevel < log.level {
		return
	}
	log.log.Panicln(args)
}

func (log *SimpleLog) Fatal(args ...interface{}) {
	if FatalLevel < log.level {
		return
	}
	log.log.Fatalln(args)
}

func (log *SimpleLog) Info(args ...interface{}) {
	if InfoLevel < log.level {
		return
	}
	log.log.Println(args)
}
<commit_msg>fix logs bug<commit_after>package summer

import (
	"log"
	"os"
)

type LogLevel int

const (
	DebugLevel LogLevel = iota
	InfoLevel
	WarnLevel
	ErrorLevel
	PanicLevel
	FatalLevel
)

var logger = NewSimpleLog("summer", InfoLevel)

type SimpleLogger struct {
	level LogLevel
}

func NewSimpleLogger(logLevel LogLevel) *SimpleLogger {
	return &SimpleLogger{logLevel}
}
func (sl *SimpleLogger) Module(module string) *SimpleLog {
	return &SimpleLog{log: log.New(os.Stderr, "["+module+"]", log.LstdFlags), level: sl.level}
}

type SimpleLog struct {
	log   *log.Logger
	level LogLevel
}

func NewSimpleLog(module string, logLevel LogLevel) *SimpleLog {
	return &SimpleLog{log: log.New(os.Stderr, "["+module+"]", log.LstdFlags), level: InfoLevel}
}
func (sl *SimpleLog) SetLevel(logLevel LogLevel) *SimpleLog {
	sl.level = logLevel
	return sl
}
func SetLogLevel(logLevel LogLevel) {
	logger.SetLevel(logLevel)
}
func (log *SimpleLog) Debug(args ...interface{}) {
	if DebugLevel < log.level {
		return
	}
	log.log.Println(args...)
}
func (log *SimpleLog) Error(args ...interface{}) {
	if ErrorLevel < log.level {
		return
	}
	log.log.Println(args...)
}
func (log *SimpleLog) Println(args ...interface{}) {
	log.log.Println(args...)
}
func (log *SimpleLog) Warn(args ...interface{}) {
	if WarnLevel < log.level {
		return
	}
	log.log.Println(args...)
}

func (log *SimpleLog) Panic(args ...interface{}) {
	if PanicLevel < log.level {
		return
	}
	log.log.Panicln(args...)
}

func (log *SimpleLog) Fatal(args ...interface{}) {
	if FatalLevel < log.level {
		return
	}
	log.log.Fatalln(args...)
}

func (log *SimpleLog) Info(args ...interface{}) {
	if InfoLevel < log.level {
		return
	}
	log.log.Println(args...)
}
<|endoftext|>


<commit_before>package last

import (
	"container/list"
	"runtime/debug"
	"sync"
)

type Cache interface {
	// SetMinFreeMemory sets the minimum amount of free memory
	// in bytes before the cache starts evicting objects.
	SetMinFreeMemory(v uint64)

	// Put stores and pushes the item to the front of the cache.
	Put(k string, v interface{})

	// Get gets the item from the cache and pushes it to the front.
	Get(k string) (interface{}, bool)

	// Del removes the item from the cache.
	Del(k string)

	// Len returns the number of items stored in the cache.
	Len() int

	// Evict removes the oldest n items from the cache.
	Evict(n int)
}

type lru struct {
	mtx        sync.Mutex
	scheduled  int32
	minFreeMem uint64
	lookup     map[string]*list.Element
	list       *list.List
}

type lruItem struct {
	key   string
	value interface{}
}

func New() Cache {
	return &lru{
		minFreeMem: 1024 * 1024 * 10, // 10MB
		lookup:     make(map[string]*list.Element),
		list:       list.New(),
	}
}

func (c *lru) SetMinFreeMemory(v uint64) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.minFreeMem = v
}

func (c *lru) Put(k string, v interface{}) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if v == nil {
		return
	}
	c.evictIfNecessary()
	c.lookup[k] = c.list.PushFront(&lruItem{
		key:   k,
		value: v,
	})
}

func (c *lru) Get(k string) (interface{}, bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.MoveToFront(e)
		return e.Value.(*lruItem).value, true
	}
	return nil, false
}

func (c *lru) Del(k string) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.Remove(e)
		delete(c.lookup, k)
	}
}

func (c *lru) Len() int {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	return c.list.Len()
}

func (c *lru) Evict(n int) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.evict(n)
}

func (c *lru) evictIfNecessary() {
	err := refreshMemStats()
	if err != nil {
		panic(err)
	}
	if memStats.Free < c.minFreeMem {
		c.evict(c.list.Len() / 4)
		debug.FreeOSMemory()
	}
}

func (c *lru) evict(n int) {
	for {
		if n < 1 {
			break
		}
		e := c.list.Back()
		delete(c.lookup, e.Value.(*lruItem).key)
		c.list.Remove(e)
		n--
	}
}
<commit_msg>Reset last read after eviction<commit_after>package last

import (
	"container/list"
	"runtime/debug"
	"sync"
	"time"
)

type Cache interface {
	// SetMinFreeMemory sets the minimum amount of free memory
	// in bytes before the cache starts evicting objects.
	SetMinFreeMemory(v uint64)

	// Put stores and pushes the item to the front of the cache.
	Put(k string, v interface{})

	// Get gets the item from the cache and pushes it to the front.
	Get(k string) (interface{}, bool)

	// Del removes the item from the cache.
	Del(k string)

	// Len returns the number of items stored in the cache.
	Len() int

	// Evict removes the oldest n items from the cache.
	Evict(n int)
}

type lru struct {
	mtx        sync.Mutex
	scheduled  int32
	minFreeMem uint64
	lookup     map[string]*list.Element
	list       *list.List
}

type lruItem struct {
	key   string
	value interface{}
}

func New() Cache {
	return &lru{
		minFreeMem: 1024 * 1024 * 10, // 10MB
		lookup:     make(map[string]*list.Element),
		list:       list.New(),
	}
}

func (c *lru) SetMinFreeMemory(v uint64) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.minFreeMem = v
}

func (c *lru) Put(k string, v interface{}) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if v == nil {
		return
	}
	c.evictIfNecessary()
	c.lookup[k] = c.list.PushFront(&lruItem{
		key:   k,
		value: v,
	})
}

func (c *lru) Get(k string) (interface{}, bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.MoveToFront(e)
		return e.Value.(*lruItem).value, true
	}
	return nil, false
}

func (c *lru) Del(k string) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.Remove(e)
		delete(c.lookup, k)
	}
}

func (c *lru) Len() int {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	return c.list.Len()
}

func (c *lru) Evict(n int) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.evict(n)
}

func (c *lru) evictIfNecessary() {
	err := refreshMemStats()
	if err != nil {
		panic(err)
	}
	if memStats.Free < c.minFreeMem {
		c.evict(c.list.Len() / 4)
		debug.FreeOSMemory()

		// force a read reset, otherwise we might evict
		// the whole cache with subsequent calls.
		lastRead = time.Unix(0, 0)
	}
}

func (c *lru) evict(n int) {
	for {
		if n < 1 {
			break
		}
		e := c.list.Back()
		delete(c.lookup, e.Value.(*lruItem).key)
		c.list.Remove(e)
		n--
	}
}
<|endoftext|>