<commit_before>// Copyright 2014 com authors
//
// 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 com

import (
	"fmt"
	"strconv"
)

// Convert string to specify type.
type StrTo string

func (f StrTo) Exist() bool {
	return string(f) != string(0x1E)
}

func (f StrTo) Uint8() (uint8, error) {
	v, err := strconv.ParseUint(f.String(), 10, 8)
	return uint8(v), err
}

func (f StrTo) Int() (int, error) {
	v, err := strconv.ParseInt(f.String(), 10, 32)
	return int(v), err
}

func (f StrTo) Int64() (int64, error) {
	v, err := strconv.ParseInt(f.String(), 10, 64)
	return int64(v), err
}

func (f StrTo) MustUint8() uint8 {
	v, _ := f.Uint8()
	return v
}

func (f StrTo) MustInt() int {
	v, _ := f.Int()
	return v
}

func (f StrTo) MustInt64() int64 {
	v, _ := f.Int64()
	return v
}

func (f StrTo) String() string {
	if f.Exist() {
		return string(f)
	}
	return ""
}

// Convert any type to string.
func ToStr(value interface{}, args ...int) (s string) {
	switch v := value.(type) {
	case bool:
		s = strconv.FormatBool(v)
	case float32:
		s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
	case float64:
		s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
	case int:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int8:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int16:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int32:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int64:
		s = strconv.FormatInt(v, argInt(args).Get(0, 10))
	case uint:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint8:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint16:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint32:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint64:
		s = strconv.FormatUint(v, argInt(args).Get(0, 10))
	case string:
		s = v
	case []byte:
		s = string(v)
	default:
		s = fmt.Sprintf("%v", v)
	}
	return s
}

type argInt []int

func (a argInt) Get(i int, args ...int) (r int) {
	if i >= 0 && i < len(a) {
		r = a[i]
	} else if len(args) > 0 {
		r = args[0]
	}
	return
}

// HexStr2int converts hex format string to decimal number.
func HexStr2int(hexStr string) (int, error) {
	num := 0
	length := len(hexStr)
	for i := 0; i < length; i++ {
		char := hexStr[length-i-1]
		factor := -1

		switch {
		case char >= '0' && char <= '9':
			factor = int(char) - '0'
		case char >= 'a' && char <= 'f':
			factor = int(char) - 'a' + 10
		default:
			return -1, fmt.Errorf("invalid hex: %s", string(char))
		}

		num += factor * PowInt(16, i)
	}
	return num, nil
}

// Int2HexStr converts decimal number to hex format string.
func Int2HexStr(num int) (hex string) {
	for num > 0 {
		r := num % 16

		c := "?"
		if r >= 0 && r <= 9 {
			c = string(r + '0')
		} else {
			c = string(r + 'a' - 10)
		}
		hex = c + hex
		num = num / 16
	}
	return hex
}
<commit_msg>Mirror bug fix<commit_after>// Copyright 2014 com authors
//
// 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 com

import (
	"fmt"
	"strconv"
)

// Convert string to specify type.
type StrTo string

func (f StrTo) Exist() bool {
	return string(f) != string(0x1E)
}

func (f StrTo) Uint8() (uint8, error) {
	v, err := strconv.ParseUint(f.String(), 10, 8)
	return uint8(v), err
}

func (f StrTo) Int() (int, error) {
	v, err := strconv.ParseInt(f.String(), 10, 32)
	return int(v), err
}

func (f StrTo) Int64() (int64, error) {
	v, err := strconv.ParseInt(f.String(), 10, 64)
	return int64(v), err
}

func (f StrTo) MustUint8() uint8 {
	v, _ := f.Uint8()
	return v
}

func (f StrTo) MustInt() int {
	v, _ := f.Int()
	return v
}

func (f StrTo) MustInt64() int64 {
	v, _ := f.Int64()
	return v
}

func (f StrTo) String() string {
	if f.Exist() {
		return string(f)
	}
	return ""
}

// Convert any type to string.
func ToStr(value interface{}, args ...int) (s string) {
	switch v := value.(type) {
	case bool:
		s = strconv.FormatBool(v)
	case float32:
		s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
	case float64:
		s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
	case int:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int8:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int16:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int32:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int64:
		s = strconv.FormatInt(v, argInt(args).Get(0, 10))
	case uint:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint8:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint16:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint32:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint64:
		s = strconv.FormatUint(v, argInt(args).Get(0, 10))
	case string:
		s = v
	case []byte:
		s = string(v)
	default:
		s = fmt.Sprintf("%v", v)
	}
	return s
}

type argInt []int

func (a argInt) Get(i int, args ...int) (r int) {
	if i >= 0 && i < len(a) {
		r = a[i]
	} else if len(args) > 0 {
		r = args[0]
	}
	return
}

// HexStr2int converts hex format string to decimal number.
func HexStr2int(hexStr string) (int, error) {
	num := 0
	length := len(hexStr)
	for i := 0; i < length; i++ {
		char := hexStr[length-i-1]
		factor := -1

		switch {
		case char >= '0' && char <= '9':
			factor = int(char) - '0'
		case char >= 'a' && char <= 'f':
			factor = int(char) - 'a' + 10
		default:
			return -1, fmt.Errorf("invalid hex: %s", string(char))
		}

		num += factor * PowInt(16, i)
	}
	return num, nil
}

// Int2HexStr converts decimal number to hex format string.
func Int2HexStr(num int) (hex string) {
	if num == 0 {
		return "0"
	}

	for num > 0 {
		r := num % 16

		c := "?"
		if r >= 0 && r <= 9 {
			c = string(r + '0')
		} else {
			c = string(r + 'a' - 10)
		}
		hex = c + hex
		num = num / 16
	}
	return hex
}
<|endoftext|>


<commit_before>package core

import (
	"database/sql"

	"reflect"

	_ "github.com/go-sql-driver/mysql"
	"github.com/pkg/errors"
)

const (
	MIGRATIONS_TABLE_NAME  = "gim_migrations"
	MIGRATION_TABLE_SCRIPT = "CREATE TABLE `gim_migrations` (\n" +
		"  `version` int(8) unsigned NOT NULL AUTO_INCREMENT,\n" +
		"  `up` text NOT NULL,\n" +
		"  `down` text NOT NULL,\n" +
		"  PRIMARY KEY (`version`)\n" +
		") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"

	ERROR_MIGRATION_TABLE_NOT_EXISTS     = "migration_table_not_exists"
	ERROR_MIGRATION_TABLE_INVALID_SCHEMA = "migration_table_invalid_schema"
	ERROR_MIGRATION_RECORD_NOT_EXISTS    = "migration_record_not_exists"
)

type MigrationsTableNotExistsError error
type MigrationsTableInvalidError error

func InitDB(driver, dsn string) (*sql.DB, error) {
	db, _ := sql.Open(driver, dsn)
	err := db.Ping()
	if err != nil {
		return db, err
	}
	return db, nil
}

func CheckMigrationsTable(db *sql.DB) error {
	rs, err := db.Query("DESC " + MIGRATIONS_TABLE_NAME)
	if err != nil {
		return errors.New(ERROR_MIGRATION_TABLE_NOT_EXISTS)
	}
	defer rs.Close()

	type rt struct {
		Field, Type, Null, Key, Extra string
		Default                       sql.NullString
	}

	var s = make(map[uint]rt)
	var i = uint(0)
	for rs.Next() {
		r := rt{}
		err = rs.Scan(&r.Field, &r.Type, &r.Null, &r.Key, &r.Default, &r.Extra)
		if err != nil {
			return err
		}
		s[i] = r
		i++
	}

	tpl := map[uint]rt{
		0: {
			Field:   "version",
			Type:    "int(8) unsigned",
			Null:    "NO",
			Key:     "PRI",
			Default: sql.NullString{},
			Extra:   "auto_increment",
		},
		1: {
			Field:   "up",
			Type:    "text",
			Null:    "NO",
			Key:     "",
			Default: sql.NullString{},
			Extra:   "",
		},
		2: {
			Field:   "down",
			Type:    "text",
			Null:    "NO",
			Key:     "",
			Default: sql.NullString{},
			Extra:   "",
		},
	}

	if !reflect.DeepEqual(s, tpl) {
		return errors.New(ERROR_MIGRATION_TABLE_INVALID_SCHEMA)
	}

	return nil
}

func CreateMigrationTable(db *sql.DB) error {
	_, err := db.Exec(MIGRATION_TABLE_SCRIPT)
	return err
}

func LoadDBMigrations(db *sql.DB) (map[int64]*Migration, error) {
	var m = map[int64]*Migration{}
	r, err := db.Query("SELECT * FROM " + MIGRATIONS_TABLE_NAME)
	if err != nil {
		return m, err
	}
	defer r.Close()

	for r.Next() {
		var u, d string
		var v int64
		err := r.Scan(&v, &u, &d)
		if err != nil {
			return m, err
		}
		m[v] = &Migration{
			Version: v,
			Up:      u,
			Down:    d,
		}
	}
	return m, err
}

func LoadDBMigration(db *sql.DB, version string) (*Migration, error) {
	var m = Migration{}
	q := "SELECT * FROM `" + MIGRATIONS_TABLE_NAME + "` WHERE `version` = " + version + ""
	err := db.QueryRow(q).Scan(&m.Version, &m.Up, &m.Down)
	if err != nil {
		if err == sql.ErrNoRows {
			return &m, errors.New(ERROR_MIGRATION_RECORD_NOT_EXISTS)
		}
	}
	return &m, err
}

func ApplyMigration(db *sql.DB, m *Migration) error {
	st, err := db.Prepare("INSERT INTO `" + MIGRATIONS_TABLE_NAME + "`(`version`, `up`, `down`) VALUES(?,?,?);")
	if err != nil {
		return err
	}
	_, err = st.Exec(m.Version, m.Up, m.Down)
	if err != nil {
		return err
	}

	_, err = db.Exec(m.Up)
	if err != nil {
		db.Exec("DELETE FROM `"+MIGRATIONS_TABLE_NAME+"` WHERE `version` = ?", m.Version)
		return err
	}
	return nil
}

func RevertMigration(db *sql.DB, m *Migration) error {
	_, err := db.Exec(m.Down)
	if err != nil {
		return err
	}

	db.Exec("DELETE FROM `"+MIGRATIONS_TABLE_NAME+"` WHERE `version` = ?", m.Version)
	return nil
}
<commit_msg>Fix. Refactor multiqueries to run separatly<commit_after>package core

import (
	"database/sql"

	"reflect"

	"strings"

	_ "github.com/go-sql-driver/mysql"
	"github.com/pkg/errors"
)

const (
	MIGRATIONS_TABLE_NAME  = "gim_migrations"
	MIGRATION_TABLE_SCRIPT = "CREATE TABLE `gim_migrations` (\n" +
		"  `version` int(8) unsigned NOT NULL AUTO_INCREMENT,\n" +
		"  `up` text NOT NULL,\n" +
		"  `down` text NOT NULL,\n" +
		"  PRIMARY KEY (`version`)\n" +
		") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"

	ERROR_MIGRATION_TABLE_NOT_EXISTS     = "migration_table_not_exists"
	ERROR_MIGRATION_TABLE_INVALID_SCHEMA = "migration_table_invalid_schema"
	ERROR_MIGRATION_RECORD_NOT_EXISTS    = "migration_record_not_exists"
)

type MigrationsTableNotExistsError error
type MigrationsTableInvalidError error

func InitDB(driver, dsn string) (*sql.DB, error) {
	db, _ := sql.Open(driver, dsn)
	err := db.Ping()
	if err != nil {
		return db, err
	}
	return db, nil
}

func CheckMigrationsTable(db *sql.DB) error {
	rs, err := db.Query("DESC " + MIGRATIONS_TABLE_NAME)
	if err != nil {
		return errors.New(ERROR_MIGRATION_TABLE_NOT_EXISTS)
	}
	defer rs.Close()

	type rt struct {
		Field, Type, Null, Key, Extra string
		Default                       sql.NullString
	}

	var s = make(map[uint]rt)
	var i = uint(0)
	for rs.Next() {
		r := rt{}
		err = rs.Scan(&r.Field, &r.Type, &r.Null, &r.Key, &r.Default, &r.Extra)
		if err != nil {
			return err
		}
		s[i] = r
		i++
	}

	tpl := map[uint]rt{
		0: {
			Field:   "version",
			Type:    "int(8) unsigned",
			Null:    "NO",
			Key:     "PRI",
			Default: sql.NullString{},
			Extra:   "auto_increment",
		},
		1: {
			Field:   "up",
			Type:    "text",
			Null:    "NO",
			Key:     "",
			Default: sql.NullString{},
			Extra:   "",
		},
		2: {
			Field:   "down",
			Type:    "text",
			Null:    "NO",
			Key:     "",
			Default: sql.NullString{},
			Extra:   "",
		},
	}

	if !reflect.DeepEqual(s, tpl) {
		return errors.New(ERROR_MIGRATION_TABLE_INVALID_SCHEMA)
	}

	return nil
}

func CreateMigrationTable(db *sql.DB) error {
	_, err := db.Exec(MIGRATION_TABLE_SCRIPT)
	return err
}

func LoadDBMigrations(db *sql.DB) (map[int64]*Migration, error) {
	var m = map[int64]*Migration{}
	r, err := db.Query("SELECT * FROM " + MIGRATIONS_TABLE_NAME)
	if err != nil {
		return m, err
	}
	defer r.Close()

	for r.Next() {
		var u, d string
		var v int64
		err := r.Scan(&v, &u, &d)
		if err != nil {
			return m, err
		}
		m[v] = &Migration{
			Version: v,
			Up:      u,
			Down:    d,
		}
	}
	return m, err
}

func LoadDBMigration(db *sql.DB, version string) (*Migration, error) {
	var m = Migration{}
	q := "SELECT * FROM `" + MIGRATIONS_TABLE_NAME + "` WHERE `version` = " + version + ""
	err := db.QueryRow(q).Scan(&m.Version, &m.Up, &m.Down)
	if err != nil {
		if err == sql.ErrNoRows {
			return &m, errors.New(ERROR_MIGRATION_RECORD_NOT_EXISTS)
		}
	}
	return &m, err
}

func ApplyMigration(db *sql.DB, m *Migration) error {
	st, err := db.Prepare("INSERT INTO `" + MIGRATIONS_TABLE_NAME + "`(`version`, `up`, `down`) VALUES(?,?,?);")
	if err != nil {
		return err
	}
	_, err = st.Exec(m.Version, m.Up, m.Down)
	if err != nil {
		return err
	}

	qs := strings.Split(m.Up, ";")
	for _, q := range qs {
		_, err = db.Exec(q)
		if err != nil {
			break
		}
	}

	if err != nil {
		db.Exec("DELETE FROM `"+MIGRATIONS_TABLE_NAME+"` WHERE `version` = ?", m.Version)
		return err
	}
	return nil
}

func RevertMigration(db *sql.DB, m *Migration) error {
	qs := strings.Split(m.Up, ";")
	for _, q := range qs {
		_, err := db.Exec(q)
		if err != nil {
			return err
		}
	}

	db.Exec("DELETE FROM `"+MIGRATIONS_TABLE_NAME+"` WHERE `version` = ?", m.Version)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Toorop/govh"
	"github.com/Toorop/govh/ip"
	//"os"
	"strconv"
	"strings"
)

func ipHandler(cmd *Cmd) (resp string, err error) {
	// New govh client
	client := govh.NewClient(OVH_APP_KEY, OVH_APP_SECRET, ck)
	// New ip ressource
	ipr, err := ip.New(client)

	switch cmd.Action {
	// List
	case "list":
		ipType := "all"
		if len(cmd.Args) > 2 {
			ipType = cmd.Args[2]
		}
		ips, err := ipr.List(ipType)
		if err != nil {
			dieError(err)
		}
		for _, i := range ips {
			resp = fmt.Sprintf("%s%s\r\n", resp, i.IP)
		}
		if len(resp) > 2 {
			resp = resp[0 : len(resp)-2]
		}
		break
	case "lb":
		if len(cmd.Args) < 3 {
			dieError("\"ip lb\" needs an argument see doc at https://github.com/Toorop/govh/blob/master/cli/README.md")
		}
		var t []byte
		t, err = ipr.LbList()
		resp = string(t)
		break

	case "fw":
		// ip fw ipBlock.IP list
		// ip fw x.x.x.x/y
		// Return IP V4 list of this block which is under firewall
		if len(cmd.Args) == 4 && cmd.Args[3] == "list" {
			block := ip.IpBlock{cmd.Args[2], ""}
			ips, err := ipr.FwListIpOfBlock(block)
			if err != nil {
				dieError(err)
			}
			for _, i := range ips {
				resp = fmt.Sprintf("%s%s\r\n", resp, i)
			}
			if len(resp) > 2 {
				resp = resp[0 : len(resp)-2]
			}
			break
		}

		// Add IP to firewall
		// cmd : ip fw ibBlock.IP ipV4 add
		if len(cmd.Args) == 5 && cmd.Args[4] == "add" {
			block := ip.IpBlock{cmd.Args[2], ""}
			if err = ipr.FwAddIp(block, cmd.Args[3]); err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("%s added to firewall", cmd.Args[3]))
		}

		// Get properties of a firewalled IP
		// ip fw ipBlock.IP ipV4 prop
		if len(cmd.Args) == 5 && cmd.Args[4] == "prop" {
			block := ip.IpBlock{cmd.Args[2], ""}
			i, err := ipr.FwGetIpProperties(block, cmd.Args[3])
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("ipOnFirewall: %s%sEnabled: %t%sState: %s", i.IpOnFirewall, NL, i.Enabled, NL, i.State))
			break
		}

		// Enable firewalll for IP ipv4
		// ip fw ipVlock ipV4 enable
		if len(cmd.Args) == 5 && cmd.Args[4] == "enable" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.FwSetFirewallEnable(block, cmd.Args[3], true)
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
			break
		}

		// Disable firewalll for IP ipv4
		// ip fw ipVlock ipV4 disable
		if len(cmd.Args) == 5 && cmd.Args[4] == "disable" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.FwSetFirewallEnable(block, cmd.Args[3], false)
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
			break
		}

		// Remove IPv4 from firewall
		// cmd : ip fw ipBlock.IP ipV4 remove
		if len(cmd.Args) == 5 && cmd.Args[4] == "remove" {
			block := ip.IpBlock{cmd.Args[2], ""}
			if err = ipr.FwRemoveIp(block, cmd.Args[3]); err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("%s removed from firewall", cmd.Args[3]))
		}

		// Get rules sequences
		// ip fw ipBlock.IP ipV4 listRules all
		if len(cmd.Args) >= 5 && cmd.Args[4] == "listRules" {
			block := ip.IpBlock{cmd.Args[2], ""}
			state := ""
			if len(cmd.Args) == 6 {
				state = cmd.Args[6]
			}
			t, err := ipr.FwGetRulesSequences(block, cmd.Args[3], state)
			if err != nil {
				dieError(err)
			}
			var r string
			if len(t) > 0 {
				r = fmt.Sprintf("%d", t[0])
				for _, s := range t[1:] {
					r = fmt.Sprintf("%s%s%d", r, NL, s)
				}
			}
			dieOk(r)
		}

		// Add rule
		// ip fw ipBlock.IP ipV4 addRule rule (as Json)
		if len(cmd.Args) == 6 && cmd.Args[4] == "addRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			// Check json
			var rule ip.FirewallRule2Add
			err := json.Unmarshal([]byte(cmd.Args[5]), &rule)
			if err != nil {
				dieError("Rule error. See doc at : https://github.com/Toorop/ovh-cli", err)
			}
			err = ipr.FwAddRule(block, cmd.Args[3], rule)
			if err != nil {
				dieError(err)
			}
			dieOk("OK")
		}

		// Remove rule
		// ip fw ipBlock.IP ipV4 removeRule ruleSequence
		if len(cmd.Args) == 6 && cmd.Args[4] == "remRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			sequence, err := strconv.Atoi(cmd.Args[5])
			if err != nil {
				dieError(err)
			}
			err = ipr.FwRemoveRule(block, cmd.Args[3], sequence)
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("Rule %d removed", sequence))

		}

		// Get rule
		// ip fw ipBlock.IP ipV4 getRule sequence
		if len(cmd.Args) == 6 && cmd.Args[4] == "getRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			sequence, err := strconv.Atoi(cmd.Args[5])
			if err != nil {
				dieError(err)
			}
			rule, err := ipr.FwGetRule(block, cmd.Args[3], sequence)
			if err != nil {
				dieError(err)
			}
			out := ""
			if len(rule.Protocol) > 0 {
				out = fmt.Sprintf("%sProtocol: %s%s", out, rule.Protocol, NL)
			}
			if len(rule.Source) > 0 {
				out = fmt.Sprintf("%sSource: %s%s", out, rule.Source, NL)
			}
			if len(rule.DestinationPort) > 0 {
				out = fmt.Sprintf("%sDestinationPort: %s%s", out, rule.DestinationPort, NL)
			}

			out = fmt.Sprintf("%sSequence: %d%s", out, rule.Sequence, NL)

			if len(rule.Options) > 0 {
				out = fmt.Sprintf("%sOptions: %s%s", out, strings.Join(rule.Options, " "), NL)
			}
			if len(rule.Destination) > 0 {
				out = fmt.Sprintf("%sDestination: %s%s", out, rule.Destination, NL)
			}
			if len(rule.Rule) > 0 {
				out = fmt.Sprintf("%sRule: %s%s", out, rule.Rule, NL)
			}
			if len(rule.SourcePort) > 0 {
				out = fmt.Sprintf("%sSourcePort: %s%s", out, rule.SourcePort, NL)
			}
			if len(rule.State) > 0 {
				out = fmt.Sprintf("%sState: %s%s", out, rule.State, NL)
			}
			if len(rule.CreationDate) > 0 {
				out = fmt.Sprintf("%sCreationDate: %s%s", out, rule.CreationDate, NL)
			}
			if len(rule.Action) > 0 {
				out = fmt.Sprintf("%sAction: %s%s", out, rule.Action, NL)
			}
			dieOk(out[0 : len(out)-2])

		}
		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
		break
	default:
		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
	}
	return

}
<commit_msg>Spam<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Toorop/govh"
	"github.com/Toorop/govh/ip"
	//"os"
	"strconv"
	"strings"
	"time"
)

func ipHandler(cmd *Cmd) (resp string, err error) {
	// New govh client
	client := govh.NewClient(OVH_APP_KEY, OVH_APP_SECRET, ck)
	// New ip ressource
	ipr, err := ip.New(client)

	switch cmd.Action {
	// List
	case "list":
		ipType := "all"
		if len(cmd.Args) > 2 {
			ipType = cmd.Args[2]
		}
		ips, err := ipr.List(ipType)
		if err != nil {
			dieError(err)
		}
		for _, i := range ips {
			resp = fmt.Sprintf("%s%s\r\n", resp, i.IP)
		}
		if len(resp) > 2 {
			resp = resp[0 : len(resp)-2]
		}
		break
	case "lb":
		if len(cmd.Args) < 3 {
			dieError("\"ip lb\" needs an argument see doc at https://github.com/Toorop/govh/blob/master/cli/README.md")
		}
		var t []byte
		t, err = ipr.LbList()
		resp = string(t)
		break

	case "fw":
		// ip fw ipBlock.IP list
		// ip fw x.x.x.x/y
		// Return IP V4 list of this block which is under firewall
		if len(cmd.Args) == 4 && cmd.Args[3] == "list" {
			block := ip.IpBlock{cmd.Args[2], ""}
			ips, err := ipr.FwListIpOfBlock(block)
			if err != nil {
				dieError(err)
			}
			for _, i := range ips {
				resp = fmt.Sprintf("%s%s\r\n", resp, i)
			}
			if len(resp) > 2 {
				resp = resp[0 : len(resp)-2]
			}
			break
		}

		// Add IP to firewall
		// cmd : ip fw ibBlock.IP ipV4 add
		if len(cmd.Args) == 5 && cmd.Args[4] == "add" {
			block := ip.IpBlock{cmd.Args[2], ""}
			if err = ipr.FwAddIp(block, cmd.Args[3]); err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("%s added to firewall", cmd.Args[3]))
		}

		// Get properties of a firewalled IP
		// ip fw ipBlock.IP ipV4 prop
		if len(cmd.Args) == 5 && cmd.Args[4] == "prop" {
			block := ip.IpBlock{cmd.Args[2], ""}
			i, err := ipr.FwGetIpProperties(block, cmd.Args[3])
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("ipOnFirewall: %s%sEnabled: %t%sState: %s", i.IpOnFirewall, NL, i.Enabled, NL, i.State))
			break
		}

		// Enable firewalll for IP ipv4
		// ip fw ipVlock ipV4 enable
		if len(cmd.Args) == 5 && cmd.Args[4] == "enable" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.FwSetFirewallEnable(block, cmd.Args[3], true)
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
			break
		}

		// Disable firewalll for IP ipv4
		// ip fw ipVlock ipV4 disable
		if len(cmd.Args) == 5 && cmd.Args[4] == "disable" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.FwSetFirewallEnable(block, cmd.Args[3], false)
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
			break
		}

		// Remove IPv4 from firewall
		// cmd : ip fw ipBlock.IP ipV4 remove
		if len(cmd.Args) == 5 && cmd.Args[4] == "remove" {
			block := ip.IpBlock{cmd.Args[2], ""}
			if err = ipr.FwRemoveIp(block, cmd.Args[3]); err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("%s removed from firewall", cmd.Args[3]))
		}

		// Get rules sequences
		// ip fw ipBlock.IP ipV4 listRules all
		if len(cmd.Args) >= 5 && cmd.Args[4] == "listRules" {
			block := ip.IpBlock{cmd.Args[2], ""}
			state := ""
			if len(cmd.Args) == 6 {
				state = cmd.Args[6]
			}
			t, err := ipr.FwGetRulesSequences(block, cmd.Args[3], state)
			if err != nil {
				dieError(err)
			}
			var r string
			if len(t) > 0 {
				r = fmt.Sprintf("%d", t[0])
				for _, s := range t[1:] {
					r = fmt.Sprintf("%s%s%d", r, NL, s)
				}
			}
			dieOk(r)
		}

		// Add rule
		// ip fw ipBlock.IP ipV4 addRule rule (as Json)
		if len(cmd.Args) == 6 && cmd.Args[4] == "addRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			// Check json
			var rule ip.FirewallRule2Add
			err := json.Unmarshal([]byte(cmd.Args[5]), &rule)
			if err != nil {
				dieError("Rule error. See doc at : https://github.com/Toorop/ovh-cli", err)
			}
			err = ipr.FwAddRule(block, cmd.Args[3], rule)
			if err != nil {
				dieError(err)
			}
			dieOk("OK")
		}

		// Remove rule
		// ip fw ipBlock.IP ipV4 remRule ruleSequence
		if len(cmd.Args) == 6 && cmd.Args[4] == "remRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			sequence, err := strconv.Atoi(cmd.Args[5])
			if err != nil {
				dieError(err)
			}
			err = ipr.FwRemoveRule(block, cmd.Args[3], sequence)
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("Rule %d removed", sequence))

		}

		// Get rule
		// ip fw ipBlock.IP ipV4 getRule sequence
		if len(cmd.Args) == 6 && cmd.Args[4] == "getRule" {
			block := ip.IpBlock{cmd.Args[2], ""}
			sequence, err := strconv.Atoi(cmd.Args[5])
			if err != nil {
				dieError(err)
			}
			rule, err := ipr.FwGetRule(block, cmd.Args[3], sequence)
			if err != nil {
				dieError(err)
			}
			out := ""
			if len(rule.Protocol) > 0 {
				out = fmt.Sprintf("%sProtocol: %s%s", out, rule.Protocol, NL)
			}
			if len(rule.Source) > 0 {
				out = fmt.Sprintf("%sSource: %s%s", out, rule.Source, NL)
			}
			if len(rule.DestinationPort) > 0 {
				out = fmt.Sprintf("%sDestinationPort: %s%s", out, rule.DestinationPort, NL)
			}

			out = fmt.Sprintf("%sSequence: %d%s", out, rule.Sequence, NL)

			if len(rule.Options) > 0 {
				out = fmt.Sprintf("%sOptions: %s%s", out, strings.Join(rule.Options, " "), NL)
			}
			if len(rule.Destination) > 0 {
				out = fmt.Sprintf("%sDestination: %s%s", out, rule.Destination, NL)
			}
			if len(rule.Rule) > 0 {
				out = fmt.Sprintf("%sRule: %s%s", out, rule.Rule, NL)
			}
			if len(rule.SourcePort) > 0 {
				out = fmt.Sprintf("%sSourcePort: %s%s", out, rule.SourcePort, NL)
			}
			if len(rule.State) > 0 {
				out = fmt.Sprintf("%sState: %s%s", out, rule.State, NL)
			}
			if len(rule.CreationDate) > 0 {
				out = fmt.Sprintf("%sCreationDate: %s%s", out, rule.CreationDate, NL)
			}
			if len(rule.Action) > 0 {
				out = fmt.Sprintf("%sAction: %s%s", out, rule.Action, NL)
			}
			dieOk(out[0 : len(out)-2])

		}
		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
		break

	case "spam":
		// List of spamming IP
		// ip spam ipBlock.IP listSpammingIp STATE
		if len(cmd.Args) >= 4 && cmd.Args[3] == "listSpammingIp" {
			block := ip.IpBlock{cmd.Args[2], ""}
			state := ""
			if len(cmd.Args) == 5 {
				state = cmd.Args[4]
			}
			ips, err := ipr.SpamGetSpammingIps(block, state)
			if err != nil {
				dieError(err)
			}
			for _, ip := range ips {
				fmt.Println(ip)
			}
			dieOk("")
		}

		// detailed info about a spamming IP
		// ip spam ipBlock.IP ipv4 details
		if len(cmd.Args) == 5 && cmd.Args[4] == "details" {
			block := ip.IpBlock{cmd.Args[2], ""}
			spamIp, err := ipr.SpamGetSpamIp(block, cmd.Args[3])
			if err != nil {
				dieError(err)
			}
			dieOk(fmt.Sprintf("Time: %d%sDate: %s%sIpSpamming: %s%sState: %s", spamIp.Time, NL, spamIp.Date, NL, spamIp.IpSpamming, NL, spamIp.State))
		}

		// Stats about a spamming IP
		// ip spam ipBlock.IP ipv4 stats FROM TO
		if len(cmd.Args) == 7 && cmd.Args[4] == "stats" {
			block := ip.IpBlock{cmd.Args[2], ""}

			from, err := strconv.ParseInt(cmd.Args[5], 10, 64)
			if err != nil {
				dieError(err)
			}

			to, err := strconv.ParseInt(cmd.Args[6], 10, 64)
			if err != nil {
				dieError(err)
			}
			spamStats, err := ipr.SpamGetIpStats(block, cmd.Args[3], time.Unix(from, 0), time.Unix(to, 0))
			if err != nil {
				dieError(err)
			}
			if spamStats == nil {
				dieOk("No spam stats for this period")
			}
			fmt.Printf("Blocked for the last time: %s%s", time.Unix(spamStats.Timestamp, 0).Format(time.RFC822Z), NL)
			fmt.Printf("Number of emails sent: %d%s", spamStats.Total, NL)
			fmt.Printf("Number of spams sent: %d%s", spamStats.NumberOfSpams, NL)
			fmt.Printf("Average score: %d%s%s", spamStats.AverageSpamScore, NL, NL)
			if len(spamStats.DetectedSpams) > 0 {
				fmt.Println("Detected Spams : ", NL)
			}
			for _, ds := range spamStats.DetectedSpams {
				fmt.Println("")
				fmt.Printf("\tDate: %s%s", time.Unix(ds.Date, 0).Format(time.RFC822Z), NL)
				fmt.Printf("\tMessage ID: %s%s", ds.MessageId, NL)
				fmt.Printf("\tDestination IP: %s%s", ds.DestinationIp, NL)
				fmt.Printf("\tScore: %d%s", ds.Spamscore, NL)
			}
			dieOk("")
		}

		// Unblock
		// ip spam ipBlock.IP ipv4 unblock
		if len(cmd.Args) == 5 && cmd.Args[4] == "unblock" {
			block := ip.IpBlock{cmd.Args[2], ""}
			err := ipr.SpamUnblockSpamIp(block, cmd.Args[3])
			if err != nil {
				dieError(err)
			}
			dieOk("ok")
		}

		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
		break
	case "getBlockedForSpam":
		// On va chercher les blocks
		ips, err := ipr.GetBlockedForSpam()
		if err != nil {
			dieError(err)
		}
		if len(ips) == 0 {
			dieOk("")
		}
		for _, i := range ips {
			fmt.Println(i)
		}
		dieOk("")

		// On les tests
		break

	default:
		err = errors.New(fmt.Sprintf("This action : '%s' is not valid or not implemented yet !", strings.Join(cmd.Args, " ")))
	}
	return

}
<|endoftext|>


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

package lb

import (
	"net/http"
	"net/http/httputil"
)

type Backend struct {
	i    int
	load int
	R    *httputil.ReverseProxy
}

func (b *Backend) handle(w http.ResponseWriter, r *http.Request, done chan<- *Backend) {
	b.R.ServeHTTP(w, r)
	done <- b
}

type Pool []*Backend

func (p *Pool) Len() int {
	return len(*p)
}

func (p *Pool) Less(i, j int) bool {
	return (*p)[i].load < (*p)[j].load
}

func (p *Pool) Swap(i, j int) {
	(*p)[i], (*p)[j] = (*p)[j], (*p)[i]
}

func (p *Pool) Push(x interface{}) {
	b := x.(*Backend)
	b.i = p.Len()
	*p = append(*p, b)
}

func (p *Pool) Pop() interface{} {
	b := (*p)[p.Len()-1]
	b.i = -1
	(*p) = (*p)[:p.Len()-1]
	return b
}
<commit_msg>lb: unexport reverse proxy<commit_after>// Copyright 2013 Francisco Souza. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lb

import (
	"net/http"
	"net/http/httputil"
)

type Backend struct {
	i    int
	load int
	r    *httputil.ReverseProxy
}

func (b *Backend) handle(w http.ResponseWriter, r *http.Request, done chan<- *Backend) {
	b.r.ServeHTTP(w, r)
	done <- b
}

type Pool []*Backend

func (p *Pool) Len() int {
	return len(*p)
}

func (p *Pool) Less(i, j int) bool {
	return (*p)[i].load < (*p)[j].load
}

func (p *Pool) Swap(i, j int) {
	(*p)[i], (*p)[j] = (*p)[j], (*p)[i]
}

func (p *Pool) Push(x interface{}) {
	b := x.(*Backend)
	b.i = p.Len()
	*p = append(*p, b)
}

func (p *Pool) Pop() interface{} {
	b := (*p)[p.Len()-1]
	b.i = -1
	(*p) = (*p)[:p.Len()-1]
	return b
}
<|endoftext|>


<commit_before>package ctx

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	jsconf "github.com/funkygao/jsconf"
)

func LoadConfig(fn string) {
	cf, err := jsconf.Load(fn)
	if err != nil {
		panic(err)
	}

	conf = new(config)
	conf.kafkaHome = cf.String("kafka_home", "")
	conf.logLevel = cf.String("loglevel", "info")
	conf.influxdbHost = cf.String("influxdb_host", "")
	conf.zones = make(map[string]string)
	conf.tunnels = make(map[string]string)
	for i := 0; i < len(cf.List("zones", nil)); i++ {
		section, err := cf.Section(fmt.Sprintf("zones[%d]", i))
		if err != nil {
			panic(err)
		}

		z := new(zone)
		z.loadConfig(section)
		conf.zones[z.name] = z.zk
		conf.tunnels[z.name] = z.tunnel
	}

}

func LoadFromHome() {
	const defaultConfig = `
{
    zones: [
        {
            name: "sit"
            zk: "10.77.144.87:10181,10.77.144.88:10181,10.77.144.89:10181"
            tunnel: "root@1.1.1.1"
        }
        {
            name: "test"
            zk: "10.77.144.101:10181,10.77.144.132:10181,10.77.144.182:10181"
            tunnel: "root@1.1.1.1"
        }
        {
            name: "prod"
            zk: "10.209.33.69:2181,10.209.37.19:2181,10.209.37.68:2181"
            tunnel: "root@1.1.1.1"
        }
    ]

    kafka_home: "/opt/kafka_2.10-0.8.1.1"
    loglevel: "info"
}
`
	var configFile string
	if usr, err := user.Current(); err == nil {
		configFile = filepath.Join(usr.HomeDir, ".gafka.cf")
	} else {
		panic(err)
	}

	_, err := os.Stat(configFile)
	if err != nil {
		if os.IsNotExist(err) {
			// create the config file on the fly
			if e := ioutil.WriteFile(configFile,
				[]byte(strings.TrimSpace(defaultConfig)), 0644); e != nil {
				panic(e)
			}
		} else {
			panic(err)
		}
	}

	LoadConfig(configFile)
}

func LogLevel() string {
	ensureLogLoaded()
	return conf.logLevel
}

func Zones() map[string]string {
	ensureLogLoaded()
	return conf.zones
}

func Tunnels() map[string]string {
	ensureLogLoaded()
	return conf.tunnels
}

func KafkaHome() string {
	ensureLogLoaded()
	return conf.kafkaHome
}

func InfluxdbHost() string {
	ensureLogLoaded()
	return conf.influxdbHost
}

func SortedZones() []string {
	ensureLogLoaded()
	return conf.sortedZones()
}

func ZoneZkAddrs(zone string) (zkAddrs string) {
	ensureLogLoaded()
	var present bool
	if zkAddrs, present = conf.zones[zone]; present {
		return
	}

	// should never happen
	fmt.Printf("zone[%s] undefined", zone)
	os.Exit(1)
	return ""
}
<commit_msg>a new default DC added<commit_after>package ctx

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	jsconf "github.com/funkygao/jsconf"
)

func LoadConfig(fn string) {
	cf, err := jsconf.Load(fn)
	if err != nil {
		panic(err)
	}

	conf = new(config)
	conf.kafkaHome = cf.String("kafka_home", "")
	conf.logLevel = cf.String("loglevel", "info")
	conf.influxdbHost = cf.String("influxdb_host", "")
	conf.zones = make(map[string]string)
	conf.tunnels = make(map[string]string)
	for i := 0; i < len(cf.List("zones", nil)); i++ {
		section, err := cf.Section(fmt.Sprintf("zones[%d]", i))
		if err != nil {
			panic(err)
		}

		z := new(zone)
		z.loadConfig(section)
		conf.zones[z.name] = z.zk
		conf.tunnels[z.name] = z.tunnel
	}

}

func LoadFromHome() {
	const defaultConfig = `
{
    zones: [
        {
            name: "sit"
            zk: "10.77.144.87:10181,10.77.144.88:10181,10.77.144.89:10181"
            tunnel: "gaopeng27@10.77.130.14"
        }
        {
            name: "test"
            zk: "10.77.144.101:10181,10.77.144.132:10181,10.77.144.182:10181"
            tunnel: "gaopeng27@10.77.130.14"
        }
        {
            name: "pre"
            zk: "10.213.33.154:2181,10.213.42.48:2181,10.213.42.49:2181"
            tunnel: "gaopeng27@10.209.11.11"
        }
        {
            name: "prod"
            zk: "10.209.33.69:2181,10.209.37.19:2181,10.209.37.68:2181"
            tunnel: "gaopeng27@10.209.11.11"
        }
    ]

    kafka_home: "/opt/kafka_2.10-0.8.1.1"
    loglevel: "info"
}
`
	var configFile string
	if usr, err := user.Current(); err == nil {
		configFile = filepath.Join(usr.HomeDir, ".gafka.cf")
	} else {
		panic(err)
	}

	_, err := os.Stat(configFile)
	if err != nil {
		if os.IsNotExist(err) {
			// create the config file on the fly
			if e := ioutil.WriteFile(configFile,
				[]byte(strings.TrimSpace(defaultConfig)), 0644); e != nil {
				panic(e)
			}
		} else {
			panic(err)
		}
	}

	LoadConfig(configFile)
}

func LogLevel() string {
	ensureLogLoaded()
	return conf.logLevel
}

func Zones() map[string]string {
	ensureLogLoaded()
	return conf.zones
}

func Tunnels() map[string]string {
	ensureLogLoaded()
	return conf.tunnels
}

func KafkaHome() string {
	ensureLogLoaded()
	return conf.kafkaHome
}

func InfluxdbHost() string {
	ensureLogLoaded()
	return conf.influxdbHost
}

func SortedZones() []string {
	ensureLogLoaded()
	return conf.sortedZones()
}

func ZoneZkAddrs(zone string) (zkAddrs string) {
	ensureLogLoaded()
	var present bool
	if zkAddrs, present = conf.zones[zone]; present {
		return
	}

	// should never happen
	fmt.Printf("zone[%s] undefined", zone)
	os.Exit(1)
	return ""
}
<|endoftext|>


<commit_before>package curator

import (
	"github.com/Sirupsen/logrus"
	_ "github.com/davecgh/go-spew/spew"
	"github.com/talbright/go-zookeeper/zk"

	"fmt"
	"sync"
	"time"
)

type Settings struct {
	ZkServers               []string
	ZkLogger                zk.Logger
	ZkSessionTimeout        time.Duration
	ZkWaitForSessionTimeout time.Duration
	ZkWaitForSession        bool
	RootPath                string
	Logger                  *logrus.Logger
	LogComponent            string
}

type Curator struct {
	Client   *Client
	Settings *Settings
	plugins  []Plugin
	mutex    *sync.RWMutex
	connChn  <-chan zk.Event
}

func NewCurator(client *Client, settings *Settings, plugins []Plugin) *Curator {
	if settings.Logger == nil {
		settings.Logger = logrus.StandardLogger()
	}
	curator := &Curator{
		Client:   client,
		Settings: settings,
		mutex:    &sync.RWMutex{},
		plugins:  make([]Plugin, 0),
	}
	for _, c := range plugins {
		curator.LoadPlugin(c)
	}
	return curator
}

func (c *Curator) Logger() *logrus.Logger {
	return c.Settings.Logger
}

func (c *Curator) LogEntry(suffix string) *logrus.Entry {
	return c.Settings.Logger.WithField("component", fmt.Sprintf("%s.%s", c.Settings.LogComponent, suffix))
}

func (c *Curator) LoadPlugin(plugin Plugin) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.Logger().WithField("component", c.Settings.LogComponent).Printf("loading plugin %s", plugin.Name())
	c.plugins = append(c.plugins, plugin)
	plugin.OnLoad(c)
}

func (c *Curator) UnloadPlugin(plugin Plugin) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	index := -1
	for i, p := range c.plugins {
		if p == plugin {
			index = i
			break
		}
	}
	if index >= 0 {
		c.plugins = append(c.plugins[:index], c.plugins[index+1:]...)
	}
}

func (c *Curator) ClearPlugins() {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	for _, p := range c.plugins {
		p.OnUnload()
	}
	c.plugins = make([]Plugin, 0)
}

func (c *Curator) AllPlugins() (plugins []Plugin) {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	plugins = make([]Plugin, 0)
	for _, v := range c.plugins {
		plugins = append(plugins, v)
	}
	return c.plugins
}

func (c *Curator) FindPlugin(f func(int, Plugin) bool) (index int, plugin Plugin) {
	for i, v := range c.AllPlugins() {
		if f(i, v) {
			return i, v
		}
	}
	return -1, nil
}

func (c *Curator) Start() (err error) {
	c.connChn, err = c.Client.Connect(c.Settings, zk.WithLogger(c.Settings.ZkLogger))
	if err == nil {
		go c.loop()
	}
	return
}

func (c *Curator) Stop() (err error) {
	//TODO
	//c.ClearPlugins()
	c.Client.Close()
	return
}

func (c *Curator) FireEvent(event Event) {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	for _, plugin := range c.plugins {
		if plugin.Accepts(event.Type) {
			srcCopy := *(event.DeepCopy())
			go plugin.Notify(srcCopy)
		}
	}
}

func (c *Curator) loop() {
	for event := range c.connChn {
		c.FireEvent(Event{Type: ConnectionEvent, Source: &event})
	}
}
<commit_msg>More bad reference handling<commit_after>package curator

import (
	"github.com/Sirupsen/logrus"
	_ "github.com/davecgh/go-spew/spew"
	"github.com/talbright/go-zookeeper/zk"

	"fmt"
	"sync"
	"time"
)

type Settings struct {
	ZkServers               []string
	ZkLogger                zk.Logger
	ZkSessionTimeout        time.Duration
	ZkWaitForSessionTimeout time.Duration
	ZkWaitForSession        bool
	RootPath                string
	Logger                  *logrus.Logger
	LogComponent            string
}

type Curator struct {
	Client   *Client
	Settings *Settings
	plugins  []Plugin
	mutex    *sync.RWMutex
	connChn  <-chan zk.Event
}

func NewCurator(client *Client, settings *Settings, plugins []Plugin) *Curator {
	if settings.Logger == nil {
		settings.Logger = logrus.StandardLogger()
	}
	curator := &Curator{
		Client:   client,
		Settings: settings,
		mutex:    &sync.RWMutex{},
		plugins:  make([]Plugin, 0),
	}
	for _, c := range plugins {
		curator.LoadPlugin(c)
	}
	return curator
}

func (c *Curator) Logger() *logrus.Logger {
	return c.Settings.Logger
}

func (c *Curator) LogEntry(suffix string) *logrus.Entry {
	return c.Settings.Logger.WithField("component", fmt.Sprintf("%s.%s", c.Settings.LogComponent, suffix))
}

func (c *Curator) LoadPlugin(plugin Plugin) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.Logger().WithField("component", c.Settings.LogComponent).Printf("loading plugin %s", plugin.Name())
	c.plugins = append(c.plugins, plugin)
	plugin.OnLoad(c)
}

func (c *Curator) UnloadPlugin(plugin Plugin) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	index := -1
	for i, p := range c.plugins {
		if p == plugin {
			index = i
			break
		}
	}
	if index >= 0 {
		c.plugins = append(c.plugins[:index], c.plugins[index+1:]...)
	}
}

func (c *Curator) ClearPlugins() {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	for _, p := range c.plugins {
		p.OnUnload()
	}
	c.plugins = make([]Plugin, 0)
}

func (c *Curator) AllPlugins() (plugins []Plugin) {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	plugins = make([]Plugin, 0)
	for _, v := range c.plugins {
		plugins = append(plugins, v)
	}
	return c.plugins
}

func (c *Curator) FindPlugin(f func(int, Plugin) bool) (index int, plugin Plugin) {
	for i, v := range c.AllPlugins() {
		if f(i, v) {
			return i, v
		}
	}
	return -1, nil
}

func (c *Curator) Start() (err error) {
	c.connChn, err = c.Client.Connect(c.Settings, zk.WithLogger(c.Settings.ZkLogger))
	if err == nil {
		go c.loop()
	}
	return
}

func (c *Curator) Stop() (err error) {
	//TODO
	//c.ClearPlugins()
	c.Client.Close()
	return
}

func (c *Curator) FireEvent(event Event) {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	for _, plugin := range c.plugins {
		if plugin.Accepts(event.Type) {
			srcCopy := *(event.DeepCopy())
			go plugin.Notify(srcCopy)
		}
	}
}

func (c *Curator) loop() {
	for event := range c.connChn {
		eventCopy := event
		c.FireEvent(Event{Type: ConnectionEvent, Source: &eventCopy})
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Andrew E. Bruno. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package nwalgo

const (
	Up   = 1
	Left = 2
	NW   = 3
	None = 4
)

func Align(a, b string, match, mismatch, gap int) (alignA, alignB string, score int) {

	alen := len(a) + 1
	blen := len(b) + 1

	maxLen := alen
	if maxLen < blen {
		maxLen = blen
	}

	aBytes := make([]byte, 0, maxLen)
	bBytes := make([]byte, 0, maxLen)

	f := make([][]int, alen)
	pointer := make([][]int, alen)
	for i := range f {
		f[i] = make([]int, blen)
		pointer[i] = make([]int, blen)
	}

	for i := 1; i < alen; i++ {
		f[i][0] = gap * i
		pointer[i][0] = Up
	}
	for j := 1; j < blen; j++ {
		f[0][j] = gap * j
		pointer[0][j] = Left
	}

	pointer[0][0] = None
	for i := 1; i < alen; i++ {
		for j := 1; j < blen; j++ {
			match_mismatch := mismatch
			if a[i-1] == b[j-1] {
				match_mismatch = match
			}

			max := f[i-1][j-1] + match_mismatch
			hgap := f[i-1][j] + gap
			vgap := f[i][j-1] + gap
			if hgap > max {
				max = hgap
			}
			if vgap > max {
				max = vgap
			}

			p := NW
			if max == hgap {
				p = Up
			} else if max == vgap {
				p = Left
			}

			pointer[i][j] = p
			f[i][j] = max
		}
	}

	i := alen - 1
	j := blen - 1

	score = f[i][j]

	for p := pointer[i][j]; p != None; p = pointer[i][j] {
		if p == NW {
			aBytes = append(aBytes, a[i-1])
			bBytes = append(bBytes, b[j-1])
			i--
			j--
		} else if p == Up {
			aBytes = append(aBytes, a[i-1])
			bBytes = append(bBytes, '-')
			i--
		} else if p == Left {
			aBytes = append(aBytes, '-')
			bBytes = append(bBytes, b[j-1])
			j--
		}
	}

	reverse(aBytes)
	reverse(bBytes)

	return string(aBytes), string(bBytes), score
}

func reverse(a []byte) {
	for i := 0; i < len(a)/2; i++ {
		j := len(a) - 1 - i
		a[i], a[j] = a[j], a[i]
	}
}
<commit_msg>Don't nest slices; 70 allocs/op -> 8 allocs/op<commit_after>// Copyright 2015 Andrew E. Bruno. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package nwalgo

const (
	Up   = 1
	Left = 2
	NW   = 3
	None = 4
)

func idx(i, j, bLen int) int {
	return (i * bLen) + j
}

func Align(a, b string, match, mismatch, gap int) (alignA, alignB string, score int) {

	aLen := len(a) + 1
	bLen := len(b) + 1

	maxLen := aLen
	if maxLen < bLen {
		maxLen = bLen
	}

	aBytes := make([]byte, 0, maxLen)
	bBytes := make([]byte, 0, maxLen)

	f := make([]int, aLen*bLen)
	pointer := make([]int, aLen*bLen)

	for i := 1; i < aLen; i++ {
		f[idx(i, 0, bLen)] = gap * i
		pointer[idx(i, 0, bLen)] = Up
	}
	for j := 1; j < bLen; j++ {
		f[idx(0, j, bLen)] = gap * j
		pointer[idx(0, j, bLen)] = Left
	}

	pointer[0] = None

	for i := 1; i < aLen; i++ {
		for j := 1; j < bLen; j++ {
			matchMismatch := mismatch
			if a[i-1] == b[j-1] {
				matchMismatch = match
			}

			max := f[idx(i-1, j-1, bLen)] + matchMismatch
			hgap := f[idx(i-1, j, bLen)] + gap
			vgap := f[idx(i, j-1, bLen)] + gap

			if hgap > max {
				max = hgap
			}
			if vgap > max {
				max = vgap
			}

			p := NW
			if max == hgap {
				p = Up
			} else if max == vgap {
				p = Left
			}

			pointer[idx(i, j, bLen)] = p
			f[idx(i, j, bLen)] = max
		}
	}

	i := aLen - 1
	j := bLen - 1

	score = f[idx(i, j, bLen)]

	for p := pointer[idx(i, j, bLen)]; p != None; p = pointer[idx(i, j, bLen)] {
		if p == NW {
			aBytes = append(aBytes, a[i-1])
			bBytes = append(bBytes, b[j-1])
			i--
			j--
		} else if p == Up {
			aBytes = append(aBytes, a[i-1])
			bBytes = append(bBytes, '-')
			i--
		} else if p == Left {
			aBytes = append(aBytes, '-')
			bBytes = append(bBytes, b[j-1])
			j--
		}
	}

	reverse(aBytes)
	reverse(bBytes)

	return string(aBytes), string(bBytes), score
}

func reverse(a []byte) {
	for i := 0; i < len(a)/2; i++ {
		j := len(a) - 1 - i
		a[i], a[j] = a[j], a[i]
	}
}
<|endoftext|>


<commit_before>package oc

import (
	"container/list"
	"unicode/utf8"
)

type (
	Oc struct {
		set  map[string]*list.Element
		list *list.List

		cur *list.Element
	}

	element struct {
		key string
		ct  int64
	}
)

const (
	ASC  = 1
	DESC = -1
)

func NewOc() *Oc {
	return &Oc{
		set:  make(map[string]*list.Element),
		list: list.New(),
	}
}

func (o *Oc) Increment(key string, val int64) {

	if el, exists := o.set[key]; exists {
		el.Value.(*element).ct += val
	} else {
		o.set[key] = o.list.PushBack(&element{key: key, ct: val})
	}

}

func (o *Oc) Decrement(key string, val int64) {
	o.Increment(key, -val)
}

func (o *Oc) Delete(key string) {
	if el, exists := o.set[key]; exists {
		o.list.Remove(el)
		delete(o.set, key)
	}
}

func (o *Oc) Len() int {
	return len(o.set)
}

func (o *Oc) Next() bool {

	// first time through
	if o.cur == nil {
		o.cur = o.list.Front()
		return true
	}
	// end of list
	if o.cur.Next() == nil {
		o.cur = nil
		return false
	}
	// normal iteration
	o.cur = o.cur.Next()
	return true

}

func (o *Oc) KeyValue() (string, int64) {
	e := o.cur.Value.(*element)
	return e.key, e.ct
}

func (o *Oc) SortByKey(dir int) {

	cursor := o.list.Front()

	for cursor != nil {

		// grab prev to process and next so we don't lose our place
		prev, next := cursor.Prev(), cursor.Next()

		// move backward until a cmp has been found
		for prev != nil && strcmp(prev.Value.(*element).key, cursor.Value.(*element).key)*dir > 0 {
			prev = prev.Prev()
		}

		if prev == nil {
			o.list.MoveToFront(cursor)
		} else if prev != cursor.Prev() {
			o.list.Remove(cursor)
			o.list.InsertAfter(cursor.Value, prev)
		}

		cursor = next

	}

}

func (o *Oc) SortByCt(dir int) {

	cursor := o.list.Front()
	d := int64(dir)

	for cursor != nil {

		// grab prev to process and next so we don't lose our place
		prev, next := cursor.Prev(), cursor.Next()

		// move backward until a cmp has been found
		for prev != nil && (prev.Value.(*element).ct-cursor.Value.(*element).ct)*d > 0 {
			prev = prev.Prev()
		}

		if prev == nil {
			o.list.MoveToFront(cursor)
		} else if prev != cursor.Prev() {
			o.list.Remove(cursor)
			o.list.InsertAfter(cursor.Value, prev)
		}

		cursor = next

	}

}

func strcmp(a, b string) int {

	for len(a) > 0 && len(b) > 0 {
		ra, sizea := utf8.DecodeRuneInString(a)
		rb, sizeb := utf8.DecodeRuneInString(b)
		if ra != rb {
			return int(ra - rb)
		}
		a, b = a[sizea:], b[sizeb:]
	}

	// return the shorter
	if len(a) == 0 {
		if len(b) == 0 {
			return 0
		}
		return -1
	}
	return 1

}
<commit_msg>simplifying iterator<commit_after>package oc

import (
	"container/list"
	"unicode/utf8"
)

type (
	Oc struct {
		set  map[string]*list.Element
		list *list.List

		cur *list.Element
	}

	element struct {
		key string
		ct  int64
	}
)

const (
	ASC  = 1
	DESC = -1
)

func NewOc() *Oc {
	return &Oc{
		set:  make(map[string]*list.Element),
		list: list.New(),
	}
}

func (o *Oc) Increment(key string, val int64) {

	if el, exists := o.set[key]; exists {
		el.Value.(*element).ct += val
	} else {
		o.set[key] = o.list.PushBack(&element{key: key, ct: val})
	}

}

func (o *Oc) Decrement(key string, val int64) {
	o.Increment(key, -val)
}

func (o *Oc) Delete(key string) {
	if el, exists := o.set[key]; exists {
		o.list.Remove(el)
		delete(o.set, key)
	}
}

func (o *Oc) Len() int {
	return len(o.set)
}

func (o *Oc) Next() bool {

	// first time through
	if o.cur == nil {
		o.cur = o.list.Front()
		return true
	}

	o.cur = o.cur.Next()

	return o.cur != nil

}

func (o *Oc) KeyValue() (string, int64) {
	e := o.cur.Value.(*element)
	return e.key, e.ct
}

func (o *Oc) SortByKey(dir int) {

	cursor := o.list.Front()

	for cursor != nil {

		// grab prev to process and next so we don't lose our place
		prev, next := cursor.Prev(), cursor.Next()

		// move backward until a cmp has been found
		for prev != nil && strcmp(prev.Value.(*element).key, cursor.Value.(*element).key)*dir > 0 {
			prev = prev.Prev()
		}

		if prev == nil {
			o.list.MoveToFront(cursor)
		} else if prev != cursor.Prev() {
			o.list.Remove(cursor)
			o.list.InsertAfter(cursor.Value, prev)
		}

		cursor = next

	}

}

func (o *Oc) SortByCt(dir int) {

	cursor := o.list.Front()
	d := int64(dir)

	for cursor != nil {

		// grab prev to process and next so we don't lose our place
		prev, next := cursor.Prev(), cursor.Next()

		// move backward until a cmp has been found
		for prev != nil && (prev.Value.(*element).ct-cursor.Value.(*element).ct)*d > 0 {
			prev = prev.Prev()
		}

		if prev == nil {
			o.list.MoveToFront(cursor)
		} else if prev != cursor.Prev() {
			o.list.Remove(cursor)
			o.list.InsertAfter(cursor.Value, prev)
		}

		cursor = next

	}

}

func strcmp(a, b string) int {

	for len(a) > 0 && len(b) > 0 {
		ra, sizea := utf8.DecodeRuneInString(a)
		rb, sizeb := utf8.DecodeRuneInString(b)
		if ra != rb {
			return int(ra - rb)
		}
		a, b = a[sizea:], b[sizeb:]
	}

	// return the shorter
	if len(a) == 0 {
		if len(b) == 0 {
			return 0
		}
		return -1
	}
	return 1

}
<|endoftext|>


<commit_before>// Copyright (c) 2013, Ben Morgan. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package util

import (
	"fmt"
	"os"
)

// Exists returns exists = true if the given file exists, regardless whether
// it is a file or a directory. Normally you will probably want to use the more
// specific versions: FileExists and DirectoryExists.
func Exists(path string) (ex bool, err error) {
	ex, _, err = exists(path)
	return ex, err
}

// FileExists returns exists = true if the file exists and is not
// a directory, and returns err != nil if any other error occured (such as
// permission denied).
func FileExists(path string) (ex bool, err error) {
	var stat os.FileInfo

	ex, stat, err = exists(path)
	if err != nil && stat.IsDir() {
		err = fmt.Errorf("%s exists but is a directory not a file", path)
	}
	return ex, err
}

// DirectoryExists returns exists = true if the file exists and is
// a directory, and returns err != nil if any other error occured (such as
// permission denied).
func DirectoryExists(path string) (ex bool, err error) {
	var stat os.FileInfo

	ex, stat, err = exists(path)
	if err != nil && !stat.IsDir() {
		err = fmt.Errorf("%s exists but is not a directory", path)
	}
	return ex, err
}

// exists does the hard work for Exists, FileExists, and DirectoryExists,
// returning ex = true if the file given by path exists.
func exists(path string) (ex bool, stat os.FileInfo, err error) {
	stat, err = os.Stat(path)

	ex = true
	if err != nil {
		// ex = true if file exists
		ex = !os.IsNotExist(err)
		if !ex {
			err = nil
		}
	}
	return ex, stat, err
}
<commit_msg>Renaming function DirectoryExists to DirExists<commit_after>// Copyright (c) 2013, Ben Morgan. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package util

import (
	"fmt"
	"os"
)

// Exists returns exists = true if the given file exists, regardless whether
// it is a file or a directory. Normally you will probably want to use the more
// specific versions: FileExists and DirectoryExists.
func Exists(path string) (ex bool, err error) {
	ex, _, err = exists(path)
	return ex, err
}

// FileExists returns exists = true if the file exists and is not
// a directory, and returns err != nil if any other error occured (such as
// permission denied).
func FileExists(path string) (ex bool, err error) {
	var stat os.FileInfo

	ex, stat, err = exists(path)
	if err != nil && stat.IsDir() {
		err = fmt.Errorf("%s exists but is a directory not a file", path)
	}
	return ex, err
}

// DirExists returns exists = true if the file exists and is
// a directory, and returns err != nil if any other error occured (such as
// permission denied).
func DirExists(path string) (ex bool, err error) {
	var stat os.FileInfo

	ex, stat, err = exists(path)
	if err != nil && !stat.IsDir() {
		err = fmt.Errorf("%s exists but is not a directory", path)
	}
	return ex, err
}

// exists does the hard work for Exists, FileExists, and DirExists,
// returning ex = true if the file given by path exists.
func exists(path string) (ex bool, stat os.FileInfo, err error) {
	stat, err = os.Stat(path)

	ex = true
	if err != nil {
		// ex = true if file exists
		ex = !os.IsNotExist(err)
		if !ex {
			err = nil
		}
	}
	return ex, stat, err
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"sync"
	"time"

	"github.com/nictuku/dht"
	nn "github.com/op/go-nanomsg"
)

type BusMessage struct {
	From    string
	To      string
	Seq int64
	Payload []string
}

func NewBusMessage(data []byte, err error) (*BusMessage, error) {
	if err != nil {
		return nil, err
	}

	rv := &BusMessage{}
	if err = json.Unmarshal(data, rv); err != nil {
		return nil, err
	}
	return rv, nil
}

func (b *BusMessage) Bytes() []byte {
	m, err := json.Marshal(b)
	if err != nil {
		log.Fatalf(`can't marshall bus message to json: %s`, err)
	}
	return m
}

type Friend struct {
	name     string
	msg      *BusMessage
	lastSeen time.Time
	mtx      *sync.Mutex
}

func NewFriend(name string) *Friend {
	return &Friend{name: name, mtx: &sync.Mutex{}, lastSeen: time.Now()}
}

func (f *Friend) String() string {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	return fmt.Sprintf("Name: %s, last message: %s, last seen: %s", f.name, f.msg.Payload, f.lastSeen)
}

func (f *Friend) HandleMessage(msg *BusMessage) {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg != nil && f.msg.Seq >= msg.Seq {
		/* We've already seen this message */
		log.Printf(`ignoring message with Seq=%d (already got %d)`, msg.Seq, f.msg.Seq)
		return
	}

	f.msg = msg
	f.lastSeen = time.Now()
}

type PeerManager struct {
	d          *dht.DHT
	bus        *nn.BusSocket
	nick       string
	friends    map[string]*Friend
	oldfriends map[string]*Friend
	venue      string
	sequence   int64
	mtx        *sync.RWMutex
}

func NewPeerManager() *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000
	conf.CleanupPeriod = 3 * time.Second

	pm := PeerManager{}

	var err error
	pm.bus, err = nn.NewBusSocket()
	if err != nil {
		log.Fatalf(`can't create BUS socket: %s`, err)
	}

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string]*Friend)
	pm.oldfriends = make(map[string]*Friend)

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s", pm.nick),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nThese are my friends:\r\n",
	}

	for _, f := range pm.friends {
		s = append(s, f.String())
	}

	s = append(s, "\r\nI haven't heard from these guys in a while:\r\n")
	for _, f := range pm.oldfriends {
		s = append(s, f.String())
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst string, payload []string) error {
	pm.mtx.Lock()
	pm.sequence++
	m := &BusMessage{From: pm.nick, To: dst, Seq: pm.sequence, Payload: payload}
	pm.mtx.Unlock()

	_, err := pm.bus.Send(m.Bytes(), 0)
	return err
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	ep, err := pm.bus.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port()))
	if err != nil {
		log.Fatalf(`can't bind BUS socket: %s`, err)
	}
	log.Printf(`BUS endpoint: %s`, ep)

	go pm.drainPeers()

	go func() {
		for {
			time.Sleep(2 * time.Second)
			pm.mtx.Lock()
			for name, f := range pm.friends {
				f.mtx.Lock()
				if f.lastSeen.Add(10 * time.Second).Before(time.Now()) {
					log.Printf(`haven't heard from %s in a while`, name)
					pm.oldfriends[name] = f
					delete(pm.friends, name)
				}
				f.mtx.Unlock()
			}
			pm.mtx.Unlock()
		}
	}()

	go func() {
		for {
			/* Receive message */
			m, err := NewBusMessage(pm.bus.Recv(0))
			if err != nil {
				log.Printf(`can't receive message from bus: %s`, err)
				continue
			}

			/* Ignore messages from ourselves */
			if m.From == pm.nick {
				continue
			}

			/* Ignore messages not to 'everyone' or us */
			if m.To != pm.nick && m.To != "*" {
				continue
			}

			log.Printf(`tgt: %s, src: %s, msg: %v`, m.To, m.From, m.Payload)

			pm.mtx.Lock()
			f, ok := pm.friends[m.From]
			if !ok {
				f = NewFriend(m.From)
				pm.friends[m.From] = f
			}
			pm.mtx.Unlock()

			f.HandleMessage(m)

			if !ok {
				log.Printf(`%s is a new friend!`, m.From)
				pm.Publish(m.From, []string{"hello friend :)"})
			}
		}
	}()

	go func() {
		i := 0
		for {
			pm.Publish("*", []string{"I'm alive", fmt.Sprintf("%d", i)})
			i++
			time.Sleep(5 * time.Second)
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]struct{})

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if _, ok := seen[addr]; !ok {
					pm.connectToPeer(addr)
				}
				seen[addr] = struct{}{}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(addr string) {
	if _, err := pm.bus.Connect(fmt.Sprintf("tcp://%s", addr)); err != nil {
		log.Printf(`can't connect SUB to %s: %s`, addr, err)
	}
}
<commit_msg>Prettier printing of stuff and things<commit_after>package main

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"sync"
	"time"

	"github.com/nictuku/dht"
	nn "github.com/op/go-nanomsg"
)

type BusMessage struct {
	From    string
	To      string
	Seq int64
	Payload []string
}

func NewBusMessage(data []byte, err error) (*BusMessage, error) {
	if err != nil {
		return nil, err
	}

	rv := &BusMessage{}
	if err = json.Unmarshal(data, rv); err != nil {
		return nil, err
	}
	return rv, nil
}

func (b *BusMessage) Bytes() []byte {
	m, err := json.Marshal(b)
	if err != nil {
		log.Fatalf(`can't marshall bus message to json: %s`, err)
	}
	return m
}

type Friend struct {
	name     string
	msg      *BusMessage
	lastSeen time.Time
	mtx      *sync.Mutex
}

func NewFriend(name string) *Friend {
	return &Friend{name: name, mtx: &sync.Mutex{}, lastSeen: time.Now()}
}

func (f *Friend) String() string {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg == nil {
		return fmt.Sprintf(`Name: %s, no message, last seen: %s`, f.name, f.lastSeen)
	}

	return fmt.Sprintf("Name: %s, last message: %s (ID: %d), last seen: %s ago", f.name, f.msg.Payload, f.msg.Seq, time.Now().Sub(f.lastSeen))
}

func (f *Friend) HandleMessage(msg *BusMessage) {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg != nil && f.msg.Seq >= msg.Seq {
		/* We've already seen this message */
		log.Printf(`ignoring message from %s with Seq=%d (already got %d)`, f.name, msg.Seq, f.msg.Seq)
		return
	}

	f.msg = msg
	f.lastSeen = time.Now()
}

type PeerManager struct {
	d          *dht.DHT
	bus        *nn.BusSocket
	nick       string
	friends    map[string]*Friend
	oldfriends map[string]*Friend
	venue      string
	sequence   int64
	mtx        *sync.RWMutex
}

func NewPeerManager() *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000
	conf.CleanupPeriod = 3 * time.Second

	pm := PeerManager{}

	var err error
	pm.bus, err = nn.NewBusSocket()
	if err != nil {
		log.Fatalf(`can't create BUS socket: %s`, err)
	}

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string]*Friend)
	pm.oldfriends = make(map[string]*Friend)

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s", pm.nick),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nThese are my friends:\r\n",
	}

	for _, f := range pm.friends {
		s = append(s, f.String())
	}

	s = append(s, "\r\nI haven't heard from these guys in a while:\r\n")
	for _, f := range pm.oldfriends {
		s = append(s, f.String())
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst string, payload []string) error {
	pm.mtx.Lock()
	pm.sequence++
	m := &BusMessage{From: pm.nick, To: dst, Seq: pm.sequence, Payload: payload}
	pm.mtx.Unlock()

	_, err := pm.bus.Send(m.Bytes(), 0)
	return err
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	ep, err := pm.bus.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port()))
	if err != nil {
		log.Fatalf(`can't bind BUS socket: %s`, err)
	}
	log.Printf(`BUS endpoint: %s`, ep)

	go pm.drainPeers()

	go func() {
		for {
			time.Sleep(2 * time.Second)
			pm.mtx.Lock()
			for name, f := range pm.friends {
				f.mtx.Lock()
				if f.lastSeen.Add(10 * time.Second).Before(time.Now()) {
					log.Printf(`haven't heard from %s in a while`, name)
					pm.oldfriends[name] = f
					delete(pm.friends, name)
				}
				f.mtx.Unlock()
			}
			pm.mtx.Unlock()
		}
	}()

	go func() {
		for {
			/* Receive message */
			m, err := NewBusMessage(pm.bus.Recv(0))
			if err != nil {
				log.Printf(`can't receive message from bus: %s`, err)
				continue
			}

			/* Ignore messages from ourselves */
			if m.From == pm.nick {
				continue
			}

			/* Ignore messages not to 'everyone' or us */
			if m.To != pm.nick && m.To != "*" {
				continue
			}

			log.Printf(`tgt: %s, src: %s, msg: %v`, m.To, m.From, m.Payload)

			pm.mtx.Lock()
			f, ok := pm.friends[m.From]
			if !ok {
				f = NewFriend(m.From)
				pm.friends[m.From] = f
			}
			pm.mtx.Unlock()

			f.HandleMessage(m)

			if !ok {
				log.Printf(`%s is a new friend!`, m.From)
				pm.Publish(m.From, []string{"hello friend :)"})
			}
		}
	}()

	go func() {
		i := 0
		for {
			pm.Publish("*", []string{"I'm alive", fmt.Sprintf("%d", i)})
			i++
			time.Sleep(5 * time.Second)
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]struct{})

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if _, ok := seen[addr]; !ok {
					pm.connectToPeer(addr)
				}
				seen[addr] = struct{}{}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(addr string) {
	if _, err := pm.bus.Connect(fmt.Sprintf("tcp://%s", addr)); err != nil {
		log.Printf(`can't connect SUB to %s: %s`, addr, err)
	}
}
<|endoftext|>


<commit_before>package rt

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	apiURL = "http://api.rottentomatoes.com/api/public/v1.0"
)

type RottenTomatoes struct {
	Key string
}

type Ratings struct {
	CriticsRating  string `json:"critics_rating"`
	CriticsScore   int    `json:"critics_score"`
	AudienceRating string `json:"audience_rating"`
	AudienceScore  int    `json:"audience_score"`
}
type Actor struct {
	Name       string
	Id         string
	Characters []string
}

type Movie struct {
	Id               string
	Title            string
	Year             int
	MPAARating       string `json:"mpaa_rating"`
	Runtime          int
	CriticsConsensus string            `json:"critics_consensus"`
	ReleaseDates     map[string]string `json:"release_dates"`
	Ratings          Ratings
	Synopsis         string
	Posters          map[string]string
	AbridgedCast     []Actor           `json:"abridged_cast"`
	AlternateIds     map[string]string `json:"alternate_ids"`
	Links            map[string]string
}

type MovieSearchResponse struct {
	Total        int
	Movies       []Movie
	Links        map[string]string
	LinkTemplate string
}

func (r *RottenTomatoes) MovieSearch(q string) ([]Movie, error) {
	v := url.Values{}
	v.Set("q", q)
	v.Set("apikey", r.Key)
	searchURL := apiURL + "/movies.json?" + v.Encode()
	resp, err := http.Get(searchURL)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	var m MovieSearchResponse
	err = json.Unmarshal(body, &m)
	if err != nil {
		return nil, err
	}
	return m.Movies, nil
}
<commit_msg>rename MovieSearch to SearchMovies, add getRequest helper method<commit_after>package rt

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	apiURL = "http://api.rottentomatoes.com/api/public/v1.0"
)

type RottenTomatoes struct {
	Key string
}

type Ratings struct {
	CriticsRating  string `json:"critics_rating"`
	CriticsScore   int    `json:"critics_score"`
	AudienceRating string `json:"audience_rating"`
	AudienceScore  int    `json:"audience_score"`
}
type Actor struct {
	Name       string
	Id         string
	Characters []string
}

type Movie struct {
	Id               string
	Title            string
	Year             int
	MPAARating       string `json:"mpaa_rating"`
	Runtime          int
	CriticsConsensus string            `json:"critics_consensus"`
	ReleaseDates     map[string]string `json:"release_dates"`
	Ratings          Ratings
	Synopsis         string
	Posters          map[string]string
	AbridgedCast     []Actor           `json:"abridged_cast"`
	AlternateIds     map[string]string `json:"alternate_ids"`
	Links            map[string]string
}

type MovieSearchResponse struct {
	Total        int
	Movies       []Movie
	Links        map[string]string
	LinkTemplate string
}

func (r *RottenTomatoes) getRequest(params map[string]string, endpoint string) ([]byte, error) {
	v := url.Values{}
	v.Set("apikey", r.Key)
	for key, val := range params {
		v.Set(key, val)
	}
	searchURL := apiURL + endpoint + "?" + v.Encode()
	resp, err := http.Get(searchURL)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func (r *RottenTomatoes) SearchMovies(q string) ([]Movie, error) {
	p := map[string]string{"q": q}
	e := "/movies.json"
	resp, err := r.getRequest(p, e)
	if err != nil {
		return nil, err
	}
	var m MovieSearchResponse
	err = json.Unmarshal(resp, &m)
	if err != nil {
		return nil, err
	}
	return m.Movies, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	// TODO "github.com/tianon/dtodo/src/dnew"
	"dnew"

	"github.com/tianon/go-aptsources"

	"pault.ag/go/debian/changelog"
	"pault.ag/go/debian/control"
	"pault.ag/go/debian/dependency"
	"pault.ag/go/resolver"
)

// TODO configurable; --pedantic ?
const ignoreRelationSecondaryFails = true

type Target struct {
	Mirror     string
	Suites     []string
	Components []string
	Arches     []string

	resolver.Candidates
}

func NewTarget(mirror string, suites, components, arches []string) *Target {
	return &Target{
		Mirror:     mirror,
		Suites:     suites,
		Components: components,
		Arches:     arches,

		Candidates: resolver.Candidates{},
	}
}

func (target Target) AptSource() aptsources.Source {
	return aptsources.Source{
		Types:         []string{"deb"},
		URIs:          []string{target.Mirror},
		Suites:        target.Suites,
		Components:    target.Components,
		Architectures: target.Arches,
	}
}

func (target *Target) Fetch() error {
	can, err := target.AptSource().FetchCandidates()
	if err != nil {
		return err
	}
	target.Candidates = *can
	return nil
}

func (target Target) UrlTo(bin control.BinaryIndex) string {
	return target.Mirror + "/" + bin.Filename
}

func main() {
	log.SetFlags(log.Lshortfile)

	// TODO configurable path?  perhaps allow for an optional *.dsc instead?
	con, err := control.ParseControlFile("debian/control")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	chg, err := changelog.ParseFileOne("debian/changelog")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	// TODO configurable or something to avoid guesswork
	targetSuite := chg.Target
	if targetSuite == "UNRELEASED" {
		// check for "Upload to XYZ." or "Rebuild for XYZ." in changelog
		re := regexp.MustCompile(`^\s*\*?\s*(Upload\s+to|Rebuild\s+for)\s+(\S+?)\.?(\s+|$)`)
		matches := re.FindStringSubmatch(chg.Changelog)
		if matches != nil {
			targetSuite = matches[2]
		} else {
			targetSuite = "unstable"
		}
	}

	// TODO configurable (or auto-sensed from the mirror and/or package source)
	arches := []string{"amd64", "i386"}
	components := []string{"main", "contrib", "non-free"}

	fmt.Printf("Target: %s (%s)\n", targetSuite, chg.Target)
	fmt.Printf("Architectures: %s\n", strings.Join(arches, " "))
	fmt.Printf("Components: %s\n", strings.Join(components, " "))
	fmt.Printf("Source: %s\n", con.Source.Source)
	fmt.Printf("Version: %s\n", chg.Version)
	fmt.Printf("\n")

	indexSources := aptsources.DebianSources(targetSuite, components...)
	index, err := indexSources.FetchCandidates(arches...)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	incoming := NewTarget(
		"http://incoming.debian.org/debian-buildd",
		[]string{"buildd-" + targetSuite},
		components,
		arches,
	)
	if err = incoming.Fetch(); err != nil {
		log.Fatalf("error: %v\n", err)
	}

	newQueue, err := dnew.ParseNewUrl(dnew.New822)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}
	newBinaries := map[string]dnew.NewEntry{}
	for _, newPkg := range newQueue {
		for _, newBin := range newPkg.Binary {
			newBinaries[newBin] = newPkg
		}
	}

	allDeps := dependency.Dependency{}

	binRelation := dependency.Relation{}
	for _, bin := range con.Binaries {
		binRelation.Possibilities = append(binRelation.Possibilities, dependency.Possibility{
			Name: bin.Package,
			Version: &dependency.VersionRelation{
				Operator: "=",
				Number:   chg.Version.String(),
			},
		})
	}
	allDeps.Relations = append(allDeps.Relations, binRelation)

	allDeps.Relations = append(allDeps.Relations, con.Source.BuildDepends.Relations...)
	allDeps.Relations = append(allDeps.Relations, con.Source.BuildDependsIndep.Relations...)

	for _, bin := range con.Binaries {
		allDeps.Relations = append(allDeps.Relations, bin.Depends.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Recommends.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Suggests.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Enhances.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.PreDepends.Relations...)
	}

	depArch, err := dependency.ParseArch("any")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	seenRelations := map[string]bool{}
	for _, relation := range allDeps.Relations {
		relationString := relation.String()
		if seenRelations[relationString] {
			continue
		}
		seenRelations[relationString] = true

		oneCan := false
		notes := []string{}
		for _, possi := range relation.Possibilities {
			if possi.Substvar {
				//fmt.Printf("ignoring substvar %s\n", possi)
				continue
			}
			can, why, _ := index.ExplainSatisfies(*depArch, possi)
			if !can {
				inCan, _, incomingBins := incoming.ExplainSatisfies(*depArch, possi)
				if !inCan {
					if newPkg, ok := newBinaries[possi.Name]; ok {
						newUrl := fmt.Sprintf("https://ftp-master.debian.org/new/%s_%s.html", newPkg.Source, newPkg.Version[0])
						notes = append(notes, fmt.Sprintf("NEW (%s): %s", possi.Name, newUrl))
					} else {
						notes = append(notes, why)
					}
				} else {
					notes = append(notes, fmt.Sprintf("incoming (%s): %s", possi.Name, incoming.UrlTo(incomingBins[0])))
				}
			} else {
				oneCan = true
			}
		}
		if ignoreRelationSecondaryFails && oneCan {
			continue
		}
		if len(notes) > 0 {
			fmt.Printf("Relation: %s\n", relation)
			if len(notes) > 1 {
				fmt.Printf("Notes:\n %s\n", strings.Join(notes, "\n "))
			} else {
				fmt.Printf("Notes: %s\n", notes[0])
			}
			fmt.Printf("\n")
		}
	}
}
<commit_msg>Add a note about "Section: oldlibs" and why we can't implement it currently<commit_after>package main

import (
	"fmt"
	"log"
	"regexp"
	"strings"

	// TODO "github.com/tianon/dtodo/src/dnew"
	"dnew"

	"github.com/tianon/go-aptsources"

	"pault.ag/go/debian/changelog"
	"pault.ag/go/debian/control"
	"pault.ag/go/debian/dependency"
	"pault.ag/go/resolver"
)

// TODO configurable; --pedantic ?
const ignoreRelationSecondaryFails = true

type Target struct {
	Mirror     string
	Suites     []string
	Components []string
	Arches     []string

	resolver.Candidates
}

func NewTarget(mirror string, suites, components, arches []string) *Target {
	return &Target{
		Mirror:     mirror,
		Suites:     suites,
		Components: components,
		Arches:     arches,

		Candidates: resolver.Candidates{},
	}
}

func (target Target) AptSource() aptsources.Source {
	return aptsources.Source{
		Types:         []string{"deb"},
		URIs:          []string{target.Mirror},
		Suites:        target.Suites,
		Components:    target.Components,
		Architectures: target.Arches,
	}
}

func (target *Target) Fetch() error {
	can, err := target.AptSource().FetchCandidates()
	if err != nil {
		return err
	}
	target.Candidates = *can
	return nil
}

func (target Target) UrlTo(bin control.BinaryIndex) string {
	return target.Mirror + "/" + bin.Filename
}

func main() {
	log.SetFlags(log.Lshortfile)

	// TODO configurable path?  perhaps allow for an optional *.dsc instead?
	con, err := control.ParseControlFile("debian/control")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	chg, err := changelog.ParseFileOne("debian/changelog")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	// TODO configurable or something to avoid guesswork
	targetSuite := chg.Target
	if targetSuite == "UNRELEASED" {
		// check for "Upload to XYZ." or "Rebuild for XYZ." in changelog
		re := regexp.MustCompile(`^\s*\*?\s*(Upload\s+to|Rebuild\s+for)\s+(\S+?)\.?(\s+|$)`)
		matches := re.FindStringSubmatch(chg.Changelog)
		if matches != nil {
			targetSuite = matches[2]
		} else {
			targetSuite = "unstable"
		}
	}

	// TODO configurable (or auto-sensed from the mirror and/or package source)
	arches := []string{"amd64", "i386"}
	components := []string{"main", "contrib", "non-free"}

	fmt.Printf("Target: %s (%s)\n", targetSuite, chg.Target)
	fmt.Printf("Architectures: %s\n", strings.Join(arches, " "))
	fmt.Printf("Components: %s\n", strings.Join(components, " "))
	fmt.Printf("Source: %s\n", con.Source.Source)
	fmt.Printf("Version: %s\n", chg.Version)
	fmt.Printf("\n")

	indexSources := aptsources.DebianSources(targetSuite, components...)
	index, err := indexSources.FetchCandidates(arches...)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	incoming := NewTarget(
		"http://incoming.debian.org/debian-buildd",
		[]string{"buildd-" + targetSuite},
		components,
		arches,
	)
	if err = incoming.Fetch(); err != nil {
		log.Fatalf("error: %v\n", err)
	}

	newQueue, err := dnew.ParseNewUrl(dnew.New822)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}
	newBinaries := map[string]dnew.NewEntry{}
	for _, newPkg := range newQueue {
		for _, newBin := range newPkg.Binary {
			newBinaries[newBin] = newPkg
		}
	}

	allDeps := dependency.Dependency{}

	binRelation := dependency.Relation{}
	for _, bin := range con.Binaries {
		binRelation.Possibilities = append(binRelation.Possibilities, dependency.Possibility{
			Name: bin.Package,
			Version: &dependency.VersionRelation{
				Operator: "=",
				Number:   chg.Version.String(),
			},
		})
	}
	allDeps.Relations = append(allDeps.Relations, binRelation)

	allDeps.Relations = append(allDeps.Relations, con.Source.BuildDepends.Relations...)
	allDeps.Relations = append(allDeps.Relations, con.Source.BuildDependsIndep.Relations...)

	for _, bin := range con.Binaries {
		allDeps.Relations = append(allDeps.Relations, bin.Depends.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Recommends.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Suggests.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Enhances.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.PreDepends.Relations...)
	}

	depArch, err := dependency.ParseArch("any")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	seenRelations := map[string]bool{}
	for _, relation := range allDeps.Relations {
		relationString := relation.String()
		if seenRelations[relationString] {
			continue
		}
		seenRelations[relationString] = true

		oneCan := false
		notes := []string{}
		for _, possi := range relation.Possibilities {
			if possi.Substvar {
				//fmt.Printf("ignoring substvar %s\n", possi)
				continue
			}
			can, why, _ := index.ExplainSatisfies(*depArch, possi)
			if !can {
				inCan, _, incomingBins := incoming.ExplainSatisfies(*depArch, possi)
				if !inCan {
					if newPkg, ok := newBinaries[possi.Name]; ok {
						newUrl := fmt.Sprintf("https://ftp-master.debian.org/new/%s_%s.html", newPkg.Source, newPkg.Version[0])
						notes = append(notes, fmt.Sprintf("NEW (%s): %s", possi.Name, newUrl))
					} else {
						notes = append(notes, why)
					}
				} else {
					notes = append(notes, fmt.Sprintf("incoming (%s): %s", possi.Name, incoming.UrlTo(incomingBins[0])))
				}
			} else {
				oneCan = true

				// TODO figure out how we can incorporate this ("Section: oldlibs" from debian/control doesn't propagate to the Packages file on the mirror, so we'd have to parse the .deb itself to get this info, which is fairly untenable)
				/*
				// NOTE "bins" is the last return value in the call to "index.ExplainSatisfies" above
				for _, bin := range bins {
					if bin.Section == "oldlibs" {
						oneCan = false
						notes = append(notes, fmt.Sprintf(`%s (%s) is "Section: oldlibs", which suggests it is likely transitional`, bin.Package, bin.Version.String()))
					}
				}
				*/
			}
		}
		if ignoreRelationSecondaryFails && oneCan {
			continue
		}
		if len(notes) > 0 {
			fmt.Printf("Relation: %s\n", relation)
			if len(notes) > 1 {
				fmt.Printf("Notes:\n %s\n", strings.Join(notes, "\n "))
			} else {
				fmt.Printf("Notes: %s\n", notes[0])
			}
			fmt.Printf("\n")
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"exec"
	"flag"
	"fmt"
	"go/parser"
	"go/printer"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

var (
	fset     = token.NewFileSet()
	exitCode = 0
)

var allowedRewrites = flag.String("r", "",
	"restrict the rewrites to this comma-separated list")

var allowed map[string]bool

var doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files")

func usage() {
	fmt.Fprintf(os.Stderr, "usage: gofix [-diff] [-r fixname,...] [path ...]\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\nAvailable rewrites are:\n")
	for _, f := range fixes {
		fmt.Fprintf(os.Stderr, "\n%s\n", f.name)
		desc := strings.TrimSpace(f.desc)
		desc = strings.Replace(desc, "\n", "\n\t", -1)
		fmt.Fprintf(os.Stderr, "\t%s\n", desc)
	}
	os.Exit(2)
}

func main() {
	sort.Sort(fixes)

	flag.Usage = usage
	flag.Parse()

	if *allowedRewrites != "" {
		allowed = make(map[string]bool)
		for _, f := range strings.Split(*allowedRewrites, ",", -1) {
			allowed[f] = true
		}
	}

	if flag.NArg() == 0 {
		if err := processFile("standard input", true); err != nil {
			report(err)
		}
		os.Exit(exitCode)
	}

	for i := 0; i < flag.NArg(); i++ {
		path := flag.Arg(i)
		switch dir, err := os.Stat(path); {
		case err != nil:
			report(err)
		case dir.IsRegular():
			if err := processFile(path, false); err != nil {
				report(err)
			}
		case dir.IsDirectory():
			walkDir(path)
		}
	}

	os.Exit(exitCode)
}

const (
	tabWidth    = 8
	parserMode  = parser.ParseComments
	printerMode = printer.TabIndent | printer.UseSpaces
)

var printConfig = &printer.Config{
	printerMode,
	tabWidth,
}

func processFile(filename string, useStdin bool) os.Error {
	var f *os.File
	var err os.Error
	var fixlog bytes.Buffer
	var buf bytes.Buffer

	if useStdin {
		f = os.Stdin
	} else {
		f, err = os.Open(filename)
		if err != nil {
			return err
		}
		defer f.Close()
	}

	src, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}

	file, err := parser.ParseFile(fset, filename, src, parserMode)
	if err != nil {
		return err
	}

	// Apply all fixes to file.
	newFile := file
	fixed := false
	for _, fix := range fixes {
		if allowed != nil && !allowed[fix.desc] {
			continue
		}
		if fix.f(newFile) {
			fixed = true
			fmt.Fprintf(&fixlog, " %s", fix.name)

			// AST changed.
			// Print and parse, to update any missing scoping
			// or position information for subsequent fixers.
			buf.Reset()
			_, err = printConfig.Fprint(&buf, fset, newFile)
			if err != nil {
				return err
			}
			newSrc := buf.Bytes()
			newFile, err = parser.ParseFile(fset, filename, newSrc, parserMode)
			if err != nil {
				return err
			}
		}
	}
	if !fixed {
		return nil
	}
	fmt.Fprintf(os.Stderr, "%s: fixed %s\n", filename, fixlog.String()[1:])

	// Print AST.  We did that after each fix, so this appears
	// redundant, but it is necessary to generate gofmt-compatible
	// source code in a few cases.  The official gofmt style is the
	// output of the printer run on a standard AST generated by the parser,
	// but the source we generated inside the loop above is the
	// output of the printer run on a mangled AST generated by a fixer.
	buf.Reset()
	_, err = printConfig.Fprint(&buf, fset, newFile)
	if err != nil {
		return err
	}
	newSrc := buf.Bytes()

	if *doDiff {
		data, err := diff(src, newSrc)
		if err != nil {
			return fmt.Errorf("computing diff: %s", err)
		}
		fmt.Printf("diff %s fixed/%s\n", filename, filename)
		os.Stdout.Write(data)
		return nil
	}

	if useStdin {
		os.Stdout.Write(newSrc)
		return nil
	}

	return ioutil.WriteFile(f.Name(), newSrc, 0)
}

var gofmtBuf bytes.Buffer

func gofmt(n interface{}) string {
	gofmtBuf.Reset()
	_, err := printConfig.Fprint(&gofmtBuf, fset, n)
	if err != nil {
		return "<" + err.String() + ">"
	}
	return gofmtBuf.String()
}

func report(err os.Error) {
	scanner.PrintError(os.Stderr, err)
	exitCode = 2
}

func walkDir(path string) {
	v := make(fileVisitor)
	go func() {
		filepath.Walk(path, v, v)
		close(v)
	}()
	for err := range v {
		if err != nil {
			report(err)
		}
	}
}

type fileVisitor chan os.Error

func (v fileVisitor) VisitDir(path string, f *os.FileInfo) bool {
	return true
}

func (v fileVisitor) VisitFile(path string, f *os.FileInfo) {
	if isGoFile(f) {
		v <- nil // synchronize error handler
		if err := processFile(path, false); err != nil {
			v <- err
		}
	}
}

func isGoFile(f *os.FileInfo) bool {
	// ignore non-Go files
	return f.IsRegular() && !strings.HasPrefix(f.Name, ".") && strings.HasSuffix(f.Name, ".go")
}

func diff(b1, b2 []byte) (data []byte, err os.Error) {
	f1, err := ioutil.TempFile("", "gofix")
	if err != nil {
		return nil, err
	}
	defer os.Remove(f1.Name())
	defer f1.Close()

	f2, err := ioutil.TempFile("", "gofix")
	if err != nil {
		return nil, err
	}
	defer os.Remove(f2.Name())
	defer f2.Close()

	f1.Write(b1)
	f2.Write(b2)

	return exec.Command("diff", f1.Name(), f2.Name()).CombinedOutput()
}
<commit_msg>gofix: fix diff regression from exec change<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"exec"
	"flag"
	"fmt"
	"go/parser"
	"go/printer"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

var (
	fset     = token.NewFileSet()
	exitCode = 0
)

var allowedRewrites = flag.String("r", "",
	"restrict the rewrites to this comma-separated list")

var allowed map[string]bool

var doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files")

func usage() {
	fmt.Fprintf(os.Stderr, "usage: gofix [-diff] [-r fixname,...] [path ...]\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\nAvailable rewrites are:\n")
	for _, f := range fixes {
		fmt.Fprintf(os.Stderr, "\n%s\n", f.name)
		desc := strings.TrimSpace(f.desc)
		desc = strings.Replace(desc, "\n", "\n\t", -1)
		fmt.Fprintf(os.Stderr, "\t%s\n", desc)
	}
	os.Exit(2)
}

func main() {
	sort.Sort(fixes)

	flag.Usage = usage
	flag.Parse()

	if *allowedRewrites != "" {
		allowed = make(map[string]bool)
		for _, f := range strings.Split(*allowedRewrites, ",", -1) {
			allowed[f] = true
		}
	}

	if flag.NArg() == 0 {
		if err := processFile("standard input", true); err != nil {
			report(err)
		}
		os.Exit(exitCode)
	}

	for i := 0; i < flag.NArg(); i++ {
		path := flag.Arg(i)
		switch dir, err := os.Stat(path); {
		case err != nil:
			report(err)
		case dir.IsRegular():
			if err := processFile(path, false); err != nil {
				report(err)
			}
		case dir.IsDirectory():
			walkDir(path)
		}
	}

	os.Exit(exitCode)
}

const (
	tabWidth    = 8
	parserMode  = parser.ParseComments
	printerMode = printer.TabIndent | printer.UseSpaces
)

var printConfig = &printer.Config{
	printerMode,
	tabWidth,
}

func processFile(filename string, useStdin bool) os.Error {
	var f *os.File
	var err os.Error
	var fixlog bytes.Buffer
	var buf bytes.Buffer

	if useStdin {
		f = os.Stdin
	} else {
		f, err = os.Open(filename)
		if err != nil {
			return err
		}
		defer f.Close()
	}

	src, err := ioutil.ReadAll(f)
	if err != nil {
		return err
	}

	file, err := parser.ParseFile(fset, filename, src, parserMode)
	if err != nil {
		return err
	}

	// Apply all fixes to file.
	newFile := file
	fixed := false
	for _, fix := range fixes {
		if allowed != nil && !allowed[fix.desc] {
			continue
		}
		if fix.f(newFile) {
			fixed = true
			fmt.Fprintf(&fixlog, " %s", fix.name)

			// AST changed.
			// Print and parse, to update any missing scoping
			// or position information for subsequent fixers.
			buf.Reset()
			_, err = printConfig.Fprint(&buf, fset, newFile)
			if err != nil {
				return err
			}
			newSrc := buf.Bytes()
			newFile, err = parser.ParseFile(fset, filename, newSrc, parserMode)
			if err != nil {
				return err
			}
		}
	}
	if !fixed {
		return nil
	}
	fmt.Fprintf(os.Stderr, "%s: fixed %s\n", filename, fixlog.String()[1:])

	// Print AST.  We did that after each fix, so this appears
	// redundant, but it is necessary to generate gofmt-compatible
	// source code in a few cases.  The official gofmt style is the
	// output of the printer run on a standard AST generated by the parser,
	// but the source we generated inside the loop above is the
	// output of the printer run on a mangled AST generated by a fixer.
	buf.Reset()
	_, err = printConfig.Fprint(&buf, fset, newFile)
	if err != nil {
		return err
	}
	newSrc := buf.Bytes()

	if *doDiff {
		data, err := diff(src, newSrc)
		if err != nil {
			return fmt.Errorf("computing diff: %s", err)
		}
		fmt.Printf("diff %s fixed/%s\n", filename, filename)
		os.Stdout.Write(data)
		return nil
	}

	if useStdin {
		os.Stdout.Write(newSrc)
		return nil
	}

	return ioutil.WriteFile(f.Name(), newSrc, 0)
}

var gofmtBuf bytes.Buffer

func gofmt(n interface{}) string {
	gofmtBuf.Reset()
	_, err := printConfig.Fprint(&gofmtBuf, fset, n)
	if err != nil {
		return "<" + err.String() + ">"
	}
	return gofmtBuf.String()
}

func report(err os.Error) {
	scanner.PrintError(os.Stderr, err)
	exitCode = 2
}

func walkDir(path string) {
	v := make(fileVisitor)
	go func() {
		filepath.Walk(path, v, v)
		close(v)
	}()
	for err := range v {
		if err != nil {
			report(err)
		}
	}
}

type fileVisitor chan os.Error

func (v fileVisitor) VisitDir(path string, f *os.FileInfo) bool {
	return true
}

func (v fileVisitor) VisitFile(path string, f *os.FileInfo) {
	if isGoFile(f) {
		v <- nil // synchronize error handler
		if err := processFile(path, false); err != nil {
			v <- err
		}
	}
}

func isGoFile(f *os.FileInfo) bool {
	// ignore non-Go files
	return f.IsRegular() && !strings.HasPrefix(f.Name, ".") && strings.HasSuffix(f.Name, ".go")
}

func diff(b1, b2 []byte) (data []byte, err os.Error) {
	f1, err := ioutil.TempFile("", "gofix")
	if err != nil {
		return nil, err
	}
	defer os.Remove(f1.Name())
	defer f1.Close()

	f2, err := ioutil.TempFile("", "gofix")
	if err != nil {
		return nil, err
	}
	defer os.Remove(f2.Name())
	defer f2.Close()

	f1.Write(b1)
	f2.Write(b2)

	data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
	if len(data) > 0 {
		// diff exits with a non-zero status when the files don't match.
		// Ignore that failure as long as we get output.
		err = nil
	}
	return
}
<|endoftext|>


<commit_before>package goriak

import (
	"errors"
	"reflect"
	"strconv"
	"strings"
	"time"

	riak "github.com/basho/riak-go-client"
)

func TsQuery(query string, session *Session) error {
	cmd, err := riak.NewTsQueryCommandBuilder().WithQuery(query).Build()
	if err != nil {
		return err
	}

	err = session.riak.Execute(cmd)
	if err != nil {
		return err
	}

	if !cmd.Success() {
		return errors.New("TsQuery failed")
	}

	return nil
}

func TsWrite(table string, object interface{}, session *Session) error {
	// Map TsCell ID to Riak struct Field
	cellIDs := make(map[int]int)

	var maxID int

	r := reflect.TypeOf(object)

	num := r.NumField()
	for i := 0; i < num; i++ {
		tag := r.Field(i).Tag.Get("goriakts")
		tagPiece := strings.Split(tag, ",")

		if len(tagPiece) != 2 {
			return errors.New("Unexpected goriakts tag")
		}

		tagNum, err := strconv.Atoi(tagPiece[0])
		if err != nil {
			return errors.New("Unexpected goriakts tag")
		}

		cellIDs[tagNum] = i

		// Keep track of the largest num found
		if tagNum > maxID {
			maxID = tagNum
		}
	}

	row := make([]riak.TsCell, maxID+1)

	rVal := reflect.ValueOf(object)

	for tsCellID, fieldID := range cellIDs {
		f := rVal.Field(fieldID)

		switch r.Field(fieldID).Type.Kind() {
		case reflect.String:
			row[tsCellID] = riak.NewStringTsCell(f.String())
		case reflect.Int64:
			row[tsCellID] = riak.NewSint64TsCell(f.Int())
		case reflect.Struct:
			if ts, ok := f.Interface().(time.Time); ok {
				row[tsCellID] = riak.NewTimestampTsCell(ts)
			} else {
				return errors.New("Unknown Type in TsWrite: " + r.Field(fieldID).Type.Kind().String())
			}
		default:
			return errors.New("Unknown Type in TsWrite: " + r.Field(fieldID).Type.Kind().String())
		}
	}

	cmd, err := riak.NewTsStoreRowsCommandBuilder().
		WithTable(table).
		WithRows([][]riak.TsCell{row}).
		Build()
	if err != nil {
		return err
	}

	err = session.riak.Execute(cmd)
	if err != nil {
		return err
	}

	if !cmd.Success() {
		return errors.New("TsWrite command execute failed")
	}

	return nil
}

func TsTimeFormat(in time.Time) int64 {
	return riak.ToUnixMillis(in)
}

func TsRead(query string, objects interface{}, session *Session) error {

	ptrValue := reflect.ValueOf(objects)
	ptrOuterType := reflect.TypeOf(objects)

	if ptrOuterType.Kind() != reflect.Ptr {
		return errors.New("objects is expected to be of ptr slice struct type (outer was not slice). Was: " + ptrOuterType.Kind().String())
	}

	sliceOuterType := ptrOuterType.Elem()
	sliceValue := ptrValue.Elem()
	if sliceOuterType.Kind() != reflect.Slice {
		return errors.New("objects is expected to be of ptr slice struct type (outer was not slice). Was: " + sliceOuterType.Kind().String())
	}

	innerType := ptrOuterType.Elem().Elem()
	if innerType.Kind() != reflect.Struct {
		return errors.New("objects is expected to be of slice struct type (slice type was not struct)")
	}

	// Map field names (from the goriakts tag) to their field position
	fieldNameToPos := make(map[string]int)
	numField := innerType.NumField()

	for i := 0; i < numField; i++ {
		tag := innerType.Field(i).Tag.Get("goriakts")
		tagPieces := strings.Split(tag, ",")

		if len(tagPieces) != 2 {
			return errors.New("Unexpected value of the goriakts tag on " + innerType.String() + ":" + innerType.Field(i).Name)
		}

		fieldNameToPos[tagPieces[1]] = i
	}

	cmd, err := riak.NewTsQueryCommandBuilder().WithQuery(query).Build()
	if err != nil {
		return err
	}

	err = session.riak.Execute(cmd)
	if err != nil {
		return err
	}

	res := cmd.(*riak.TsQueryCommand)

	if !res.Success() {
		return errors.New("Query was not successfully executed")
	}

	// Create a new slice
	outputSlice := reflect.MakeSlice(sliceOuterType, len(res.Response.Rows), len(res.Response.Rows))

	for rowID, row := range res.Response.Rows {

		// Create a new struct
		newOutObject := reflect.New(innerType).Elem()

		for colID, data := range row {
			colName := res.Response.Columns[colID].GetName()
			if pos, ok := fieldNameToPos[colName]; ok {
				switch data.GetDataType() {
				case "VARCHAR":
					newOutObject.Field(pos).SetString(data.GetStringValue())
				case "SINT64":
					newOutObject.Field(pos).SetInt(data.GetSint64Value())
				case "TIMESTAMP":
					newOutObject.Field(pos).Set(reflect.ValueOf(data.GetTimeValue()))
				default:
					return errors.New("Unknown type " + data.GetDataType() + " in result parsing")
				}
			} else {
				return errors.New("Could not map " + colName + " to output object")
			}
		}

		outputSlice.Index(rowID).Set(newOutObject)
	}

	// Replace the user subbmited slice with the one that we have created
	sliceValue.Set(outputSlice)

	return nil
}

func TsDel() {
	riak.NewTsDeleteRowCommandBuilder()
}
<commit_msg>Removed ts.go<commit_after><|endoftext|>