<commit_before>package main

import (
	"net"
	"os"
	"fmt"
    "strings"
    "errors"
    "database/sql"
    "github.com/go-sql-driver/mysql"
)

func dieIfError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
		os.Exit(1)
	}
}

func main() {

    // connect to database to store tags
    db, err := sql.Open("mysql", "carbon_tagger:carbon_tagger_pw@tcp(graphitemachine:3306)/carbon_tagger?charset=utf8")
    dieIfError(err)
    defer db.Close()
    // Open doesn't open a connection. Validate DSN data:
    err = db.Ping()
    dieIfError(err)
    statement_insert_tag, err := db.Prepare("INSERT INTO tags (tag_key, tag_val) VALUES( ?, ? )")
    dieIfError(err)
    statement_select_tag, err := db.Prepare("SELECT tag_id FROM tags WHERE tag_key=? AND tag_val=?")
    dieIfError(err)
    statement_insert_metric, err := db.Prepare("INSERT INTO metrics VALUES( ? )")
    dieIfError(err)
    statement_insert_link, err := db.Prepare("INSERT INTO metrics_tags VALUES( ?, ? )")
    dieIfError(err)

    // listen for incoming metrics
	service := ":2003"
	addr, err := net.ResolveTCPAddr("tcp4", service)
	dieIfError(err)
	listener, err := net.ListenTCP("tcp", addr)
	dieIfError(err)

    // TODO connect to outgoing carbon-relay or carbon-cache

	for {
		conn_in, err := listener.Accept()
		if err != nil {
			continue
		}
		handleClient(conn_in, db, statement_insert_tag, statement_select_tag, statement_insert_metric, statement_insert_link)
		conn_in.Close()
	}
}

func parseTagBasedMetric(metric string) (metric_id string, tags map[string]string, err error) {
    fmt.Printf(">incoming: %s\n", metric)
    // metric_spec value unix_timestamp
    elements := strings.Split(metric, " ")
    metric_id = ""
    if len(elements) != 3  {
        return metric_id, nil, errors.New("metric doesn't contain exactly 3 nodes")
    }
    metric_id = elements[0]
    nodes := strings.Split(metric_id, ".")
    tags = make(map[string]string)
    // TODO make sure incoming tags are sorted
    for _, node := range nodes {
        tag := strings.Split(node, "=")
        if len(tag) != 2 {
            return metric_id, nil, errors.New("bad metric spec: each node must be a 'tag_k=tag_v' pair")
        }
        if tag[0] == "" || tag[1] == "" {
            return metric_id, nil, errors.New("bad metric spec: tag_k and tag_v must be non-empty strings")
        }

        tags[tag[0]] = tag[1]
    }
    if _,ok := tags["unit"]; !ok {
        return metric_id, nil, errors.New("bad metric spec: unit tag (mandatory) not specified")
    }
    if len(tags) < 2 {
        return metric_id, nil, errors.New("bad metric spec: must have at least one tag_k/tag_v pair beyond unit")
    }
    return
}

func forwardMetric(metric string) {
    // forward
    //_, err2 := conn_out.Write(buf[0:n])
    //if err2 != nil {
    //    return
   // }
}

func handleClient(conn_in net.Conn, db *sql.DB, statement_insert_tag *sql.Stmt, statement_select_tag *sql.Stmt, statement_insert_metric *sql.Stmt, statement_insert_link *sql.Stmt) {
	var buf [512]byte
	for {
		bytes, err := conn_in.Read(buf[0:])
		if err != nil {
			return
		}
        str := string(buf[0:bytes])
        if(strings.ContainsAny(str, "=")) {
            str = strings.TrimSpace(str)
            metric_id, tags, err:= parseTagBasedMetric(str)
            if err != nil {
                fmt.Printf("DEBUG: invalid tag based metric, ignoring (%s)\n", err)
            } else {
                fmt.Printf("DEBUG: valid tag based metric %s, storing tags and forwarding\n", strings.TrimSpace(str))
                // TODO this should go in a transaction. for now we first store all tag_k=tag_v pairs (if they are orphans, it's not so bad)
                // then add the metric, than the coupling between metric and tags. <-- all this should def. be in a transaction
                tag_ids := make([]int64, 1)
                for tag_k, tag_v := range tags {
                    fmt.Println("Key:", tag_k, "Value:", tag_v)
                    res, err := statement_insert_tag.Exec(tag_k, tag_v)
                    if err != nil {
                        if err.(*mysql.MySQLError).Number == 1062 {  // Error 1062: Duplicate entry
                            res, err := statement_select_tag.Exec(tag_k, tag_v)
                            if err != nil {
                                fmt.Fprintf(os.Stderr, "Can't lookup the id of tag %s=%s: %s\n", tag_k, tag_v, err.Error())
                                return
                            }
                        } else {
                            fmt.Fprintf(os.Stderr, "can't store tag %s=%s: %s\n", tag_k, tag_v, err.Error())
                            return
                        }
                    } else {
                        id, err := res.LastInsertId()
                        if err != nil {
                            tag_ids = append(tag_ids, id)
                        } else {
                            fmt.Fprintf(os.Stderr, "can't get id for just inserted tag %s=%s: %s\n", tag_k, tag_v, err.Error())
                            return
                        }
                    }
                }
                _, err = statement_insert_metric.Exec(metric_id)
                if err != nil {
                    if err.(*mysql.MySQLError).Number != 1062 { // Error 1062: Duplicate entry 'unit=f.b=aeu' for key 'PRIMARY'
                        fmt.Fprintf(os.Stderr, "can't store metric %s:%s\n", metric_id, err.Error())
                        return
                    }
                } else {
                // the metric is newly inserted.. we still have to couple it to the tags.
                // so we assume if the metric already existed, we don't need to do this anymore. which is not very accurate since we don't use transactions yet
                    for _, tag_id := range tag_ids {
                        _, err = statement_insert_link.Exec(metric_id, tag_id)
                        if err != nil {
                            fmt.Fprintf(os.Stderr, "can't link metric %s to tag:%s\n", metric_id, err.Error())
                            return
                        }
                    }
                }
                forwardMetric(str)
            }
        } else {
            fmt.Printf("DEBUG: not tag based, forwarding metric %s\n", strings.TrimSpace(str))
            forwardMetric(str)
        }
	}
}

<commit_msg>fixes<commit_after>package main

import (
	"net"
	"os"
	"fmt"
    "strings"
    "errors"
    "database/sql"
    "github.com/go-sql-driver/mysql"
)

func dieIfError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
		os.Exit(1)
	}
}

func main() {

    // connect to database to store tags
    db, err := sql.Open("mysql", "carbon_tagger:carbon_tagger_pw@tcp(graphitemachine:3306)/carbon_tagger?charset=utf8")
    dieIfError(err)
    defer db.Close()
    // Open doesn't open a connection. Validate DSN data:
    err = db.Ping()
    dieIfError(err)
    statement_insert_tag, err := db.Prepare("INSERT INTO tags (tag_key, tag_val) VALUES( ?, ? )")
    dieIfError(err)
    statement_select_tag, err := db.Prepare("SELECT tag_id FROM tags WHERE tag_key=? AND tag_val=?")
    dieIfError(err)
    statement_insert_metric, err := db.Prepare("INSERT INTO metrics VALUES( ? )")
    dieIfError(err)
    statement_insert_link, err := db.Prepare("INSERT INTO metrics_tags VALUES( ?, ? )")
    dieIfError(err)

    // listen for incoming metrics
	service := ":2003"
	addr, err := net.ResolveTCPAddr("tcp4", service)
	dieIfError(err)
	listener, err := net.ListenTCP("tcp", addr)
	dieIfError(err)

    // TODO connect to outgoing carbon-relay or carbon-cache

	for {
		conn_in, err := listener.Accept()
		if err != nil {
			continue
		}
		handleClient(conn_in, db, statement_insert_tag, statement_select_tag, statement_insert_metric, statement_insert_link)
		conn_in.Close()
	}
}

func parseTagBasedMetric(metric string) (metric_id string, tags map[string]string, err error) {
    fmt.Printf(">incoming: %s\n", metric)
    // metric_spec value unix_timestamp
    elements := strings.Split(metric, " ")
    metric_id = ""
    if len(elements) != 3  {
        return metric_id, nil, errors.New("metric doesn't contain exactly 3 nodes")
    }
    metric_id = elements[0]
    nodes := strings.Split(metric_id, ".")
    tags = make(map[string]string)
    // TODO make sure incoming tags are sorted
    for _, node := range nodes {
        tag := strings.Split(node, "=")
        if len(tag) != 2 {
            return metric_id, nil, errors.New("bad metric spec: each node must be a 'tag_k=tag_v' pair")
        }
        if tag[0] == "" || tag[1] == "" {
            return metric_id, nil, errors.New("bad metric spec: tag_k and tag_v must be non-empty strings")
        }

        tags[tag[0]] = tag[1]
    }
    if _,ok := tags["unit"]; !ok {
        return metric_id, nil, errors.New("bad metric spec: unit tag (mandatory) not specified")
    }
    if len(tags) < 2 {
        return metric_id, nil, errors.New("bad metric spec: must have at least one tag_k/tag_v pair beyond unit")
    }
    return
}

func forwardMetric(metric string) {
    // forward
    //_, err2 := conn_out.Write(buf[0:n])
    //if err2 != nil {
    //    return
   // }
}

func handleClient(conn_in net.Conn, db *sql.DB, statement_insert_tag *sql.Stmt, statement_select_tag *sql.Stmt, statement_insert_metric *sql.Stmt, statement_insert_link *sql.Stmt) {
	var buf [512]byte
	for {
		bytes, err := conn_in.Read(buf[0:])
		if err != nil {
			return
		}
        str := string(buf[0:bytes])
        if(strings.ContainsAny(str, "=")) {
            str = strings.TrimSpace(str)
            metric_id, tags, err:= parseTagBasedMetric(str)
            if err != nil {
                fmt.Printf("DEBUG: invalid tag based metric, ignoring (%s)\n", err)
            } else {
                fmt.Printf("DEBUG: valid tag based metric %s, storing tags and forwarding\n", strings.TrimSpace(str))
                // TODO this should go in a transaction. for now we first store all tag_k=tag_v pairs (if they are orphans, it's not so bad)
                // then add the metric, than the coupling between metric and tags. <-- all this should def. be in a transaction
                tag_ids := make([]int64, 0)  //maybe set cap to len(tags) or so
                for tag_k, tag_v := range tags {
                    fmt.Println("Key:", tag_k, "Value:", tag_v)
                    res, err := statement_insert_tag.Exec(tag_k, tag_v)
                    if err != nil {
                        if err.(*mysql.MySQLError).Number == 1062 {  // Error 1062: Duplicate entry
                            var id int64
                            err := statement_select_tag.QueryRow(tag_k, tag_v).Scan(&id)
                            if err != nil {
                                fmt.Fprintf(os.Stderr, "Can't lookup the id of tag %s=%s: %s\n", tag_k, tag_v, err.Error())
                                return
                            }
                            tag_ids = append(tag_ids, id)
                        } else {
                            fmt.Fprintf(os.Stderr, "can't store tag %s=%s: %s\n", tag_k, tag_v, err.Error())
                            return
                        }
                    } else {
                        id, err := res.LastInsertId()
                        if err != nil {
                            fmt.Fprintf(os.Stderr, "can't get id for just inserted tag %s=%s: %s\n", tag_k, tag_v, err.Error())
                            return
                        } else {
                            tag_ids = append(tag_ids, id)
                        }
                    }
                }
                _, err = statement_insert_metric.Exec(metric_id)
                if err != nil {
                    if err.(*mysql.MySQLError).Number != 1062 { // Error 1062: Duplicate entry 'unit=f.b=aeu' for key 'PRIMARY'
                        fmt.Fprintf(os.Stderr, "can't store metric %s:%s\n", metric_id, err.Error())
                        return
                    }
                } else {
                // the metric is newly inserted.. we still have to couple it to the tags.
                // so we assume if the metric already existed, we don't need to do this anymore. which is not very accurate since we don't use transactions yet
                    for _, tag_id := range tag_ids {
                        _, err = statement_insert_link.Exec(metric_id, tag_id)
                        if err != nil {
                            fmt.Fprintf(os.Stderr, "can't link metric %s to tag:%s\n", metric_id, err.Error())
                            return
                        }
                    }
                }
                forwardMetric(str)
            }
        } else {
            fmt.Printf("DEBUG: not tag based, forwarding metric %s\n", strings.TrimSpace(str))
            forwardMetric(str)
        }
	}
}

<|endoftext|>


<commit_before>package meow-ml

import "ashumeow/ml-kmeans/meow-data-structures"

type meowCluster struct {
	blackhole *meowPoint
	dots *meow-data-structures.meowArrayList
}

// new meowCluster
func meowNewCluster(blackhole *meowPoint) *meowCluster {
	my := &meowCluster{}
	my.blackhole = blackhole
	my.dots = meow-data-structures.meowNewArrayList()
	return my
}

// dots
func (my *meowCluster) dots() *meow-data-structures.meowArrayList {
	return my.dots
}

// blackhole -- center
func (my *meowCluster) blackhole() *meowPoint {
	return my.blackhole
}

// blackhole in deep -- re-centering
func(my *meowCluster) blackholeInDeep() float64 {
	totalDots := my.dots.meowLen()
	sourceDot := my.dots.meowFetch(0).(*meowPoint)
	totalCoordinates := sourceDot.stuffs.meowLen()

	// still more to code
}<commit_msg>add cluster<commit_after>package meow-ml

import "ashumeow/ml-kmeans/meow-data-structures"

type meowCluster struct {
	blackhole *meowPoint
	dots *meow-data-structures.meowArrayList
}

// new meowCluster
func meowNewCluster(blackhole *meowPoint) *meowCluster {
	my := &meowCluster{}
	my.blackhole = blackhole
	my.dots = meow-data-structures.meowNewArrayList()
	return my
}

// dots
func (my *meowCluster) dots() *meow-data-structures.meowArrayList {
	return my.dots
}

// blackhole -- center
func (my *meowCluster) blackhole() *meowPoint {
	return my.blackhole
}

// blackhole in deep -- re-centering
func(my *meowCluster) blackholeInDeep() float64 {
	totalDots := my.dots.meowLen()
	sourceDot := my.dots.meowFetch(0).(*meowPoint)
	totalCoordinates := sourceDot.stuffs.meowLen()

	// addition
	meowTotal := make([]float64, totalCoordinates)
	for x := 0; x < totalDots; x++ {
		dot := my.dots.meowFetch(x).(*meowPoint)
		for xx := 0; xx < totalCoordinates; xx++ {
			meowTotal[xx] = meowTotal[xx] + dot.stuffs.meowFetch(xx).(float64)
		}
	}

	// average
	meowAvg := make([]float64, totalCoordinates)
	for x := 0; x < totalCoordinates; x++ {
		meowAvg[x] = meowTotal[x] / float64(totalDots)
	}

	// distance between old and new blackhole center
	newBlackhole := meowPoint(meowAvg)
	meowDist := my.blackhole.DistanceFromPoint(newBlackhole)
	my.blackhole = newBlackhole
	return meowDist
}<|endoftext|>


<commit_before>// Package slug provides an utility for generating URL-friendly slugs.
//
// Example:
//
//	package main
//
//	import "github.com/peferron/slug"
//
//	func main() {
//		s := slug.Slug("Hello World!", 50, "-")
//		print(s) // Prints "hello-world"
//	}
package slug

import (
	"strings"
	"unicode"

	"github.com/fiam/gounidecode/unidecode"
)

// Generate returns a slug generated from s, with sensible default parameters.
func Generate(s string) string {
	return GenerateWith(s, ` ,./\-_=~|()[]{}:;?!<>`, "-", 100)
}

// GenerateWith returns a slug generated from s, with all Unicode code points in chars replaced by
// the separator sep, and the final maximum length l.
func GenerateWith(s, chars, sep string, l int) string {
	decoded := unidecode.Unidecode(s)
	slug := ""

	for _, d := range decoded {
		r := convert(d, chars, sep)

		switch r {
		case "":
			continue
		case sep:
			if len(slug) > 0 && !strings.HasSuffix(slug, sep) {
				slug += sep
			}
		default:
			slug += string(r)
		}

		if len(slug) >= l {
			break
		}
	}

	return strings.TrimSuffix(slug, sep)
}

// convert returns the slug representation of r, using the separator sep.
func convert(r rune, chars, sep string) string {
	switch {
	case 'a' <= r && r <= 'z' || '0' <= r && r <= '9':
		return string(r)
	case 'A' <= r && r <= 'Z':
		return string(unicode.ToLower(r))
	case strings.ContainsRune(chars, r):
		return sep
	}
	return ""
}
<commit_msg>Update example<commit_after>// Package slug provides an utility for generating URL-friendly slugs.
//
// Example:
//
//	package main
//
//	import "github.com/peferron/slug"
//
//	func main() {
//		s := slug.Generate("Hello World!")
//		print(s) // Prints "hello-world"
//	}
package slug

import (
	"strings"
	"unicode"

	"github.com/fiam/gounidecode/unidecode"
)

// Generate returns a slug generated from s, with sensible default parameters.
func Generate(s string) string {
	return GenerateWith(s, ` ,./\-_=~|()[]{}:;?!<>`, "-", 100)
}

// GenerateWith returns a slug generated from s, with all Unicode code points in chars replaced by
// the separator sep, and the final maximum length l.
func GenerateWith(s, chars, sep string, l int) string {
	decoded := unidecode.Unidecode(s)
	slug := ""

	for _, d := range decoded {
		r := convert(d, chars, sep)

		switch r {
		case "":
			continue
		case sep:
			if len(slug) > 0 && !strings.HasSuffix(slug, sep) {
				slug += sep
			}
		default:
			slug += string(r)
		}

		if len(slug) >= l {
			break
		}
	}

	return strings.TrimSuffix(slug, sep)
}

// convert returns the slug representation of r, using the separator sep.
func convert(r rune, chars, sep string) string {
	switch {
	case 'a' <= r && r <= 'z' || '0' <= r && r <= '9':
		return string(r)
	case 'A' <= r && r <= 'Z':
		return string(unicode.ToLower(r))
	case strings.ContainsRune(chars, r):
		return sep
	}
	return ""
}
<|endoftext|>


<commit_before>package aggro

type Sortable interface {
	Less(a, b *ResultBucket) bool
}

func sortableForOptions(options *SortOptions) Sortable {
	if options == nil {
		return nil
	}
	switch options.Type {
	case "alphabetical":
		s := AlphabeticalSortable(!options.Desc)
		return &s
	}
	return nil
}

type AlphabeticalSortable bool

func (sortable *AlphabeticalSortable) Less(a, b *ResultBucket) bool {
	return a.Value < b.Value == bool(*sortable)
}
<commit_msg>Add some comments to sort.go<commit_after>package aggro

// Sortable provides an interface that various sorters can implement to compare
// two result buckets. This enables access to both the value and any metrics
// that the query may have contained.
type Sortable interface {
	Less(a, b *ResultBucket) bool
}

// sortableForOptions returns the appropriate sorter for the supplied sort
// options. If the options type provided is invalid, it is ignored an no sorter
// is returned. A nil response here will end up with results being in a
// non-deterministic order due to randomisation when ranging over maps.
func sortableForOptions(options *SortOptions) Sortable {
	if options == nil {
		return nil
	}
	switch options.Type {
	case "alphabetical":
		s := AlphabeticalSortable(!options.Desc)
		return &s
	}
	return nil
}

// AlphabeticalSortable is a simple  sorter that sorts alphabetically in the
// direction of the boolean, true meaning ascending and false being descending.
type AlphabeticalSortable bool

// Less implements Sortable by comparing the values field of each result.
func (sortable *AlphabeticalSortable) Less(a, b *ResultBucket) bool {
	return a.Value < b.Value == bool(*sortable)
}
<|endoftext|>


<commit_before>// Copyright 2013 Artur Grabowski. All rights reserved.
// Use of this source code is governed by a ISC-style
// license that can be found in the LICENSE file.

package timers

import (
	"net/http"
	"encoding/json"
)

// StdJSON is the default layout for outputing the timer data as JSON.
type StdJSON struct {
	Name string
	Cnt Counts
	Children []*StdJSON
}

func (sj *StdJSON) Insert(name []string, counts *Counts) {
	if len(name) == 0 {
		sj.Cnt = *counts
		return
	}

	// This would be so much easier with a map, but then the json is a pain in the ass to handle.
	var c *StdJSON
	for _, v := range sj.Children {
		if v.Name == name[0] {
			c = v
			break
		}
	}
	if c == nil {
		c = &StdJSON{}
		c.Name = name[0]
		sj.Children = append(sj.Children, c)
	}
	c.Insert(name[1:], counts)
}

// Standard http handler for returning a Timer with JSON.
func (t Timer) JSONHandler(w http.ResponseWriter, req *http.Request) {
	out := StdJSON{ Name: "top" }

	t.Foreach(func (name []string, counts *Counts) {
		out.Insert(name, counts)
	})
	json, _ := json.MarshalIndent(out, "", "    ")
	w.Write(json)
}

func JSONHandlerGraph(w http.ResponseWriter, req *http.Request, timers_url string) {
d :=`

    reload

`
	w.Write([]byte(d))
}
<commit_msg>Better partition rendering code.<commit_after>// Copyright 2013 Artur Grabowski. All rights reserved.
// Use of this source code is governed by a ISC-style
// license that can be found in the LICENSE file.

package timers

import (
	"net/http"
	"encoding/json"
)

// StdJSON is the default layout for outputing the timer data as JSON.
type StdJSON struct {
	Name string
	Cnt Counts
	Children []*StdJSON
}

func (sj *StdJSON) Insert(name []string, counts *Counts) {
	if len(name) == 0 {
		sj.Cnt = *counts
		return
	}

	// This would be so much easier with a map, but then the json is a pain in the ass to handle.
	var c *StdJSON
	for _, v := range sj.Children {
		if v.Name == name[0] {
			c = v
			break
		}
	}
	if c == nil {
		c = &StdJSON{}
		c.Name = name[0]
		sj.Children = append(sj.Children, c)
	}
	c.Insert(name[1:], counts)
}

// Standard http handler for returning a Timer with JSON.
func (t Timer) JSONHandler(w http.ResponseWriter, req *http.Request) {
	out := StdJSON{ Name: "top" }

	t.Foreach(func (name []string, counts *Counts) {
		out.Insert(name, counts)
	})
	json, _ := json.MarshalIndent(out, "", "    ")
	w.Write(json)
}

func JSONHandlerGraph(w http.ResponseWriter, req *http.Request, timers_url string) {
d :=`

    reload

`
	w.Write([]byte(d))
}
<|endoftext|>


<commit_before>package floatutils

import (
	"math"
	"math/big"
)

func Sqrt(z *big.Float) *big.Float {

	// panic on negative z < 0
	if z.Sign() == -1 {
		panic("square root of negative number")
	}

	// Sqrt(±0) = ±0
	if z.Sign() == 0 {
		return big.NewFloat(float64(z.Sign()))
	}

	// Sqrt(+Inf) = +Inf
	if z.IsInf() {
		return big.NewFloat(math.Inf(+1))
	}

	// We need extra-precision to make Sqrt results 100%
	// compatible with what math.Sqrt returns on regular float64s.
	// Not sure how much extra bits we really need, but
	// forcing a whole new Word in the nat representation seems reasonable.
	// 32 seems to work too, but leave 64 for now.
	// Performance is about 40% worse when prec ~ 10,
	// otherwise there's no difference.
	prec := z.Prec() + 64 // TODO: find a better value

	one := new(big.Float).SetPrec(prec).SetInt64(1)
	half := new(big.Float).SetPrec(prec).SetFloat64(0.5)

	// initial estimate
	x := new(big.Float).SetPrec(prec).SetMantExp(one, z.MantExp(nil)/2)

	t := new(big.Float).SetPrec(prec)

	// Newton:
	//     x_{n+1} = 1/2 * ( x_n + (S / x_n) )

	// we need at least log_2(prec) iterations
	steps := math.Log2(float64(prec))

	for i := 0; i < int(steps); i++ {
		t.Quo(z, x)    // t = S / x_n
		t.Add(t, x)    // t = x_n + (S / x_n)
		x.Mul(t, half) // x = t / 2
	}

	return x.SetPrec(z.Prec())
}
<commit_msg>Added a few TODOs<commit_after>package floatutils

import (
	"math"
	"math/big"
)

func Sqrt(z *big.Float) *big.Float {

	// panic on negative z < 0
	if z.Sign() == -1 {
		panic("square root of negative number")
	}

	// Sqrt(±0) = ±0
	if z.Sign() == 0 {
		return big.NewFloat(float64(z.Sign()))
	}

	// Sqrt(+Inf) = +Inf
	if z.IsInf() {
		return big.NewFloat(math.Inf(+1))
	}

	// We need extra-precision to make Sqrt results 100%
	// compatible with what math.Sqrt returns on regular float64s.
	// Not sure how much extra bits we really need, but
	// forcing a whole new Word in the nat representation seems reasonable.
	// 32 seems to work too, but leave 64 for now.
	// Performance is about 40% worse when prec ~ 10,
	// otherwise there's no difference.
	prec := z.Prec() + 64 // TODO: find a better value

	one := new(big.Float).SetPrec(prec).SetInt64(1)
	half := new(big.Float).SetPrec(prec).SetFloat64(0.5)

	// initial estimate
	x := new(big.Float).SetPrec(prec).SetMantExp(one, z.MantExp(nil)/2)

	// TODO: no need to call setPrec
	t := new(big.Float).SetPrec(prec)

	// Newton:
	//     x_{n+1} = 1/2 * ( x_n + (S / x_n) )

	// we need at least log_2(prec) iterations
	// TODO: test if new(big.Float).Mul(x, x).Cmp(z) != 0 is better
	steps := math.Log2(float64(prec))

	for i := 0; i < int(steps); i++ {
		t.Quo(z, x)    // t = S / x_n
		t.Add(t, x)    // t = x_n + (S / x_n)
		x.Mul(t, half) // x = t / 2
	}

	return x.SetPrec(z.Prec())
}
<|endoftext|>


<commit_before>// Copyright 2016 Open Networking Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strings"
	"text/template"
)

type GenerationOptions struct {
	SwitchCount int `json:"switchcount"`
	HostCount   int `json:"hostcount"`
}

func (c *Config) configGenHandler(w http.ResponseWriter, r *http.Request) {
	var options GenerationOptions

	deviceMap := make(map[string]*onosDevice)

	decoder := json.NewDecoder(r.Body)
	defer r.Body.Close()
	if err := decoder.Decode(&options); err != nil {
		log.Errorf("Unable to decode provisioning request options: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var devices onosDevices
	err := c.fetch("/onos/v1/devices", &devices)
	if err != nil {
		log.Errorf("Unable to retrieve device information from controller: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// If the request specified the number of switches, validate we have that
	// exact number
	if options.SwitchCount > 0 && len(devices.Devices) != options.SwitchCount {
		log.Errorf("Expecting %d switch(es), found %d, no configuration generated",
			options.SwitchCount, len(devices.Devices))
		http.Error(w, "Expected switch count mismatch",
			http.StatusInternalServerError)
		return
	}

	for _, device := range devices.Devices {
		deviceMap[device.Id] = device
		device.Mac = splitString(device.ChassisId, 2, ":")
	}

	var hosts onosHosts
	err = c.fetch("/onos/v1/hosts", &hosts)
	if err != nil {
		log.Errorf("Unable to retrieve host information from controller: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return

	}

	// If the request specified the number of hosts, validate we have that
	// exact number
	if options.HostCount > 0 && len(hosts.Hosts) != options.HostCount {
		log.Errorf("Expecting %d host(s), found %d, no configuration generated",
			options.HostCount, len(hosts.Hosts))
		http.Error(w, "Expected host count mismatch",
			http.StatusInternalServerError)
		return
	}

	// Use a simple heuristic to determine which switches are edge routers
	// and which are not
	markEdgeRouters(deviceMap, hosts)

	// Generate the configuration file
	cfg := onosConfig{
		Devices: devices.Devices,
		Hosts:   hosts.Hosts,
	}

	funcMap := template.FuncMap{
		// The name "inc" is what the function will be called in the template text.
		"add": func(a, b int) int {
			return a + b
		},
		"gateway": func(ips []string) string {
			if len(ips) > 0 {
				parts := strings.Split(ips[0], ".")
				ip := ""
				for _, v := range parts[:len(parts)-1] {
					ip = ip + v + "."
				}
				return ip + "254/24"
			} else {
				return "0.0.0.254/24"
			}
		},
		"vlan": func(ips []string) string {
			if (len(ips) > 0) {
				return strings.Split(ips[0], ".")[2]
			} else {
				return "0"
			}
		},
	}

	tpl, err := template.New("netconfig.tpl").Funcs(funcMap).ParseFiles("netconfig.tpl")
	if err != nil {
		log.Errorf("Unable to parse template: %s", err)
		http.Error(w, "Template parse error", http.StatusInternalServerError)
		return
	}

	// Write template to buffer, so if there is an error we can return an
	// http error
	buf := new(bytes.Buffer)
	err = tpl.Execute(buf, cfg)
	if err != nil {
		log.Errorf("Unexpected error while processing template: %s", err)
		http.Error(w, "Template processing error", http.StatusInternalServerError)
	}

	w.Write(buf.Bytes())
}

// markEdgeRouters use hueristic to determine and mark switches that act
// as edge routers
func markEdgeRouters(dm map[string]*onosDevice, hosts onosHosts) {
	// Walk the list of know compute nodes (hosts) and if the compute node
	// is connected to a switch, then that switch is an edge router
	for _, host := range hosts.Hosts {
		if device, ok := dm[host.Location.ElementID]; ok {
			(*device).IsEdgeRouter = true
		}
	}
}

// splitString used to convert a string to a psudeo MAC address by
// splitting and separating it with a colon
func splitString(src string, n int, sep string) string {
	r := ""
	for i, c := range src {
		if i > 0 && i%n == 0 {
			r += sep
		}
		r += string(c)
	}
	return r
}

// fetch fetch the specified data from ONOS
func (c *Config) fetch(path string, data interface{}) error {
	resp, err := http.Get(c.connect + path)
	if err != nil {
		return err
	}

	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	err = decoder.Decode(data)
	return err
}
<commit_msg>CORD-1919 only use IPv4 addresses<commit_after>// Copyright 2016 Open Networking Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strings"
	"text/template"
)

type GenerationOptions struct {
	SwitchCount int `json:"switchcount"`
	HostCount   int `json:"hostcount"`
}

func (c *Config) configGenHandler(w http.ResponseWriter, r *http.Request) {
	var options GenerationOptions

	deviceMap := make(map[string]*onosDevice)

	decoder := json.NewDecoder(r.Body)
	defer r.Body.Close()
	if err := decoder.Decode(&options); err != nil {
		log.Errorf("Unable to decode provisioning request options: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var devices onosDevices
	err := c.fetch("/onos/v1/devices", &devices)
	if err != nil {
		log.Errorf("Unable to retrieve device information from controller: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// If the request specified the number of switches, validate we have that
	// exact number
	if options.SwitchCount > 0 && len(devices.Devices) != options.SwitchCount {
		log.Errorf("Expecting %d switch(es), found %d, no configuration generated",
			options.SwitchCount, len(devices.Devices))
		http.Error(w, "Expected switch count mismatch",
			http.StatusInternalServerError)
		return
	}

	for _, device := range devices.Devices {
		deviceMap[device.Id] = device
		device.Mac = splitString(device.ChassisId, 2, ":")
	}

	var hosts onosHosts
	err = c.fetch("/onos/v1/hosts", &hosts)
	if err != nil {
		log.Errorf("Unable to retrieve host information from controller: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return

	}

	// If the request specified the number of hosts, validate we have that
	// exact number
	if options.HostCount > 0 && len(hosts.Hosts) != options.HostCount {
		log.Errorf("Expecting %d host(s), found %d, no configuration generated",
			options.HostCount, len(hosts.Hosts))
		http.Error(w, "Expected host count mismatch",
			http.StatusInternalServerError)
		return
	}

	// Use a simple heuristic to determine which switches are edge routers
	// and which are not
	markEdgeRouters(deviceMap, hosts)

	// Generate the configuration file
	cfg := onosConfig{
		Devices: devices.Devices,
		Hosts:   hosts.Hosts,
	}

	funcMap := template.FuncMap{
		// The name "inc" is what the function will be called in the template text.
		"add": func(a, b int) int {
			return a + b
		},
		"gateway": func(ips []string) string {
			// Find the first v4 address, as determined by
			// not having a ':' in the IP
			for _, ip := range ips {
				if strings.Index(ip, ":") == -1 {
					parts := strings.Split(ip, ".")
					targetIp := ""
					for _, v := range parts[:len(parts)-1] {
						targetIp = targetIp + v + "."
					}
					return targetIp + "254/24"
				}
			}
			return "0.0.0.254/24"
		},
		"vlan": func(ips []string) string {
			// Find the first v4 address, as determined by
			// not having a ':' in the IP
			for _, ip := range ips {
				if strings.Index(ip, ":") == -1 {
					return strings.Split(ip, ".")[2]
				}
			}
			return "0"
		},
	}

	tpl, err := template.New("netconfig.tpl").Funcs(funcMap).ParseFiles("netconfig.tpl")
	if err != nil {
		log.Errorf("Unable to parse template: %s", err)
		http.Error(w, "Template parse error", http.StatusInternalServerError)
		return
	}

	// Write template to buffer, so if there is an error we can return an
	// http error
	buf := new(bytes.Buffer)
	err = tpl.Execute(buf, cfg)
	if err != nil {
		log.Errorf("Unexpected error while processing template: %s", err)
		http.Error(w, "Template processing error", http.StatusInternalServerError)
	}

	w.Write(buf.Bytes())
}

// markEdgeRouters use hueristic to determine and mark switches that act
// as edge routers
func markEdgeRouters(dm map[string]*onosDevice, hosts onosHosts) {
	// Walk the list of know compute nodes (hosts) and if the compute node
	// is connected to a switch, then that switch is an edge router
	for _, host := range hosts.Hosts {
		if device, ok := dm[host.Location.ElementID]; ok {
			(*device).IsEdgeRouter = true
		}
	}
}

// splitString used to convert a string to a psudeo MAC address by
// splitting and separating it with a colon
func splitString(src string, n int, sep string) string {
	r := ""
	for i, c := range src {
		if i > 0 && i%n == 0 {
			r += sep
		}
		r += string(c)
	}
	return r
}

// fetch fetch the specified data from ONOS
func (c *Config) fetch(path string, data interface{}) error {
	resp, err := http.Get(c.connect + path)
	if err != nil {
		return err
	}

	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	err = decoder.Decode(data)
	return err
}
<|endoftext|>


<commit_before>package meritop

// These interface is useful for safety check.
type TGMeta interface {
	GetEpochID() uint64
	GetTaskID() uint64
}

// Task is a logic repersentation of a computing unit.
// Each task contain at least one Node.
// Each task has exact one master Node and might have multiple salve Nodes.
type Task interface {
	// This is useful to bring the task up to speed from scratch or if it recovers.
	Init(taskID uint64, framework Framework, config Config)

	// Task need to finish up for exit, last chance to save work?
	Exit()

	// These are called by framework implementation so that task implementation can
	// reacts to parent or children restart.
	ParentRestart(parentID uint64)
	ChildRestart(childID uint64)

	ParentDie(parentID uint64)
	ChildDie(childID uint64)

	// Ideally, we should also have the following:
	ParentReady(parentID uint64, meta TGMeta)
	ChildReady(childID uint64, meta TGMeta)

	// This give the task an opportunity to cleanup and regroup.
	SetEpoch(epochID uint64)

	// These are payload rpc for application purpose.
	GetFromParent(req TGMeta) TGMeta
	GetFromChild(reg TGMeta) TGMeta
}

// Backupable is an interface that task need to implement if they want to have
// hot standby copy. This is another can of beans.
type Backupable interface {
	// Some hooks that need for master slave etc.
	BecameMaster()
	BecameBackup()
}
<commit_msg>Add payload rpc interface<commit_after>package meritop

// These interface is useful for safety check.
type TGMeta interface {
	GetEpochID() uint64
	GetTaskID() uint64
	GetFromTaskID() uint64
	GetUUID() uint64
}

// Task is a logic repersentation of a computing unit.
// Each task contain at least one Node.
// Each task has exact one master Node and might have multiple salve Nodes.
type Task interface {
	// This is useful to bring the task up to speed from scratch or if it recovers.
	Init(taskID uint64, framework Framework, config Config)

	// Task need to finish up for exit, last chance to save work?
	Exit()

	// These are called by framework implementation so that task implementation can
	// reacts to parent or children restart.
	ParentRestart(parentID uint64)
	ChildRestart(childID uint64)

	ParentDie(parentID uint64)
	ChildDie(childID uint64)

	// Ideally, we should also have the following:
	ParentReady(parentID uint64, meta TGMeta)
	ChildReady(childID uint64, meta TGMeta)

	// This give the task an opportunity to cleanup and regroup.
	SetEpoch(epochID uint64)

	// These are payload for application purpose.
	ServeAsParent(req TGMeta) TGMeta
	ServeAsChild(reg TGMeta) TGMeta

	ParentDataReady(req, response TGMeta)
	ChildDataReady(req, response TGMeta)
}

// Backupable is an interface that task need to implement if they want to have
// hot standby copy. This is another can of beans.
type Backupable interface {
	// Some hooks that need for master slave etc.
	BecameMaster()
	BecameBackup()
}
<|endoftext|>


<commit_before>package slack

import (
	"errors"
	"net/url"
	"strconv"
)

const (
	DEFAULT_LOGINS_COUNT   = 100
	DEFAULT_LOGINS_PAGE    = 1
)

type TeamResponse struct {
	Team TeamInfo `json:"team"`
	SlackResponse
}

type TeamInfo struct {
	ID          string                 `json:"id"`
	Name        string                 `json:"name"`
	Domain      string                 `json:"domain"`
	EmailDomain string                 `json:"email_domain"`
	Icon        map[string]interface{} `json:"icon"`
}

type LoginResponse struct {
	Logins []Login `json:"logins"`
	Paging         `json:"paging"`
	SlackResponse
}

type Login struct {
	UserID    string `json:"user_id"`
	Username  string `json:"username"`
	DateFirst int    `json:"date_first"`
	DateLast  int    `json:"date_last"`
	Count     int    `json:"count"`
	IP        string `json:"ip"`
	UserAgent string `json:"user_agent"`
	ISP       string `json:"isp"`
	Country   string `json:"country"`
	Region    string `json:"region"`
}

type BillableInfoResponse struct {
	BillableInfo map[string]BillingActive `json:"billable_info"`
	SlackResponse

}

type BillingActive struct {
	BillingActive map[string]bool `json:"billing_active"`
}

// AccessLogParameters contains all the parameters necessary (including the optional ones) for a GetAccessLogs() request
type AccessLogParameters struct {
	Count         int
	Page          int
}

// NewAccessLogParameters provides an instance of AccessLogParameters with all the sane default values set
func NewAccessLogParameters() AccessLogParameters {
	return AccessLogParameters{
		Count: DEFAULT_LOGINS_COUNT,
		Page:  DEFAULT_LOGINS_PAGE,
	}
}

func teamRequest(path string, values url.Values, debug bool) (*TeamResponse, error) {
	response := &TeamResponse{}
	err := post(path, values, response, debug)
	if err != nil {
		return nil, err
	}

	if !response.Ok {
		return nil, errors.New(response.Error)
	}

	return response, nil
}

func billableInfoRequest(path string, values url.Values, debug bool) (*BillableInfoResponse, error) {
	response := &BillableInfoResponse{}
	err := post(path, values, response, debug)
	if err != nil {
		return nil, err
	}

	if !response.Ok {
		return nil, errors.New(response.Error)
	}

	return response, nil
}

func accessLogsRequest(path string, values url.Values, debug bool) (*LoginResponse, error) {
	response := &LoginResponse{}
	err := post(path, values, response, debug)
	if err != nil {
		return nil, err
	}
	if !response.Ok {
		return nil, errors.New(response.Error)
	}
	return response, nil
}

// GetTeamInfo gets the Team Information of the user
func (api *Client) GetTeamInfo() (*TeamInfo, error) {
	values := url.Values{
		"token": {api.config.token},
	}

	response, err := teamRequest("team.info", values, api.debug)
	if err != nil {
		return nil, err
	}
	return &response.Team, nil
}

// GetAccessLogs retrieves a page of logins according to the parameters given
func (api *Client) GetAccessLogs(params AccessLogParameters) ([]Login, *Paging, error) {
	values := url.Values{
		"token": {api.config.token},
	}
	if params.Count != DEFAULT_LOGINS_COUNT {
		values.Add("count", strconv.Itoa(params.Count))
	}
	if params.Page != DEFAULT_LOGINS_PAGE {
		values.Add("page", strconv.Itoa(params.Page))
	}
	response, err := accessLogsRequest("team.accessLogs", values, api.debug)
	if err != nil {
		return nil, nil, err
	}
	return response.Logins, &response.Paging, nil
}

func (api *Client) GetBillableInfo(user string) (map[string]BillingActive, error) {
	values := url.Values{
		"token": {api.config.token},
		"user": {user},
	}

	response, err := billableInfoRequest("team.billableInfo", values, api.debug)
	if err != nil {
		return nil, err
	}
	return response.BillableInfo, nil

}
<commit_msg>Return boolean for billing_active<commit_after>package slack

import (
	"errors"
	"net/url"
	"strconv"
)

const (
	DEFAULT_LOGINS_COUNT   = 100
	DEFAULT_LOGINS_PAGE    = 1
)

type TeamResponse struct {
	Team TeamInfo `json:"team"`
	SlackResponse
}

type TeamInfo struct {
	ID          string                 `json:"id"`
	Name        string                 `json:"name"`
	Domain      string                 `json:"domain"`
	EmailDomain string                 `json:"email_domain"`
	Icon        map[string]interface{} `json:"icon"`
}

type LoginResponse struct {
	Logins []Login `json:"logins"`
	Paging         `json:"paging"`
	SlackResponse
}

type Login struct {
	UserID    string `json:"user_id"`
	Username  string `json:"username"`
	DateFirst int    `json:"date_first"`
	DateLast  int    `json:"date_last"`
	Count     int    `json:"count"`
	IP        string `json:"ip"`
	UserAgent string `json:"user_agent"`
	ISP       string `json:"isp"`
	Country   string `json:"country"`
	Region    string `json:"region"`
}

type BillableInfoResponse struct {
	BillableInfo map[string]BillingActive `json:"billable_info"`
	SlackResponse

}

type BillingActive struct {
	BillingActive bool `json:"billing_active"`
}

// AccessLogParameters contains all the parameters necessary (including the optional ones) for a GetAccessLogs() request
type AccessLogParameters struct {
	Count         int
	Page          int
}

// NewAccessLogParameters provides an instance of AccessLogParameters with all the sane default values set
func NewAccessLogParameters() AccessLogParameters {
	return AccessLogParameters{
		Count: DEFAULT_LOGINS_COUNT,
		Page:  DEFAULT_LOGINS_PAGE,
	}
}

func teamRequest(path string, values url.Values, debug bool) (*TeamResponse, error) {
	response := &TeamResponse{}
	err := post(path, values, response, debug)
	if err != nil {
		return nil, err
	}

	if !response.Ok {
		return nil, errors.New(response.Error)
	}

	return response, nil
}

func billableInfoRequest(path string, values url.Values, debug bool) (*BillableInfoResponse, error) {
	response := &BillableInfoResponse{}
	err := post(path, values, response, debug)
	if err != nil {
		return nil, err
	}

	if !response.Ok {
		return nil, errors.New(response.Error)
	}

	return response, nil
}

func accessLogsRequest(path string, values url.Values, debug bool) (*LoginResponse, error) {
	response := &LoginResponse{}
	err := post(path, values, response, debug)
	if err != nil {
		return nil, err
	}
	if !response.Ok {
		return nil, errors.New(response.Error)
	}
	return response, nil
}

// GetTeamInfo gets the Team Information of the user
func (api *Client) GetTeamInfo() (*TeamInfo, error) {
	values := url.Values{
		"token": {api.config.token},
	}

	response, err := teamRequest("team.info", values, api.debug)
	if err != nil {
		return nil, err
	}
	return &response.Team, nil
}

// GetAccessLogs retrieves a page of logins according to the parameters given
func (api *Client) GetAccessLogs(params AccessLogParameters) ([]Login, *Paging, error) {
	values := url.Values{
		"token": {api.config.token},
	}
	if params.Count != DEFAULT_LOGINS_COUNT {
		values.Add("count", strconv.Itoa(params.Count))
	}
	if params.Page != DEFAULT_LOGINS_PAGE {
		values.Add("page", strconv.Itoa(params.Page))
	}
	response, err := accessLogsRequest("team.accessLogs", values, api.debug)
	if err != nil {
		return nil, nil, err
	}
	return response.Logins, &response.Paging, nil
}

func (api *Client) GetBillableInfo(user string) (map[string]BillingActive, error) {
	values := url.Values{
		"token": {api.config.token},
		"user": {user},
	}

	response, err := billableInfoRequest("team.billableInfo", values, api.debug)
	if err != nil {
		return nil, err
	}
	return response.BillableInfo, nil

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"strings"
	"sync"
)

var rmFlags = flag.NewFlagSet("rm", flag.ExitOnError)
var rmRecurse = rmFlags.Bool("r", false, "Recursively delete")
var rmVerbose = rmFlags.Bool("v", false, "Verbose")
var rmWg = sync.WaitGroup{}
var rmCh = make(chan string, 100)

func rmDashR(baseUrl string) {
	for strings.HasSuffix(baseUrl, "/") {
		baseUrl = baseUrl[:len(baseUrl)-1]
	}

	listing, err := listStuff(baseUrl)
	if err != nil {
		log.Fatalf("Error listing files: %v", err)
	}
	for fn := range listing.Files {
		rmCh <- baseUrl + "/" + fn
	}
	for dn := range listing.Dirs {
		if *rmVerbose {
			log.Printf("Recursing into %v/%v", baseUrl, dn)
		}
		rmDashR(baseUrl + "/" + dn)
	}
}

func rmFile(u string) error {
	req, err := http.NewRequest("DELETE", u, nil)
	if err != nil {
		return err
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	res.Body.Close()
	if res.StatusCode != 204 && res.StatusCode != 404 {
		return fmt.Errorf("Unexpected status deleting %v: %v",
			u, err)
	}
	return nil
}

func rmWorker() {
	defer rmWg.Done()

	for u := range rmCh {
		if *rmVerbose {
			log.Printf("Deleting %v", u)
		}

		err := rmFile(u)
		if err != nil {
			log.Fatalf("Error removing %v: %v", u, err)
		}
	}
}

func rmCommand(u string, args []string) {
	rmFlags.Parse(args)

	if rmFlags.NArg() < 1 {
		log.Fatalf("Filename is required")
	}

	for i := 0; i < 4; i++ {
		rmWg.Add(1)
		go rmWorker()
	}

	for _, path := range rmFlags.Args() {
		ru := relativeUrl(u, path)
		if *rmRecurse {
			rmDashR(ru)
		} else {
			rmCh <- ru
		}
	}
	close(rmCh)

	rmWg.Wait()
}
<commit_msg>Added -n to CLI rm<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"strings"
	"sync"
)

var rmFlags = flag.NewFlagSet("rm", flag.ExitOnError)
var rmRecurse = rmFlags.Bool("r", false, "Recursively delete")
var rmVerbose = rmFlags.Bool("v", false, "Verbose")
var rmNoop = rmFlags.Bool("n", false, "Dry run")
var rmWg = sync.WaitGroup{}
var rmCh = make(chan string, 100)

func rmDashR(baseUrl string) {
	for strings.HasSuffix(baseUrl, "/") {
		baseUrl = baseUrl[:len(baseUrl)-1]
	}

	listing, err := listStuff(baseUrl)
	if err != nil {
		log.Fatalf("Error listing files: %v", err)
	}
	for fn := range listing.Files {
		rmCh <- baseUrl + "/" + fn
	}
	for dn := range listing.Dirs {
		if *rmVerbose {
			log.Printf("Recursing into %v/%v", baseUrl, dn)
		}
		rmDashR(baseUrl + "/" + dn)
	}
}

func rmFile(u string) error {
	if *rmNoop {
		return nil
	}
	req, err := http.NewRequest("DELETE", u, nil)
	if err != nil {
		return err
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	res.Body.Close()
	if res.StatusCode != 204 && res.StatusCode != 404 {
		return fmt.Errorf("Unexpected status deleting %v: %v",
			u, err)
	}
	return nil
}

func rmWorker() {
	defer rmWg.Done()

	for u := range rmCh {
		if *rmVerbose {
			log.Printf("Deleting %v", u)
		}

		err := rmFile(u)
		if err != nil {
			log.Fatalf("Error removing %v: %v", u, err)
		}
	}
}

func rmCommand(u string, args []string) {
	rmFlags.Parse(args)

	if rmFlags.NArg() < 1 {
		log.Fatalf("Filename is required")
	}

	for i := 0; i < 4; i++ {
		rmWg.Add(1)
		go rmWorker()
	}

	for _, path := range rmFlags.Args() {
		ru := relativeUrl(u, path)
		if *rmRecurse {
			rmDashR(ru)
		} else {
			rmCh <- ru
		}
	}
	close(rmCh)

	rmWg.Wait()
}
<|endoftext|>


<commit_before>package migrations

import (
	"time"

	"strings"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Seklfreak/Robyul2/models"
	"github.com/cheggaaa/pb"
	"github.com/globalsign/mgo/bson"
	"github.com/gorethink/gorethink"
)

func m67_migration_table_names() {
	if !TableExists("names") {
		return
	}

	cache.GetLogger().WithField("module", "migrations").Info("moving names to mongodb")

	cursor, err := gorethink.Table("names").Count().Run(helpers.GetDB())
	if err != nil {
		panic(err)
	}
	defer cursor.Close()

	var numberOfElements int
	cursor.One(&numberOfElements)

	cursor, err = gorethink.Table("names").Run(helpers.GetDB())
	if err != nil {
		panic(err)
	}
	defer cursor.Close()

	var previousEntry struct {
		ID        bson.ObjectId `bson:"_id,omitempty"`
		ChangedAt time.Time
		GuildID   string
		UserID    string
		Nickname  string
		Username  string
	}
	var rethinkdbEntry struct {
		ID        string    `rethink:"id,omitempty"`
		ChangedAt time.Time `rethink:"changed_at"`
		GuildID   string    `rethink:"guild_id"`
		UserID    string    `rethink:"user_id"`
		Nickname  string    `rethink:"nickname"`
		Username  string    `rethink:"username"`
	}
	bar := pb.StartNew(numberOfElements)
	for cursor.Next(&rethinkdbEntry) {
		if rethinkdbEntry.GuildID == "global" {
			// check for username duplicate first
			err = helpers.MdbOneWithoutLogging(
				helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": rethinkdbEntry.UserID, "guildid": "global"}).Sort("-changedat"),
				&previousEntry,
			)
			if err == nil {
				if previousEntry.Username == rethinkdbEntry.Username {
					cache.GetLogger().WithField("module", "migrations").Infof("skipped username %s for #%s because already in DB", rethinkdbEntry.Username, rethinkdbEntry.UserID)
					bar.Increment()
					continue
				}
			} else {
				if !strings.Contains(err.Error(), "not found") {
					panic(err)
				}
			}
		} else {
			// check for nickname duplicate first
			err = helpers.MdbOneWithoutLogging(
				helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": rethinkdbEntry.UserID, "guildid": rethinkdbEntry.GuildID}).Sort("-changedat"),
				&previousEntry,
			)
			if err == nil {
				if previousEntry.Nickname == rethinkdbEntry.Nickname {
					cache.GetLogger().WithField("module", "migrations").Infof("skipped nickname %s for #%s because already in DB", rethinkdbEntry.Nickname, rethinkdbEntry.UserID)
					bar.Increment()
					continue
				}
			} else {
				if !strings.Contains(err.Error(), "not found") {
					panic(err)
				}
			}
		}

		err = helpers.MDbUpsertWithoutLogging(
			models.NamesTable,
			bson.M{"guildid": rethinkdbEntry.GuildID, "userid": rethinkdbEntry.UserID, "changedat": rethinkdbEntry.ChangedAt, "nickname": rethinkdbEntry.Nickname, "username": rethinkdbEntry.Username},
			models.NamesEntry{
				ChangedAt: rethinkdbEntry.ChangedAt,
				GuildID:   rethinkdbEntry.GuildID,
				UserID:    rethinkdbEntry.UserID,
				Nickname:  rethinkdbEntry.Nickname,
				Username:  rethinkdbEntry.Username,
			},
		)
		if err != nil {
			panic(err)
		}

		bar.Increment()
	}

	if cursor.Err() != nil {
		panic(err)
	}
	bar.Finish()

	cache.GetLogger().WithField("module", "migrations").Info("dropping rethinkdb names")
	_, err = gorethink.TableDrop("names").Run(helpers.GetDB())
	if err != nil {
		panic(err)
	}
}
<commit_msg>[names+mongodb] improves migration performance 🐌<commit_after>package migrations

import (
	"time"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Seklfreak/Robyul2/models"
	"github.com/cheggaaa/pb"
	"github.com/gorethink/gorethink"
)

func m67_migration_table_names() {
	if !TableExists("names") {
		return
	}

	cache.GetLogger().WithField("module", "migrations").Info("moving names to mongodb")

	cursor, err := gorethink.Table("names").Count().Run(helpers.GetDB())
	if err != nil {
		panic(err)
	}
	defer cursor.Close()

	var numberOfElements int
	cursor.One(&numberOfElements)

	cursor, err = gorethink.Table("names").Run(helpers.GetDB())
	if err != nil {
		panic(err)
	}
	defer cursor.Close()

	previousUsernames := make(map[string]string, 0)
	previousNicknames := make(map[string]string, 0)
	var rethinkdbEntry struct {
		ID        string    `rethink:"id,omitempty"`
		ChangedAt time.Time `rethink:"changed_at"`
		GuildID   string    `rethink:"guild_id"`
		UserID    string    `rethink:"user_id"`
		Nickname  string    `rethink:"nickname"`
		Username  string    `rethink:"username"`
	}
	bar := pb.StartNew(numberOfElements)
	for cursor.Next(&rethinkdbEntry) {
		if rethinkdbEntry.GuildID == "global" {
			// check for username duplicate first
			if previousUsername, ok := previousUsernames[rethinkdbEntry.UserID]; ok && previousUsername == rethinkdbEntry.Username {
				cache.GetLogger().WithField("module", "migrations").Infof("skipped username %s for #%s because already in DB", rethinkdbEntry.Username, rethinkdbEntry.UserID)
				bar.Increment()
				continue
			}
			previousUsernames[rethinkdbEntry.UserID] = rethinkdbEntry.Username
		} else {
			// check for nickname duplicate first
			if previousNickname, ok := previousNicknames[rethinkdbEntry.UserID+rethinkdbEntry.GuildID]; ok && previousNickname == rethinkdbEntry.Nickname {
				cache.GetLogger().WithField("module", "migrations").Infof("skipped nickname %s for #%s because already in DB", rethinkdbEntry.Nickname, rethinkdbEntry.UserID)
				bar.Increment()
				continue
			}
			previousNicknames[rethinkdbEntry.UserID+rethinkdbEntry.GuildID] = rethinkdbEntry.Nickname
		}

		_, err = helpers.MDbInsertWithoutLogging(
			models.NamesTable,
			models.NamesEntry{
				ChangedAt: rethinkdbEntry.ChangedAt,
				GuildID:   rethinkdbEntry.GuildID,
				UserID:    rethinkdbEntry.UserID,
				Nickname:  rethinkdbEntry.Nickname,
				Username:  rethinkdbEntry.Username,
			},
		)
		if err != nil {
			panic(err)
		}

		bar.Increment()
	}

	if cursor.Err() != nil {
		panic(err)
	}
	bar.Finish()

	cache.GetLogger().WithField("module", "migrations").Info("dropping rethinkdb names")
	_, err = gorethink.TableDrop("names").Run(helpers.GetDB())
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main
import (
    "encoding/json"
    "net/http"
    "github.com/go-martini/martini"
)

func main() {
    m := martini.Classic()
    m.Get("/api/v3/json", func(res http.ResponseWriter) string {
        res.Header().Add("Server", "GoMartini/1.0")
        b, err := json.Marshal(map[string]interface{}{
            "code": 0, "desc": "test api for go martini",
        })
        if err != nil {
            // error
        }
        return string(b)
    })
    http.ListenAndServe(":8080", m)
}
<commit_msg>update go martini<commit_after>package main
import (
    "os"
    "fmt"
    "encoding/json"
    "net/http"
    "github.com/go-martini/martini"
)

func main() {
    fmt.Println("go martini web server")
    if len(os.Args) <= 1 {
        fmt.Println("Usage:", os.Args[0], "<port>")
        fmt.Println("   port: the port to listen at.")
        fmt.Println("For example:")
        fmt.Println("   ", os.Args[0], 8080)
        return
    }
    fmt.Println("listen at", os.Args[1])

    m := martini.Classic()
    m.Get("/api/v3/json", func(res http.ResponseWriter) string {
        res.Header().Add("Server", "GoMartini/1.0")
        b, err := json.Marshal(map[string]interface{}{
            "code": 0, "desc": "test api for go martini",
        })
        if err != nil {
            // error
        }
        return string(b)
    })
    http.ListenAndServe(":" + os.Args[1], m)
}
<|endoftext|>


<commit_before>package txbuilder

import (
	"context"
	"encoding/hex"
	"fmt"
	"reflect"
	"testing"
	"time"

	"golang.org/x/crypto/sha3"

	"chain/crypto/ed25519"
	"chain/crypto/ed25519/hd25519"
	"chain/database/pg"
	"chain/database/pg/pgtest"
	"chain/encoding/json"
	"chain/errors"
	"chain/protocol/bc"
	"chain/protocol/mempool"
	"chain/protocol/vm"
	"chain/protocol/vmutil"
	"chain/testutil"
)

type testAction bc.AssetAmount

func (t testAction) Build(ctx context.Context) ([]*bc.TxInput, []*bc.TxOutput, []*Input, error) {
	in := bc.NewSpendInput([32]byte{255}, 0, nil, t.AssetID, t.Amount, nil, nil)
	tplIn := &Input{
		WitnessComponents: []WitnessComponent{
			DataWitness("redeem"),
		},
	}
	change := bc.NewTxOutput(t.AssetID, t.Amount, []byte("change"), nil)
	return []*bc.TxInput{in}, []*bc.TxOutput{change}, []*Input{tplIn}, nil
}

func newControlProgramAction(assetAmt bc.AssetAmount, script []byte) *ControlProgramAction {
	return &ControlProgramAction{
		Params: struct {
			bc.AssetAmount
			Program    json.HexBytes `json:"control_program"`
			AssetAlias string        `json:"asset_alias"`
		}{assetAmt, script, ""},
	}
}

func TestBuild(t *testing.T) {
	ctx := pg.NewContext(context.Background(), pgtest.NewTx(t))
	pool := mempool.New()

	err := pool.Insert(ctx, &bc.Tx{
		Hash: [32]byte{255},
		TxData: bc.TxData{
			Outputs: []*bc.TxOutput{
				bc.NewTxOutput([32]byte{1}, 5, nil, nil),
			},
		},
	})
	if err != nil {
		testutil.FatalErr(t, err)
	}

	actions := []Action{
		newControlProgramAction(bc.AssetAmount{AssetID: [32]byte{2}, Amount: 6}, []byte("dest")),
		testAction(bc.AssetAmount{AssetID: [32]byte{1}, Amount: 5}),
	}
	expiryTime := bc.Millis(time.Now().Add(time.Minute))
	got, err := Build(ctx, nil, actions, nil, expiryTime)
	if err != nil {
		t.Log(errors.Stack(err))
		t.Fatal(err)
	}

	want := &Template{
		Unsigned: &bc.TxData{
			Version: 1,
			MaxTime: expiryTime,
			Inputs: []*bc.TxInput{
				bc.NewSpendInput([32]byte{255}, 0, nil, [32]byte{1}, 5, nil, nil),
			},
			Outputs: []*bc.TxOutput{
				bc.NewTxOutput([32]byte{2}, 6, []byte("dest"), nil),
				bc.NewTxOutput([32]byte{1}, 5, []byte("change"), nil),
			},
		},
		Inputs: []*Input{{
			WitnessComponents: []WitnessComponent{
				DataWitness("redeem"),
			},
		}},
	}

	if !reflect.DeepEqual(got.Unsigned, want.Unsigned) {
		t.Errorf("got tx:\n\t%#v\nwant tx:\n\t%#v", got.Unsigned, want.Unsigned)
		t.Errorf("got tx inputs:\n\t%#v\nwant tx inputs:\n\t%#v", got.Unsigned.Inputs, want.Unsigned.Inputs)
		t.Errorf("got tx outputs:\n\t%#v\nwant tx outputs:\n\t%#v", got.Unsigned.Outputs, want.Unsigned.Outputs)
	}

	if !reflect.DeepEqual(got.Inputs, want.Inputs) {
		t.Errorf("got inputs:\n\t%#v\nwant inputs:\n\t%#v", got.Inputs, want.Inputs)
	}
}

func programWithDefinition(pubkeys []ed25519.PublicKey, nrequired int, definition []byte) ([]byte, error) {
	issuanceProg := vmutil.P2DPMultiSigProgram(pubkeys, nrequired)
	builder := vmutil.NewBuilder()
	builder.AddData(definition).AddOp(vm.OP_DROP)
	builder.AddRawBytes(issuanceProg)
	return builder.Program, nil
}

func TestMaterializeWitnesses(t *testing.T) {
	var initialBlockHash bc.Hash
	privkey, pubkey, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	issuanceProg := vmutil.P2DPMultiSigProgram([]ed25519.PublicKey{pubkey.Key}, 1)
	assetID := bc.ComputeAssetID(issuanceProg, initialBlockHash, 1)
	outscript := mustDecodeHex("76a914c5d128911c28776f56baaac550963f7b88501dc388c0")
	now := time.Unix(233400000, 0)
	unsigned := &bc.TxData{
		Version: 1,
		Inputs: []*bc.TxInput{
			bc.NewIssuanceInput(now, now.Add(time.Hour), initialBlockHash, 5, issuanceProg, nil, nil),
		},
		Outputs: []*bc.TxOutput{
			bc.NewTxOutput(assetID, 5, outscript, nil),
		},
	}

	witnessData := mustDecodeHex("5221033dda0a756db51f76a4f394161614f01df4061644c514fde3994adbe4a3a2d21621038a0f0a8d593773abcd8c878f8777c57986f9f84886c8dde0cf00fdc2c89f0c592103b9e805011523bb28eedb3fcfff8924684a91116a76408fe0972805295e50e15d53ae")
	prog, err := vm.Compile(fmt.Sprintf("0x804cf05736 MAXTIME LESSTHAN VERIFY 0 5 0x%x 1 0x76a914c5d128911c28776f56baaac550963f7b88501dc388c0 FINDOUTPUT", assetID[:]))
	h := sha3.Sum256(prog)
	sig := ed25519.Sign(privkey.Key, h[:])
	if err != nil {
		t.Fatal(err)
	}

	tpl := &Template{
		Unsigned: unsigned,
		Inputs: []*Input{{
			WitnessComponents: []WitnessComponent{
				&SignatureWitness{
					Quorum: 1,
					Keys: []KeyID{{
						XPub:           pubkey.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					}},
					Constraints: []Constraint{
						TTLConstraint(bc.Millis(now.Add(time.Hour))),
						&PayConstraint{
							AssetAmount: bc.AssetAmount{
								AssetID: assetID,
								Amount:  5,
							},
							Program: outscript,
						},
					},
					Sigs: []json.HexBytes{sig},
				},
				DataWitness(witnessData),
			},
		}},
	}

	want := [][]byte{
		sig,
		prog,
		witnessData,
	}

	tx, err := MaterializeWitnesses(tpl)
	if err != nil {
		t.Fatal(withStack(err))
	}

	got := tx.Inputs[0].InputWitness
	if !reflect.DeepEqual(got, want) {
		t.Errorf("got input witness %v, want input witness %v", got, want)
	}
}

func TestSignatureWitnessMaterialize(t *testing.T) {
	var initialBlockHash bc.Hash
	privkey1, pubkey1, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	privkey2, pubkey2, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	privkey3, pubkey3, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	issuanceProg := vmutil.P2DPMultiSigProgram([]ed25519.PublicKey{pubkey1.Key, pubkey2.Key, pubkey3.Key}, 2)
	assetID := bc.ComputeAssetID(issuanceProg, initialBlockHash, 1)
	outscript := mustDecodeHex("76a914c5d128911c28776f56baaac550963f7b88501dc388c0")
	now := time.Unix(233400000, 0)
	unsigned := &bc.TxData{
		Version: 1,
		Inputs: []*bc.TxInput{
			bc.NewIssuanceInput(now, now.Add(time.Hour), initialBlockHash, 100, issuanceProg, nil, nil),
		},
		Outputs: []*bc.TxOutput{
			bc.NewTxOutput(assetID, 100, outscript, nil),
		},
	}

	tpl := &Template{
		Unsigned: unsigned,
	}
	h := tpl.Hash(0, bc.SigHashAll)
	builder := vmutil.NewBuilder()
	builder.AddData(h[:])
	builder.AddInt64(1).AddOp(vm.OP_TXSIGHASH).AddOp(vm.OP_EQUAL)
	msg := sha3.Sum256(builder.Program)
	sig1 := ed25519.Sign(privkey1.Key, msg[:])
	sig2 := ed25519.Sign(privkey2.Key, msg[:])
	sig3 := ed25519.Sign(privkey3.Key, msg[:])
	tpl.Inputs = []*Input{{
		WitnessComponents: []WitnessComponent{
			&SignatureWitness{
				Quorum: 2,
				Keys: []KeyID{
					{
						XPub:           pubkey1.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					},
					{
						XPub:           pubkey2.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					},
					{
						XPub:           pubkey3.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					},
				},
				Constraints: []Constraint{},
				Sigs:        []json.HexBytes{sig1, sig2, sig3},
			},
		},
	}}

	_, err = MaterializeWitnesses(tpl)
	if err != nil {
		t.Fatal(withStack(err))
	}
}

func withStack(err error) string {
	s := err.Error()
	for _, frame := range errors.Stack(err) {
		s += "\n" + frame.String()
	}
	return s
}

func mustDecodeHex(str string) []byte {
	data, err := hex.DecodeString(str)
	if err != nil {
		panic(err)
	}
	return data
}
<commit_msg>core/txbuilder: add more robust test cases for TestSignatureWitnessMaterialize<commit_after>package txbuilder

import (
	"context"
	"encoding/hex"
	"fmt"
	"reflect"
	"testing"
	"time"

	"golang.org/x/crypto/sha3"

	"chain/crypto/ed25519"
	"chain/crypto/ed25519/hd25519"
	"chain/database/pg"
	"chain/database/pg/pgtest"
	"chain/encoding/json"
	"chain/errors"
	"chain/protocol/bc"
	"chain/protocol/mempool"
	"chain/protocol/vm"
	"chain/protocol/vmutil"
	"chain/testutil"
)

type testAction bc.AssetAmount

func (t testAction) Build(ctx context.Context) ([]*bc.TxInput, []*bc.TxOutput, []*Input, error) {
	in := bc.NewSpendInput([32]byte{255}, 0, nil, t.AssetID, t.Amount, nil, nil)
	tplIn := &Input{
		WitnessComponents: []WitnessComponent{
			DataWitness("redeem"),
		},
	}
	change := bc.NewTxOutput(t.AssetID, t.Amount, []byte("change"), nil)
	return []*bc.TxInput{in}, []*bc.TxOutput{change}, []*Input{tplIn}, nil
}

func newControlProgramAction(assetAmt bc.AssetAmount, script []byte) *ControlProgramAction {
	return &ControlProgramAction{
		Params: struct {
			bc.AssetAmount
			Program    json.HexBytes `json:"control_program"`
			AssetAlias string        `json:"asset_alias"`
		}{assetAmt, script, ""},
	}
}

func TestBuild(t *testing.T) {
	ctx := pg.NewContext(context.Background(), pgtest.NewTx(t))
	pool := mempool.New()

	err := pool.Insert(ctx, &bc.Tx{
		Hash: [32]byte{255},
		TxData: bc.TxData{
			Outputs: []*bc.TxOutput{
				bc.NewTxOutput([32]byte{1}, 5, nil, nil),
			},
		},
	})
	if err != nil {
		testutil.FatalErr(t, err)
	}

	actions := []Action{
		newControlProgramAction(bc.AssetAmount{AssetID: [32]byte{2}, Amount: 6}, []byte("dest")),
		testAction(bc.AssetAmount{AssetID: [32]byte{1}, Amount: 5}),
	}
	expiryTime := bc.Millis(time.Now().Add(time.Minute))
	got, err := Build(ctx, nil, actions, nil, expiryTime)
	if err != nil {
		t.Log(errors.Stack(err))
		t.Fatal(err)
	}

	want := &Template{
		Unsigned: &bc.TxData{
			Version: 1,
			MaxTime: expiryTime,
			Inputs: []*bc.TxInput{
				bc.NewSpendInput([32]byte{255}, 0, nil, [32]byte{1}, 5, nil, nil),
			},
			Outputs: []*bc.TxOutput{
				bc.NewTxOutput([32]byte{2}, 6, []byte("dest"), nil),
				bc.NewTxOutput([32]byte{1}, 5, []byte("change"), nil),
			},
		},
		Inputs: []*Input{{
			WitnessComponents: []WitnessComponent{
				DataWitness("redeem"),
			},
		}},
	}

	if !reflect.DeepEqual(got.Unsigned, want.Unsigned) {
		t.Errorf("got tx:\n\t%#v\nwant tx:\n\t%#v", got.Unsigned, want.Unsigned)
		t.Errorf("got tx inputs:\n\t%#v\nwant tx inputs:\n\t%#v", got.Unsigned.Inputs, want.Unsigned.Inputs)
		t.Errorf("got tx outputs:\n\t%#v\nwant tx outputs:\n\t%#v", got.Unsigned.Outputs, want.Unsigned.Outputs)
	}

	if !reflect.DeepEqual(got.Inputs, want.Inputs) {
		t.Errorf("got inputs:\n\t%#v\nwant inputs:\n\t%#v", got.Inputs, want.Inputs)
	}
}

func TestMaterializeWitnesses(t *testing.T) {
	var initialBlockHash bc.Hash
	privkey, pubkey, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	issuanceProg := vmutil.P2DPMultiSigProgram([]ed25519.PublicKey{pubkey.Key}, 1)
	assetID := bc.ComputeAssetID(issuanceProg, initialBlockHash, 1)
	outscript := mustDecodeHex("76a914c5d128911c28776f56baaac550963f7b88501dc388c0")
	now := time.Unix(233400000, 0)
	unsigned := &bc.TxData{
		Version: 1,
		Inputs: []*bc.TxInput{
			bc.NewIssuanceInput(now, now.Add(time.Hour), initialBlockHash, 5, issuanceProg, nil, nil),
		},
		Outputs: []*bc.TxOutput{
			bc.NewTxOutput(assetID, 5, outscript, nil),
		},
	}

	witnessData := mustDecodeHex("5221033dda0a756db51f76a4f394161614f01df4061644c514fde3994adbe4a3a2d21621038a0f0a8d593773abcd8c878f8777c57986f9f84886c8dde0cf00fdc2c89f0c592103b9e805011523bb28eedb3fcfff8924684a91116a76408fe0972805295e50e15d53ae")
	prog, err := vm.Compile(fmt.Sprintf("0x804cf05736 MAXTIME LESSTHAN VERIFY 0 5 0x%x 1 0x76a914c5d128911c28776f56baaac550963f7b88501dc388c0 FINDOUTPUT", assetID[:]))
	h := sha3.Sum256(prog)
	sig := ed25519.Sign(privkey.Key, h[:])
	if err != nil {
		t.Fatal(err)
	}

	tpl := &Template{
		Unsigned: unsigned,
		Inputs: []*Input{{
			WitnessComponents: []WitnessComponent{
				&SignatureWitness{
					Quorum: 1,
					Keys: []KeyID{{
						XPub:           pubkey.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					}},
					Constraints: []Constraint{
						TTLConstraint(bc.Millis(now.Add(time.Hour))),
						&PayConstraint{
							AssetAmount: bc.AssetAmount{
								AssetID: assetID,
								Amount:  5,
							},
							Program: outscript,
						},
					},
					Sigs: []json.HexBytes{sig},
				},
				DataWitness(witnessData),
			},
		}},
	}

	want := [][]byte{
		sig,
		prog,
		witnessData,
	}

	tx, err := MaterializeWitnesses(tpl)
	if err != nil {
		t.Fatal(withStack(err))
	}

	got := tx.Inputs[0].InputWitness
	if !reflect.DeepEqual(got, want) {
		t.Errorf("got input witness %v, want input witness %v", got, want)
	}
}

func TestSignatureWitnessMaterialize(t *testing.T) {
	var initialBlockHash bc.Hash
	privkey1, pubkey1, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	privkey2, pubkey2, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	privkey3, pubkey3, err := hd25519.NewXKeys(nil)
	if err != nil {
		t.Fatal(err)
	}
	issuanceProg := vmutil.P2DPMultiSigProgram([]ed25519.PublicKey{pubkey1.Key, pubkey2.Key, pubkey3.Key}, 2)
	assetID := bc.ComputeAssetID(issuanceProg, initialBlockHash, 1)
	outscript := mustDecodeHex("76a914c5d128911c28776f56baaac550963f7b88501dc388c0")
	now := time.Unix(233400000, 0)
	unsigned := &bc.TxData{
		Version: 1,
		Inputs: []*bc.TxInput{
			bc.NewIssuanceInput(now, now.Add(time.Hour), initialBlockHash, 100, issuanceProg, nil, nil),
		},
		Outputs: []*bc.TxOutput{
			bc.NewTxOutput(assetID, 100, outscript, nil),
		},
	}

	tpl := &Template{
		Unsigned: unsigned,
	}
	h := tpl.Hash(0, bc.SigHashAll)
	builder := vmutil.NewBuilder()
	builder.AddData(h[:])
	builder.AddInt64(1).AddOp(vm.OP_TXSIGHASH).AddOp(vm.OP_EQUAL)
	prog := builder.Program
	msg := sha3.Sum256(prog)
	sig1 := ed25519.Sign(privkey1.Key, msg[:])
	sig2 := ed25519.Sign(privkey2.Key, msg[:])
	sig3 := ed25519.Sign(privkey3.Key, msg[:])
	want := [][]byte{
		sig1,
		sig2,
		prog,
	}

	// Test with more signatures than required, in correct order
	tpl.Inputs = []*Input{{
		WitnessComponents: []WitnessComponent{
			&SignatureWitness{
				Quorum: 2,
				Keys: []KeyID{
					{
						XPub:           pubkey1.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					},
					{
						XPub:           pubkey2.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					},
					{
						XPub:           pubkey3.String(),
						DerivationPath: []uint32{0, 0, 0, 0},
					},
				},
				Constraints: []Constraint{},
				Sigs:        []json.HexBytes{sig1, sig2, sig3},
			},
		},
	}}
	tx, err := MaterializeWitnesses(tpl)
	if err != nil {
		t.Fatal(withStack(err))
	}
	got := tx.Inputs[0].InputWitness
	if !reflect.DeepEqual(got, want) {
		t.Errorf("got input witness %v, want input witness %v", got, want)
	}

	// Test with more signatures than required, in incorrect order
	component, ok := tpl.Inputs[0].WitnessComponents[0].(*SignatureWitness)
	if !ok {
		t.Fatal("expecting WitnessComponent of type SignatureWitness")
	}
	component.Sigs = []json.HexBytes{sig3, sig2, sig1}
	tx, err = MaterializeWitnesses(tpl)
	if err != nil {
		t.Fatal(withStack(err))
	}

	got = tx.Inputs[0].InputWitness
	if !reflect.DeepEqual(got, want) {
		t.Errorf("got input witness %v, want input witness %v", got, want)
	}

	// Test with exact amount of signatures required, in correct order
	component.Sigs = []json.HexBytes{sig1, sig2}
	tx, err = MaterializeWitnesses(tpl)
	if err != nil {
		t.Fatal(withStack(err))
	}
	got = tx.Inputs[0].InputWitness
	if !reflect.DeepEqual(got, want) {
		t.Errorf("got input witness %v, want input witness %v", got, want)
	}

	// Test with exact amount of signatures required, in incorrect order
	component.Sigs = []json.HexBytes{sig2, sig1}
	tx, err = MaterializeWitnesses(tpl)
	if err != nil {
		t.Fatal(withStack(err))
	}
	got = tx.Inputs[0].InputWitness
	if !reflect.DeepEqual(got, want) {
		t.Errorf("got input witness %v, want input witness %v", got, want)
	}

	// Test with insufficient amount of signatures required
	component.Sigs = []json.HexBytes{sig2}
	tx, err = MaterializeWitnesses(tpl)
	if errors.Root(err) != ErrMissingSig {
		t.Errorf("got %v, want ErrMissingSig", err)
	}
}

func withStack(err error) string {
	s := err.Error()
	for _, frame := range errors.Stack(err) {
		s += "\n" + frame.String()
	}
	return s
}

func mustDecodeHex(str string) []byte {
	data, err := hex.DecodeString(str)
	if err != nil {
		panic(err)
	}
	return data
}
<|endoftext|>


<commit_before>package cpp

import (
	"bytes"
	"testing"
)

var exprTestCases = []struct {
	expr     string
	expected int64
}{
	{"1", 1},
	{"2", 2},
	{"0x1", 0x1},
	{"0x1", 0x1},
	{"-1", -1},
	{"-2", -2},
	{"0x1234", 0x1234},
	{"foo", 1},
	{"bang", 0},
	{"defined foo", 1},
	{"defined bang", 0},
	{"defined(foo)", 1},
	{"defined(bang)", 0},
}

var testExprPredefined = map[string]struct{}{
	"foo": {},
	"bar": {},
	"baz": {},
}

func TestExprEval(t *testing.T) {
	for idx := range exprTestCases {
		tc := &exprTestCases[idx]
		r := bytes.NewBufferString(tc.expr)
		tokChan := Lex("testcase.c", r)

		var e error = nil
		onErr := func(evalErr error) {
			e = evalErr
		}
		nextTok := func() *Token {
			t := <-tokChan
			return t
		}
		isDefined := func(s string) bool {
			_, ok := testExprPredefined[s]
			return ok
		}

		result := evalIfExpr(isDefined, nextTok, onErr)
		if e != nil {
			t.Errorf("test %s failed - got error <%s>", tc.expr, e)
		} else if result != tc.expected {
			t.Errorf("test %s failed - got %s expected %s", tc.expr, result, tc.expected)
		}
	}
}
<commit_msg>added some tests for cpp expression parser<commit_after>package cpp

import (
	"bytes"
	"testing"
)

var exprTestCases = []struct {
	expr      string
	expected  int64
	expectErr bool
}{
	{"1", 1, false},
	{"2", 2, false},
	{"0x1", 0x1, false},
	{"0x1", 0x1, false},
	{"-1", -1, false},
	{"-2", -2, false},
	{"0x1234", 0x1234, false},
	{"foo", 1, false},
	{"bang", 0, false},
	{"defined foo", 1, false},
	{"defined bang", 0, false},
	{"defined(foo)", 1, false},
	{"defined(bang)", 0, false},
	{"defined", 0, true},
	{"defined(bang", 0, true},
	{"defined bang)", 0, true},
}

var testExprPredefined = map[string]struct{}{
	"foo": {},
	"bar": {},
	"baz": {},
}

func TestExprEval(t *testing.T) {
	for idx := range exprTestCases {
		tc := &exprTestCases[idx]
		r := bytes.NewBufferString(tc.expr)
		tokChan := Lex("testcase.c", r)

		var e error = nil
		onErr := func(evalErr error) {
			e = evalErr
		}
		nextTok := func() *Token {
			t := <-tokChan
			return t
		}
		isDefined := func(s string) bool {
			_, ok := testExprPredefined[s]
			return ok
		}

		result := evalIfExpr(isDefined, nextTok, onErr)
		if e != nil {
			if !tc.expectErr {
				t.Errorf("test %s failed - got error <%s>", tc.expr, e)
			}
		} else if tc.expectErr {
			t.Errorf("test %s failed - expected an error", tc.expr)
		} else if result != tc.expected {
			t.Errorf("test %s failed - got %s expected %s", tc.expr, result, tc.expected)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"runtime/debug"
	"strings"
	"time"

	"code.google.com/p/go-uuid/uuid"
)

var (
	listen           = flag.String("l", ":8888", "port to accept requests")
	targetProduction = flag.String("a", "http://localhost:8080", "where production traffic goes. http://localhost:8080/production")
	altTarget        = flag.String("b", "http://localhost:8081", "where testing traffic goes. response are skipped. http://localhost:8081/test")

	// Hop-by-hop headers. These are removed when sent to the backend.
	// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
	hopHeaders = []string{
		"Connection",
		"Keep-Alive",
		"Proxy-Authenticate",
		"Proxy-Authorization",
		"Te", // canonicalized version of "TE"
		"Trailers",
		"Transfer-Encoding",
		"Upgrade",
	}
)

type Hosts struct {
	Target      url.URL
	Alternative url.URL
}

var hosts Hosts
var client *http.Client
var proxy *httputil.ReverseProxy

type TimeoutTransport struct {
	http.Transport
}

func (t *TimeoutTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	return t.Transport.RoundTrip(req)
}

func clientCall(id string, req, req2 *http.Request) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered in clientCall", r, debug.Stack())
		}
	}()

	resp, err := http.DefaultTransport.RoundTrip(req2)
	if err != nil {
		fmt.Printf("[%v][%v][<B Error>][<%v>][Request: %+v]\n", time.Now().Format(time.RFC3339Nano), id, err, req2)
		return
	}

	r, e := httputil.DumpResponse(resp, true)
	if e != nil {
		logMessage("[%v][%v][<B Error Dump>][<%v>]\n", id, e)
	} else {
		logMessage("[%v][%v][<B Resp>][<%v>]\n", id, string(r))
	}

	io.Copy(ioutil.Discard, resp.Body)
	resp.Body.Close()
}

func teeDirector(req *http.Request) {
	id := uuid.NewUUID().String()
	fmt.Printf("[%v][%v][<Request>][<%+v>]\n", time.Now().Format(time.RFC3339Nano), id, req)

	go clientCall(id, req, duplicateRequest(req))

	targetQuery := hosts.Target.RawQuery
	req.URL.Scheme = hosts.Target.Scheme
	req.URL.Host = hosts.Target.Host
	req.URL.Path = singleJoiningSlash(hosts.Target.Path, req.URL.Path)
	if targetQuery == "" || req.URL.RawQuery == "" {
		req.URL.RawQuery = targetQuery + req.URL.RawQuery
	} else {
		req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
	}
}

func logMessage(message string, id string, logObj interface{}) {
	fmt.Printf(message, time.Now().Format(time.RFC3339Nano), id, logObj)
}

func singleJoiningSlash(a, b string) string {
	aslash := strings.HasSuffix(a, "/")
	bslash := strings.HasPrefix(b, "/")
	switch {
	case aslash && bslash:
		return a + b[1:]
	case !aslash && !bslash:
		return a + "/" + b
	}
	return a + b
}

func duplicateRequest(request *http.Request) (request1 *http.Request) {
	b1 := new(bytes.Buffer)
	b2 := new(bytes.Buffer)
	w := io.MultiWriter(b1, b2)
	io.Copy(w, request.Body)
	request.Body = ioutil.NopCloser(bytes.NewReader(b2.Bytes()))
	bodyReader := ioutil.NopCloser(bytes.NewReader(b1.Bytes()))

	request2 := &http.Request{
		Method: request.Method,
		URL: &url.URL{
			Scheme:   hosts.Alternative.Scheme,
			Host:     hosts.Alternative.Host,
			Path:     singleJoiningSlash(hosts.Alternative.Path, request.URL.Path),
			RawQuery: request.URL.RawQuery,
		},
		Proto:         request.Proto,
		ProtoMajor:    request.ProtoMajor,
		ProtoMinor:    request.ProtoMinor,
		Header:        request.Header,
		Body:          bodyReader,
		ContentLength: request.ContentLength,
		Close:         false,
	}

	// Remove hop-by-hop headers to the backend.  Especially
	// important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.  This
	// is modifying the same underlying map from req (shallow
	// copied above) so we only copy it if necessary.
	copiedHeaders := false
	for _, h := range hopHeaders {
		if request2.Header.Get(h) != "" {
			if !copiedHeaders {
				request2.Header = make(http.Header)
				copyHeader(request2.Header, request.Header)
				copiedHeaders = true
			}
			request2.Header.Del(h)
		}
	}

	return request2
}

func copyHeader(dst, src http.Header) {
	for k, vv := range src {
		for _, v := range vv {
			dst.Add(k, v)
		}
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	dump, e := httputil.DumpRequest(r, true)
	if e != nil {
		logMessage("[%v][%v][<In Error Dump>][<%v>]\n", "", e)
	} else {
		logMessage("[%v][%v][<In Req>][<%v>]\n", "", string(dump))
	}
	proxy.ServeHTTP(w, r)
}

func main() {
	flag.Parse()

	target, _ := url.Parse(*targetProduction)
	alt, _ := url.Parse(*altTarget)
	client = &http.Client{
		Timeout: time.Millisecond * 2000,
	}

	hosts = Hosts{
		Target:      *target,
		Alternative: *alt,
	}

	u, _ := url.Parse(*targetProduction)
	proxy = httputil.NewSingleHostReverseProxy(u)
	proxy.Transport = &TimeoutTransport{}
	proxy.Director = teeDirector

	http.HandleFunc("/", handler)
	http.ListenAndServe(*listen, nil)
}
<commit_msg>Make tee log messages logstash friendly, clean up messages<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"runtime/debug"
	"strings"
	"time"

	"code.google.com/p/go-uuid/uuid"
)

var (
	listen           = flag.String("l", ":8888", "port to accept requests")
	targetProduction = flag.String("a", "http://localhost:8080", "where production traffic goes. http://localhost:8080/production")
	altTarget        = flag.String("b", "http://localhost:8081", "where testing traffic goes. response are skipped. http://localhost:8081/test")

	// Hop-by-hop headers. These are removed when sent to the backend.
	// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
	hopHeaders = []string{
		"Connection",
		"Keep-Alive",
		"Proxy-Authenticate",
		"Proxy-Authorization",
		"Te", // canonicalized version of "TE"
		"Trailers",
		"Transfer-Encoding",
		"Upgrade",
	}
)

type Hosts struct {
	Target      url.URL
	Alternative url.URL
}

var hosts Hosts
var client *http.Client
var proxy *httputil.ReverseProxy

type TimeoutTransport struct {
	http.Transport
}

func (t *TimeoutTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	return t.Transport.RoundTrip(req)
}

func clientCall(id string, req, req2 *http.Request) {
	defer func() {
		if r := recover(); r != nil {
			logMessage(id, "ERROR", fmt.Sprintf("Recovered in clientCall: <%v> <%s>", r, removeEndsOfLines(string(debug.Stack()))))
		}
	}()

	resp, err := http.DefaultTransport.RoundTrip(req2)
	if err != nil {
		logMessage(id, "ERROR", fmt.Sprintf("Invoking client failed: <%v>. Request: <%s>.", err, prettyPrint(req2)))
		return
	}

	r, e := httputil.DumpResponse(resp, true)
	if e != nil {
		logMessage(id, "ERROR", fmt.Sprintf("Could not create response dump: <%v>", e))
	} else {
		logMessage(id, "INFO", fmt.Sprintf("Response: <%s>", removeEndsOfLines(string(r))))
	}

	io.Copy(ioutil.Discard, resp.Body)
	resp.Body.Close()
}

func teeDirector(req *http.Request) {
	id := uuid.NewUUID().String()
	logMessage(id, "INFO", fmt.Sprintf("Request: <%s>", prettyPrint(req)))

	go clientCall(id, req, duplicateRequest(req))

	targetQuery := hosts.Target.RawQuery
	req.URL.Scheme = hosts.Target.Scheme
	req.URL.Host = hosts.Target.Host
	req.URL.Path = singleJoiningSlash(hosts.Target.Path, req.URL.Path)
	if targetQuery == "" || req.URL.RawQuery == "" {
		req.URL.RawQuery = targetQuery + req.URL.RawQuery
	} else {
		req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
	}
}

func duplicateRequest(request *http.Request) (request1 *http.Request) {
	b1 := new(bytes.Buffer)
	b2 := new(bytes.Buffer)
	w := io.MultiWriter(b1, b2)
	io.Copy(w, request.Body)
	request.Body = ioutil.NopCloser(bytes.NewReader(b2.Bytes()))
	bodyReader := ioutil.NopCloser(bytes.NewReader(b1.Bytes()))

	request2 := &http.Request{
		Method: request.Method,
		URL: &url.URL{
			Scheme:   hosts.Alternative.Scheme,
			Host:     hosts.Alternative.Host,
			Path:     singleJoiningSlash(hosts.Alternative.Path, request.URL.Path),
			RawQuery: request.URL.RawQuery,
		},
		Proto:         request.Proto,
		ProtoMajor:    request.ProtoMajor,
		ProtoMinor:    request.ProtoMinor,
		Header:        request.Header,
		Body:          bodyReader,
		ContentLength: request.ContentLength,
		Close:         false,
	}

	// Remove hop-by-hop headers to the backend.  Especially
	// important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.  This
	// is modifying the same underlying map from req (shallow
	// copied above) so we only copy it if necessary.
	copiedHeaders := false
	for _, h := range hopHeaders {
		if request2.Header.Get(h) != "" {
			if !copiedHeaders {
				request2.Header = make(http.Header)
				copyHeader(request2.Header, request.Header)
				copiedHeaders = true
			}
			request2.Header.Del(h)
		}
	}

	return request2
}

func copyHeader(dst, src http.Header) {
	for k, vv := range src {
		for _, v := range vv {
			dst.Add(k, v)
		}
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	proxy.ServeHTTP(w, r)
}

// want to keep log messages on a single line, one line is one log entry
func removeEndsOfLines(s string) string {
	return strings.Replace(strings.Replace(s, "\n", "\\n", -1), "\r", "\\r", -1)
}

func prettyPrint(obj interface{}) string {
	return removeEndsOfLines(fmt.Sprintf("%+v", obj))
}

func logMessage(id, messageType, message string) {
	fmt.Printf("[%s][%s][%s][%s]\n", time.Now().Format(time.RFC3339Nano), id, messageType, message)
}

func singleJoiningSlash(a, b string) string {
	aslash := strings.HasSuffix(a, "/")
	bslash := strings.HasPrefix(b, "/")
	switch {
	case aslash && bslash:
		return a + b[1:]
	case !aslash && !bslash:
		return a + "/" + b
	}
	return a + b
}

func main() {
	flag.Parse()

	target, _ := url.Parse(*targetProduction)
	alt, _ := url.Parse(*altTarget)
	client = &http.Client{
		Timeout: time.Millisecond * 2000,
	}

	hosts = Hosts{
		Target:      *target,
		Alternative: *alt,
	}

	u, _ := url.Parse(*targetProduction)
	proxy = httputil.NewSingleHostReverseProxy(u)
	proxy.Transport = &TimeoutTransport{}
	proxy.Director = teeDirector

	http.HandleFunc("/", handler)
	http.ListenAndServe(*listen, nil)
}
<|endoftext|>


<commit_before>package rekordo

import (
	"database/sql"
	"errors"
	"fmt"

	"github.com/go-gorp/gorp"
	"github.com/loopfz/gadgeto/zesty"
)

// Default database settings.
const (
	maxOpenConns = 5
	maxIdleConns = 3
)

// DatabaseConfig represents the configuration used to
// register a new database.
type DatabaseConfig struct {
	Name         string
	DSN          string
	System       DBMS
	MaxOpenConns int
	MaxIdleConns int
}

// RegisterDatabase creates a gorp map with tables and tc and
// registers it with zesty.
func RegisterDatabase(db *DatabaseConfig, tc gorp.TypeConverter) error {
	modelsMu.Lock()
	tableModels, ok := models[db.Name]
	modelsMu.Unlock()
	if !ok {
		return fmt.Errorf("no models registered for database %s", db.Name)
	}
	dbConn, err := sql.Open(db.System.DriverName(), db.DSN)
	if err != nil {
		return err
	}
	// Make sure we have proper values for the database
	// settings, and replace them with default if necessary
	// before applying to the new connection.
	if db.MaxOpenConns == 0 {
		db.MaxOpenConns = maxOpenConns
	}
	dbConn.SetMaxOpenConns(db.MaxOpenConns)
	if db.MaxIdleConns == 0 {
		db.MaxIdleConns = maxIdleConns
	}
	dbConn.SetMaxIdleConns(db.MaxIdleConns)

	// Select the proper dialect used by gorp.
	var dialect gorp.Dialect
	switch db.System {
	case DatabaseMySQL:
		dialect = gorp.MySQLDialect{}
	case DatabasePostgreSQL:
		dialect = gorp.PostgresDialect{}
	default:
		return errors.New("unknown database system")
	}
	dbmap := &gorp.DbMap{
		Db:            dbConn,
		Dialect:       dialect,
		TypeConverter: tc,
	}
	for _, t := range tableModels {
		dbmap.AddTableWithName(t.Model, t.Name).SetKeys(t.AutoIncrement, t.Keys...)
	}
	return zesty.RegisterDB(zesty.NewDB(dbmap), db.Name)
}

// DBMS represents a database management system.
type DBMS uint8

// Database management systems.
const (
	DatabasePostgreSQL DBMS = iota ^ 42
	DatabaseMySQL
)

// DriverName returns the name of the driver for ds.
func (d DBMS) DriverName() string {
	switch d {
	case DatabasePostgreSQL:
		return "postgres"
	case DatabaseMySQL:
		return "mysql"
	}
	return ""
}
<commit_msg>zesty: sqlite3 support<commit_after>package rekordo

import (
	"database/sql"
	"errors"
	"fmt"

	"github.com/go-gorp/gorp"
	"github.com/loopfz/gadgeto/zesty"
)

// Default database settings.
const (
	maxOpenConns = 5
	maxIdleConns = 3
)

// DatabaseConfig represents the configuration used to
// register a new database.
type DatabaseConfig struct {
	Name         string
	DSN          string
	System       DBMS
	MaxOpenConns int
	MaxIdleConns int
}

// RegisterDatabase creates a gorp map with tables and tc and
// registers it with zesty.
func RegisterDatabase(db *DatabaseConfig, tc gorp.TypeConverter) error {
	modelsMu.Lock()
	tableModels, ok := models[db.Name]
	modelsMu.Unlock()
	if !ok {
		return fmt.Errorf("no models registered for database %s", db.Name)
	}
	dbConn, err := sql.Open(db.System.DriverName(), db.DSN)
	if err != nil {
		return err
	}
	// Make sure we have proper values for the database
	// settings, and replace them with default if necessary
	// before applying to the new connection.
	if db.MaxOpenConns == 0 {
		db.MaxOpenConns = maxOpenConns
	}
	dbConn.SetMaxOpenConns(db.MaxOpenConns)
	if db.MaxIdleConns == 0 {
		db.MaxIdleConns = maxIdleConns
	}
	dbConn.SetMaxIdleConns(db.MaxIdleConns)

	// Select the proper dialect used by gorp.
	var dialect gorp.Dialect
	switch db.System {
	case DatabaseMySQL:
		dialect = gorp.MySQLDialect{}
	case DatabasePostgreSQL:
		dialect = gorp.PostgresDialect{}
	case DatabaseSqlite3:
		dialect = gorp.SqliteDialect{}
	default:
		return errors.New("unknown database system")
	}
	dbmap := &gorp.DbMap{
		Db:            dbConn,
		Dialect:       dialect,
		TypeConverter: tc,
	}
	for _, t := range tableModels {
		dbmap.AddTableWithName(t.Model, t.Name).SetKeys(t.AutoIncrement, t.Keys...)
	}
	return zesty.RegisterDB(zesty.NewDB(dbmap), db.Name)
}

// DBMS represents a database management system.
type DBMS uint8

// Database management systems.
const (
	DatabasePostgreSQL DBMS = iota ^ 42
	DatabaseMySQL
	DatabaseSqlite3
)

// DriverName returns the name of the driver for ds.
func (d DBMS) DriverName() string {
	switch d {
	case DatabasePostgreSQL:
		return "postgres"
	case DatabaseMySQL:
		return "mysql"
	case DatabaseSqlite3:
		return "sqlite3"
	}
	return ""
}
<|endoftext|>