<commit_before>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/bmizerany/pq"
	"log"
	"strconv"
	"strings"
	"time"
)

func NewDbController(user, pass, database string) (c DbController, err error) {
	db, err := sql.Open("postgres", fmt.Sprintf("user=%s password=%s dbname=%s host=localhost sslmode=disable", user, pass, database))
	if err == nil {
		c = DbController{db}
	}
	return
}

type DbController struct {
	db *sql.DB
}

func (d *DbController) Close() {
	d.db.Close()
}

func (d *DbController) GetUser(uid int) (u User, err error) {
	row := d.db.QueryRow(
		`SELECT id, username, email
		   FROM auth_user
		   WHERE id = $1;`, uid)
	err = row.Scan(&u.Id, &u.username, &u.Email)
	return
}

func (d *DbController) GetUsers() (users []User, err error) {
	rows, err := d.db.Query(
		`SELECT id, username, email
		   FROM auth_user;`)
	if err != nil {
		return
	}
	defer rows.Close()

	for rows.Next() {
		var u User
		err = rows.Scan(&u.Id, &u.username, &u.Email)
		if err != nil {
			return
		}
		users = append(users, u)
	}
	return
}

func (d *DbController) GetUserRepos(user_id int) ([]GithubRepo, error) {
	// guess as to initial size. Likely very few users following < 10 repos.
	var repos = make([]GithubRepo, 10)

	// TODO(justinabrahms): Should really alter the schema such
	// that the join from user <-> repo doesn't go through
	// userprofiles.
	rows, err := d.db.Query(
		`SELECT r.id, username, project_name
	           FROM streamer_repo r
		   JOIN streamer_userprofile_repos upr ON upr.repo_id = r.id
		   JOIN streamer_userprofile up ON up.id = upr.userprofile_id
                   WHERE up.user_id = $1;`, user_id)
	// what's a good way to handle this not working?
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var username, project_name string
	var pk int
	for rows.Next() {
		err = rows.Scan(&pk, &username, &project_name)
		if err != nil {
			log.Print("Error fetching user's repos: ", user_id, err)
		}
		var repo = GithubRepo{pk, username, project_name}
		repos = append(repos, repo)
	}

	return repos, err
}

func (d *DbController) GetRepoActivity(repo *GithubRepo, userId int) (activity_list []Activity, err error) {
	activity_list = make([]Activity, 0)
	rows, err := d.db.Query(
		`SELECT a.id, a.event_id, a.type, a.created_at, ghu.name, r.username, r.project_name, meta
		  FROM streamer_activity a
		  JOIN streamer_repo r on r.id=a.repo_id
		  JOIN streamer_githubuser ghu on ghu.id=a.user_id
		  JOIN streamer_userprofile_repos upr on r.id=upr.repo_id
                  JOIN streamer_userprofile up on up.id=upr.userprofile_id
		  WHERE r.id = $1
                  AND up.user_id = $2
		  AND a.created_at > (NOW() - INTERVAL '5 days') -- don't send things more than a few days old. Think, new users who subscribe to rails/rails
		  AND (upr.last_sent is null -- hasn't been sent at all
		    OR a.created_at > upr.last_sent); --  or hasn't been sent since we've gotten new stuff`,
		repo.Id, userId)
	if err != nil {
		return
	}
	defer rows.Close()

	var (
		pk, github_id, repo_id                                 int
		activity_type, username, repo_project, repo_user, meta string
		created_at                                             time.Time
	)

	for rows.Next() {
		err = rows.Scan(&pk, &github_id, &activity_type, &created_at, &username, &repo_user, &repo_project, &meta)
		if err != nil {
			log.Print("Error getting activity for repo: ", repo, err)
		}

		activity_list = append(activity_list,
			Activity{pk, github_id, activity_type, created_at, username,
				GithubRepo{repo_id, repo_user, repo_project}, meta})
	}

	return
}

func (d *DbController) MarkUserRepoSent(user User, repos []GithubRepo) (err error) {
	// finds the streamer_userprofile_repo row for the repo / user
	// combo, mark its last_sent as now
	ids := make([]string, 0)
	for _, repo := range repos {
		// TODO: why are they 0?
		if repo.Id != 0 {
			ids = append(ids, strconv.FormatInt(int64(repo.Id), 10))
		}
	}

	// There is likely a better way to get parameterization, but
	// it wasn't working for me with ?'s.
	str := fmt.Sprintf(
		`UPDATE streamer_userprofile_repos
		   SET last_sent=NOW()
		   WHERE repo_id IN ($1)`, strings.Join(ids, ","))
	_, err = d.db.Exec(str)
	return
}
<commit_msg>Reverting "fixing string sub format stuff." Revert "fixing string sub format stuff."<commit_after>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/bmizerany/pq"
	"log"
	"strconv"
	"strings"
	"time"
)

func NewDbController(user, pass, database string) (c DbController, err error) {
	db, err := sql.Open("postgres", fmt.Sprintf("user=%s password=%s dbname=%s host=localhost sslmode=disable", user, pass, database))
	if err == nil {
		c = DbController{db}
	}
	return
}

type DbController struct {
	db *sql.DB
}

func (d *DbController) Close() {
	d.db.Close()
}

func (d *DbController) GetUser(uid int) (u User, err error) {
	row := d.db.QueryRow(
		`SELECT id, username, email
		   FROM auth_user
		   WHERE id = $1;`, uid)
	err = row.Scan(&u.Id, &u.username, &u.Email)
	return
}

func (d *DbController) GetUsers() (users []User, err error) {
	rows, err := d.db.Query(
		`SELECT id, username, email
		   FROM auth_user;`)
	if err != nil {
		return
	}
	defer rows.Close()

	for rows.Next() {
		var u User
		err = rows.Scan(&u.Id, &u.username, &u.Email)
		if err != nil {
			return
		}
		users = append(users, u)
	}
	return
}

func (d *DbController) GetUserRepos(user_id int) ([]GithubRepo, error) {
	// guess as to initial size. Likely very few users following < 10 repos.
	var repos = make([]GithubRepo, 10)

	// TODO(justinabrahms): Should really alter the schema such
	// that the join from user <-> repo doesn't go through
	// userprofiles.
	rows, err := d.db.Query(
		`SELECT r.id, username, project_name
	           FROM streamer_repo r
		   JOIN streamer_userprofile_repos upr ON upr.repo_id = r.id
		   JOIN streamer_userprofile up ON up.id = upr.userprofile_id
                   WHERE up.user_id = $1;`, user_id)
	// what's a good way to handle this not working?
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var username, project_name string
	var pk int
	for rows.Next() {
		err = rows.Scan(&pk, &username, &project_name)
		if err != nil {
			log.Print("Error fetching user's repos: ", user_id, err)
		}
		var repo = GithubRepo{pk, username, project_name}
		repos = append(repos, repo)
	}

	return repos, err
}

func (d *DbController) GetRepoActivity(repo *GithubRepo, userId int) (activity_list []Activity, err error) {
	activity_list = make([]Activity, 0)
	rows, err := d.db.Query(
		`SELECT a.id, a.event_id, a.type, a.created_at, ghu.name, r.username, r.project_name, meta
		  FROM streamer_activity a
		  JOIN streamer_repo r on r.id=a.repo_id
		  JOIN streamer_githubuser ghu on ghu.id=a.user_id
		  JOIN streamer_userprofile_repos upr on r.id=upr.repo_id
                  JOIN streamer_userprofile up on up.id=upr.userprofile_id
		  WHERE r.id = $1
                  AND up.user_id = $2
		  AND a.created_at > (NOW() - INTERVAL '5 days') -- don't send things more than a few days old. Think, new users who subscribe to rails/rails
		  AND (upr.last_sent is null -- hasn't been sent at all
		    OR a.created_at > upr.last_sent); --  or hasn't been sent since we've gotten new stuff`,
		repo.Id, userId)
	if err != nil {
		return
	}
	defer rows.Close()

	var (
		pk, github_id, repo_id                                 int
		activity_type, username, repo_project, repo_user, meta string
		created_at                                             time.Time
	)

	for rows.Next() {
		err = rows.Scan(&pk, &github_id, &activity_type, &created_at, &username, &repo_user, &repo_project, &meta)
		if err != nil {
			log.Print("Error getting activity for repo: ", repo, err)
		}

		activity_list = append(activity_list,
			Activity{pk, github_id, activity_type, created_at, username,
				GithubRepo{repo_id, repo_user, repo_project}, meta})
	}

	return
}

func (d *DbController) MarkUserRepoSent(user User, repos []GithubRepo) (err error) {
	// finds the streamer_userprofile_repo row for the repo / user
	// combo, mark its last_sent as now
	ids := make([]string, 0)
	for _, repo := range repos {
		// TODO: why are they 0?
		if repo.Id != 0 {
			ids = append(ids, strconv.FormatInt(int64(repo.Id), 10))
		}
	}

	// There is likely a better way to get parameterization, but
	// it wasn't working for me with ?'s.
	str := fmt.Sprintf(
		`UPDATE streamer_userprofile_repos
		   SET last_sent=NOW()
		   WHERE repo_id IN (%s)`, strings.Join(ids, ","))
	_, err = d.db.Exec(str)
	return
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package secp256k1fx

import (
	"encoding/json"
	"errors"

	"github.com/ava-labs/avalanchego/utils/constants"
	"github.com/ava-labs/avalanchego/utils/formatting"

	"github.com/ava-labs/avalanchego/snow"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/vms/components/verify"
)

var (
	errNilOutput                         = errors.New("nil output")
	errOutputUnspendable                 = errors.New("output is unspendable")
	errOutputUnoptimized                 = errors.New("output representation should be optimized")
	errAddrsNotSortedUnique              = errors.New("addresses not sorted and unique")
	errMarshal                           = errors.New("cannot marshal without ctx")
	_                       verify.State = &OutputOwners{}
)

// OutputOwners ...
type OutputOwners struct {
	Locktime  uint64        `serialize:"true" json:"locktime"`
	Threshold uint32        `serialize:"true" json:"threshold"`
	Addrs     []ids.ShortID `serialize:"true" json:"addresses"`
	// ctx is used in MarshalJSON to convert Addrs into human readable
	// format with ChainID and NetworkID. Unexported because we don't use
	// it outside this object.
	ctx *snow.Context `serialize:"false"`
}

// InitCtx assigns the OutputOwners.ctx object to given [ctx] object
// Must be called at least once for MarshalJSON to work successfully
func (out *OutputOwners) InitCtx(ctx *snow.Context) {
	out.ctx = ctx
}

// MarshalJSON marshals OutputOwners as JSON with human readable addresses.
// OutputOwners.InitCtx must be called before marshalling this or one of
// the parent objects to json. Uses the OutputOwners.ctx method to format
// the addresses. Returns errMarshal error if OutputOwners.ctx is not set.
func (out *OutputOwners) MarshalJSON() ([]byte, error) {
	addrsLen := len(out.Addrs)

	// we need out.ctx to do this, if its absent, throw error
	if addrsLen > 0 && out.ctx == nil {
		return nil, errMarshal
	}

	result := make(map[string]interface{})
	result["locktime"] = out.Locktime
	result["threshold"] = out.Threshold

	addresses := make([]string, addrsLen)
	for i, n := 0, addrsLen; i < n; i++ {
		// for each [addr] in [Addrs] we attempt to format it given
		// the [out.ctx] object
		addr := out.Addrs[i]
		fAddr, err := FormatAddress(out.ctx, addr)
		if err != nil {
			// we expect these addresses to be valid, return error
			// if they are not
			return nil, err
		}
		addresses[i] = fAddr
	}
	result["addresses"] = addresses

	return json.Marshal(result)
}

// Addresses returns the addresses that manage this output
func (out *OutputOwners) Addresses() [][]byte {
	addrs := make([][]byte, len(out.Addrs))
	for i, addr := range out.Addrs {
		addrs[i] = addr.Bytes()
	}
	return addrs
}

// AddressesSet returns addresses as a set
func (out *OutputOwners) AddressesSet() ids.ShortSet {
	set := ids.NewShortSet(len(out.Addrs))
	set.Add(out.Addrs...)
	return set
}

// Equals returns true if the provided owners create the same condition
func (out *OutputOwners) Equals(other *OutputOwners) bool {
	if out == other {
		return true
	}
	if out == nil || other == nil || out.Locktime != other.Locktime || out.Threshold != other.Threshold || len(out.Addrs) != len(other.Addrs) {
		return false
	}
	for i, addr := range out.Addrs {
		otherAddr := other.Addrs[i]
		if addr != otherAddr {
			return false
		}
	}
	return true
}

// Verify ...
func (out *OutputOwners) Verify() error {
	switch {
	case out == nil:
		return errNilOutput
	case out.Threshold > uint32(len(out.Addrs)):
		return errOutputUnspendable
	case out.Threshold == 0 && len(out.Addrs) > 0:
		return errOutputUnoptimized
	case !ids.IsSortedAndUniqueShortIDs(out.Addrs):
		return errAddrsNotSortedUnique
	default:
		return nil
	}
}

// VerifyState ...
func (out *OutputOwners) VerifyState() error { return out.Verify() }

// Sort ...
func (out *OutputOwners) Sort() { ids.SortShortIDs(out.Addrs) }

// FormatAddress formats a given [addr] into human readable format using
// [ChainID] and [NetworkID] from the provided [ctx].
func FormatAddress(ctx *snow.Context, addr ids.ShortID) (string, error) {
	chainIDAlias, err := ctx.BCLookup.PrimaryAlias(ctx.ChainID)
	if err != nil {
		return "", err
	}

	hrp := constants.GetHRP(ctx.NetworkID)
	return formatting.FormatAddress(chainIDAlias, hrp, addr.Bytes())
}
<commit_msg>directly init map<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package secp256k1fx

import (
	"encoding/json"
	"errors"

	"github.com/ava-labs/avalanchego/utils/constants"
	"github.com/ava-labs/avalanchego/utils/formatting"

	"github.com/ava-labs/avalanchego/snow"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/vms/components/verify"
)

var (
	errNilOutput                         = errors.New("nil output")
	errOutputUnspendable                 = errors.New("output is unspendable")
	errOutputUnoptimized                 = errors.New("output representation should be optimized")
	errAddrsNotSortedUnique              = errors.New("addresses not sorted and unique")
	errMarshal                           = errors.New("cannot marshal without ctx")
	_                       verify.State = &OutputOwners{}
)

// OutputOwners ...
type OutputOwners struct {
	Locktime  uint64        `serialize:"true" json:"locktime"`
	Threshold uint32        `serialize:"true" json:"threshold"`
	Addrs     []ids.ShortID `serialize:"true" json:"addresses"`
	// ctx is used in MarshalJSON to convert Addrs into human readable
	// format with ChainID and NetworkID. Unexported because we don't use
	// it outside this object.
	ctx *snow.Context `serialize:"false"`
}

// InitCtx assigns the OutputOwners.ctx object to given [ctx] object
// Must be called at least once for MarshalJSON to work successfully
func (out *OutputOwners) InitCtx(ctx *snow.Context) {
	out.ctx = ctx
}

// MarshalJSON marshals OutputOwners as JSON with human readable addresses.
// OutputOwners.InitCtx must be called before marshalling this or one of
// the parent objects to json. Uses the OutputOwners.ctx method to format
// the addresses. Returns errMarshal error if OutputOwners.ctx is not set.
func (out *OutputOwners) MarshalJSON() ([]byte, error) {
	addrsLen := len(out.Addrs)

	// we need out.ctx to do this, if its absent, throw error
	if addrsLen > 0 && out.ctx == nil {
		return nil, errMarshal
	}

	addresses := make([]string, addrsLen)
	for i, n := 0, addrsLen; i < n; i++ {
		// for each [addr] in [Addrs] we attempt to format it given
		// the [out.ctx] object
		addr := out.Addrs[i]
		fAddr, err := FormatAddress(out.ctx, addr)
		if err != nil {
			// we expect these addresses to be valid, return error
			// if they are not
			return nil, err
		}
		addresses[i] = fAddr
	}
	result := map[string]interface{}{
		"locktime":  out.Locktime,
		"threshold": out.Threshold,
		"addresses": addresses,
	}

	return json.Marshal(result)
}

// Addresses returns the addresses that manage this output
func (out *OutputOwners) Addresses() [][]byte {
	addrs := make([][]byte, len(out.Addrs))
	for i, addr := range out.Addrs {
		addrs[i] = addr.Bytes()
	}
	return addrs
}

// AddressesSet returns addresses as a set
func (out *OutputOwners) AddressesSet() ids.ShortSet {
	set := ids.NewShortSet(len(out.Addrs))
	set.Add(out.Addrs...)
	return set
}

// Equals returns true if the provided owners create the same condition
func (out *OutputOwners) Equals(other *OutputOwners) bool {
	if out == other {
		return true
	}
	if out == nil || other == nil || out.Locktime != other.Locktime || out.Threshold != other.Threshold || len(out.Addrs) != len(other.Addrs) {
		return false
	}
	for i, addr := range out.Addrs {
		otherAddr := other.Addrs[i]
		if addr != otherAddr {
			return false
		}
	}
	return true
}

// Verify ...
func (out *OutputOwners) Verify() error {
	switch {
	case out == nil:
		return errNilOutput
	case out.Threshold > uint32(len(out.Addrs)):
		return errOutputUnspendable
	case out.Threshold == 0 && len(out.Addrs) > 0:
		return errOutputUnoptimized
	case !ids.IsSortedAndUniqueShortIDs(out.Addrs):
		return errAddrsNotSortedUnique
	default:
		return nil
	}
}

// VerifyState ...
func (out *OutputOwners) VerifyState() error { return out.Verify() }

// Sort ...
func (out *OutputOwners) Sort() { ids.SortShortIDs(out.Addrs) }

// FormatAddress formats a given [addr] into human readable format using
// [ChainID] and [NetworkID] from the provided [ctx].
func FormatAddress(ctx *snow.Context, addr ids.ShortID) (string, error) {
	chainIDAlias, err := ctx.BCLookup.PrimaryAlias(ctx.ChainID)
	if err != nil {
		return "", err
	}

	hrp := constants.GetHRP(ctx.NetworkID)
	return formatting.FormatAddress(chainIDAlias, hrp, addr.Bytes())
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	flags "github.com/jessevdk/go-flags"
	"github.com/mit-dci/lit/coinparam"
	"github.com/mit-dci/lit/litbamf"
	"github.com/mit-dci/lit/litrpc"
	"github.com/mit-dci/lit/lnutil"
	"github.com/mit-dci/lit/qln"
)

type config struct { // define a struct for usage with go-flags
	Tn3host     string `long:"tn3" description:"Connect to bitcoin testnet3."`
	Bc2host     string `long:"bc2" description:"bc2 full node."`
	Lt4host     string `long:"lt4" description:"Connect to litecoin testnet4."`
	Reghost     string `long:"reg" description:"Connect to bitcoin regtest."`
	Litereghost string `long:"litereg" description:"Connect to litecoin regtest."`
	Tvtchost    string `long:"tvtc" description:"Connect to Vertcoin test node."`
	Vtchost     string `long:"vtc" description:"Connect to Vertcoin."`
	LitHomeDir  string `long:"dir" description:"Specify Home Directory of lit as an absolute path."`
	ConfigFile  string

	ReSync  bool `short:"r"long:"reSync" description:"Resync from the given tip."`
	Tower   bool `long:"tower" description:"Watchtower: Run a watching node"`
	Hard    bool `short:"t" long:"hard" description:"Flag to set networks."`
	Verbose bool `short:"v" long:"verbose" description:"Set verbosity to true."`

	Rpcport uint16 `short:"p"long:"rpcport" description:"Set rpcport to connect to."`

	Params *coinparam.Params
}

var (
	defaultLitHomeDirName = os.Getenv("HOME") + "/.lit"
	defaultKeyFileName    = "privkey.hex"
	defaultConfigFilename = "lit.conf"
	defaultHomeDir        = os.Getenv("HOME")
	defaultConfigFile     = filepath.Join(os.Getenv("HOME"), "/.lit/lit.conf")
	defaultRpcport        = uint16(8001)
)

func fileExists(name string) bool {
	if _, err := os.Stat(name); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

// newConfigParser returns a new command line flags parser.
func newConfigParser(conf *config, options flags.Options) *flags.Parser {
	parser := flags.NewParser(conf, options)
	return parser
}

func linkWallets(node *qln.LitNode, key *[32]byte, conf *config) error {
	// for now, wallets are linked to the litnode on startup, and
	// can't appear / disappear while it's running.  Later
	// could support dynamically adding / removing wallets

	// order matters; the first registered wallet becomes the default

	var err error
	// try regtest
	if conf.Reghost != "" {
		p := &coinparam.RegressionNetParams
		if !strings.Contains(conf.Reghost, ":") {
			conf.Reghost = conf.Reghost + ":" + p.DefaultPort
		}
		fmt.Printf("reg: %s\n", conf.Reghost)
		err = node.LinkBaseWallet(key, 120, conf.ReSync, conf.Tower, conf.Reghost, p)
		if err != nil {
			return err
		}
	}
	// try testnet3
	if conf.Tn3host != "" {
		p := &coinparam.TestNet3Params
		if !strings.Contains(conf.Tn3host, ":") {
			conf.Tn3host = conf.Tn3host + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, 1150000, conf.ReSync, conf.Tower,
			conf.Tn3host, p)
		if err != nil {
			return err
		}
	}
	// try litecoin regtest
	if conf.Litereghost != "" {
		p := &coinparam.LiteRegNetParams
		if !strings.Contains(conf.Litereghost, ":") {
			conf.Litereghost = conf.Litereghost + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(key, 120, conf.ReSync, conf.Tower, conf.Litereghost, p)
		if err != nil {
			return err
		}
	}

	// try litecoin testnet4
	if conf.Lt4host != "" {
		p := &coinparam.LiteCoinTestNet4Params
		if !strings.Contains(conf.Lt4host, ":") {
			conf.Lt4host = conf.Lt4host + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, p.StartHeight, conf.ReSync, conf.Tower,
			conf.Lt4host, p)
		if err != nil {
			return err
		}
	}
	// try vertcoin testnet
	if conf.Tvtchost != "" {
		p := &coinparam.VertcoinTestNetParams
		if !strings.Contains(conf.Tvtchost, ":") {
			conf.Tvtchost = conf.Tvtchost + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, 0, conf.ReSync, conf.Tower,
			conf.Tvtchost, p)
		if err != nil {
			return err
		}
	}
	// try vertcoin mainnet
	if conf.Vtchost != "" {
		p := &coinparam.VertcoinParams
		if !strings.Contains(conf.Vtchost, ":") {
			conf.Vtchost = conf.Vtchost + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, p.StartHeight, conf.ReSync, conf.Tower,
			conf.Vtchost, p)
		if err != nil {
			return err
		}

	}
	return nil
}

func main() {

	conf := config{
		LitHomeDir: defaultLitHomeDirName,
		ConfigFile: defaultConfigFile,
		Rpcport:    defaultRpcport,
	}

	// Pre-parse the command line options to see if an alternative config
	// file or the version flag was specified.  Any errors aside from the
	// help message error can be ignored here since they will be caught by
	// the final parse below.
	preconf := conf
	preParser := newConfigParser(&preconf, flags.HelpFlag)
	_, err := preParser.Parse()
	if err != nil { // if there is some sort of error while parsing the CLI arguments
		if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
			fmt.Fprintln(os.Stderr, err)
			log.Fatal(err)
			return
			// return nil, nil, err
		}
	}

	// appName := filepath.Base(os.Args[0])
	// appName = strings.TrimSuffix(appName, filepath.Ext(appName))
	// usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
	// if preconf.ShowVersion {
	// 	fmt.Println(appName, "version", version())
	// 	os.Exit(0)
	// }

	// Load additional config from file
	var configFileError error
	parser := newConfigParser(&conf, flags.Default) // Single line command to read all the CLI params passed

	// creates a directory in the absolute sense
	if _, err := os.Stat(preconf.LitHomeDir); os.IsNotExist(err) {
		os.Mkdir(preconf.LitHomeDir, 0700)
		fmt.Println("Creating a new config file")
		err1 := createDefaultConfigFile(preconf.LitHomeDir) // Source of error
		if err1 != nil {
			fmt.Fprintf(os.Stderr, "Error creating a "+
				"default config file: %v\n", err)
		}
	}

	if err != nil {
		fmt.Println("Error while creating a directory")
		fmt.Println(err)
	}

	if !(preconf.ConfigFile != defaultConfigFile) {
		// passing works fine.
		// fmt.Println("Watch out")
		// fmt.Println(filepath.Join(preconf.LitHomeDir))
		if _, err := os.Stat(filepath.Join(filepath.Join(preconf.LitHomeDir), "lit.conf")); os.IsNotExist(err) {
			if err != nil {
				fmt.Println(err)
			}
			fmt.Println("Creating a new config file")
			err1 := createDefaultConfigFile(filepath.Join(preconf.LitHomeDir)) // Source of error
			if err1 != nil {
				fmt.Fprintf(os.Stderr, "Error creating a "+
					"default config file: %v\n", err)
			}
		}
		preconf.ConfigFile = filepath.Join(filepath.Join(preconf.LitHomeDir), "lit.conf")
		err := flags.NewIniParser(parser).ParseFile(preconf.ConfigFile) // lets parse the config file provided, if any
		if err != nil {
			if _, ok := err.(*os.PathError); !ok {
				fmt.Fprintf(os.Stderr, "Error parsing config "+
					"file: %v\n", err)
				// fmt.Fprintln(os.Stderr, usageMessage)
				log.Fatal(err)
				// return nil, nil, err
			}
			configFileError = err
		}
	}

	// Parse command line options again to ensure they take precedence.
	remainingArgs, err := parser.Parse() // no extra work, free overloading.
	if err != nil {
		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
			// fmt.Fprintln(os.Stderr, usageMessage)
		}
		log.Fatal(err)
		// return nil, nil, err
	}

	if configFileError != nil {
		fmt.Printf("%v", configFileError)
	}

	if remainingArgs != nil {
		//fmt.Printf("%v", remainingArgs)
	}

	logFilePath := filepath.Join(conf.LitHomeDir, "lit.log")

	logfile, err := os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	defer logfile.Close()

	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	if conf.Verbose {
		logOutput := io.MultiWriter(os.Stdout, logfile)
		log.SetOutput(logOutput)
	} else {
		log.SetOutput(logfile)
	}

	// Allow node with no linked wallets, for testing.
	// TODO Should update tests and disallow nodes without wallets later.
	//	if conf.Tn3host == "" && conf.Lt4host == "" && conf.Reghost == "" {
	//		log.Fatal("error: no network specified; use -tn3, -reg, -lt4")
	//	}

	// Keys: the litNode, and wallits, all get 32 byte keys.
	// Right now though, they all get the *same* key.  For lit as a single binary
	// now, all using the same key makes sense; could split up later.

	keyFilePath := filepath.Join(conf.LitHomeDir, defaultKeyFileName)

	// read key file (generate if not found)
	key, err := lnutil.ReadKeyFile(keyFilePath)
	if err != nil {
		log.Fatal(err)
	}

	// Setup LN node.  Activate Tower if in hard mode.
	// give node and below file pathof lit home directoy
	node, err := qln.NewLitNode(key, conf.LitHomeDir)
	if err != nil {
		log.Fatal(err)
	}

	// node is up; link wallets based on args
	err = linkWallets(node, key, &conf)
	if err != nil {
		log.Fatal(err)
	}

	rpcl := new(litrpc.LitRPC)
	rpcl.Node = node
	rpcl.OffButton = make(chan bool, 1)

	litrpc.RPCListen(rpcl, conf.Rpcport)
	litbamf.BamfListen(conf.Rpcport, conf.LitHomeDir)

	<-rpcl.OffButton
	fmt.Printf("Got stop request\n")
	time.Sleep(time.Second)

	return
	// New directory being created over at PWD
	// conf file being created at /
}

func createDefaultConfigFile(destinationPath string) error {

	// We assume sample config file path is same as binary TODO: change to ~/.lit/config/
	path, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		return err
	}
	sampleConfigPath := filepath.Join(path, defaultConfigFilename)

	// We generate a random user and password
	randomBytes := make([]byte, 20)
	_, err = rand.Read(randomBytes)
	if err != nil {
		return err
	}
	generatedRPCUser := base64.StdEncoding.EncodeToString(randomBytes)

	_, err = rand.Read(randomBytes)
	if err != nil {
		return err
	}
	generatedRPCPass := base64.StdEncoding.EncodeToString(randomBytes)

	src, err := os.Open(sampleConfigPath)
	if err != nil {
		return err
	}
	defer src.Close()

	dest, err := os.OpenFile(filepath.Join(destinationPath, defaultConfigFilename),
		os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer dest.Close()

	// We copy every line from the sample config file to the destination,
	// only replacing the two lines for rpcuser and rpcpass
	reader := bufio.NewReader(src)
	for err != io.EOF {
		var line string
		line, err = reader.ReadString('\n')
		if err != nil && err != io.EOF {
			return err
		}

		if strings.Contains(line, "rpcuser=") {
			line = "rpcuser=" + generatedRPCUser + "\n"
		} else if strings.Contains(line, "rpcpass=") {
			line = "rpcpass=" + generatedRPCPass + "\n"
		}

		if _, err := dest.WriteString(line); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>bump height for testnet3<commit_after>package main

import (
	"bufio"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	flags "github.com/jessevdk/go-flags"
	"github.com/mit-dci/lit/coinparam"
	"github.com/mit-dci/lit/litbamf"
	"github.com/mit-dci/lit/litrpc"
	"github.com/mit-dci/lit/lnutil"
	"github.com/mit-dci/lit/qln"
)

type config struct { // define a struct for usage with go-flags
	Tn3host     string `long:"tn3" description:"Connect to bitcoin testnet3."`
	Bc2host     string `long:"bc2" description:"bc2 full node."`
	Lt4host     string `long:"lt4" description:"Connect to litecoin testnet4."`
	Reghost     string `long:"reg" description:"Connect to bitcoin regtest."`
	Litereghost string `long:"litereg" description:"Connect to litecoin regtest."`
	Tvtchost    string `long:"tvtc" description:"Connect to Vertcoin test node."`
	Vtchost     string `long:"vtc" description:"Connect to Vertcoin."`
	LitHomeDir  string `long:"dir" description:"Specify Home Directory of lit as an absolute path."`
	ConfigFile  string

	ReSync  bool `short:"r"long:"reSync" description:"Resync from the given tip."`
	Tower   bool `long:"tower" description:"Watchtower: Run a watching node"`
	Hard    bool `short:"t" long:"hard" description:"Flag to set networks."`
	Verbose bool `short:"v" long:"verbose" description:"Set verbosity to true."`

	Rpcport uint16 `short:"p"long:"rpcport" description:"Set rpcport to connect to."`

	Params *coinparam.Params
}

var (
	defaultLitHomeDirName = os.Getenv("HOME") + "/.lit"
	defaultKeyFileName    = "privkey.hex"
	defaultConfigFilename = "lit.conf"
	defaultHomeDir        = os.Getenv("HOME")
	defaultConfigFile     = filepath.Join(os.Getenv("HOME"), "/.lit/lit.conf")
	defaultRpcport        = uint16(8001)
)

func fileExists(name string) bool {
	if _, err := os.Stat(name); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

// newConfigParser returns a new command line flags parser.
func newConfigParser(conf *config, options flags.Options) *flags.Parser {
	parser := flags.NewParser(conf, options)
	return parser
}

func linkWallets(node *qln.LitNode, key *[32]byte, conf *config) error {
	// for now, wallets are linked to the litnode on startup, and
	// can't appear / disappear while it's running.  Later
	// could support dynamically adding / removing wallets

	// order matters; the first registered wallet becomes the default

	var err error
	// try regtest
	if conf.Reghost != "" {
		p := &coinparam.RegressionNetParams
		if !strings.Contains(conf.Reghost, ":") {
			conf.Reghost = conf.Reghost + ":" + p.DefaultPort
		}
		fmt.Printf("reg: %s\n", conf.Reghost)
		err = node.LinkBaseWallet(key, 120, conf.ReSync, conf.Tower, conf.Reghost, p)
		if err != nil {
			return err
		}
	}
	// try testnet3
	if conf.Tn3host != "" {
		p := &coinparam.TestNet3Params
		if !strings.Contains(conf.Tn3host, ":") {
			conf.Tn3host = conf.Tn3host + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, 1210000, conf.ReSync, conf.Tower,
			conf.Tn3host, p)
		if err != nil {
			return err
		}
	}
	// try litecoin regtest
	if conf.Litereghost != "" {
		p := &coinparam.LiteRegNetParams
		if !strings.Contains(conf.Litereghost, ":") {
			conf.Litereghost = conf.Litereghost + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(key, 120, conf.ReSync, conf.Tower, conf.Litereghost, p)
		if err != nil {
			return err
		}
	}

	// try litecoin testnet4
	if conf.Lt4host != "" {
		p := &coinparam.LiteCoinTestNet4Params
		if !strings.Contains(conf.Lt4host, ":") {
			conf.Lt4host = conf.Lt4host + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, p.StartHeight, conf.ReSync, conf.Tower,
			conf.Lt4host, p)
		if err != nil {
			return err
		}
	}
	// try vertcoin testnet
	if conf.Tvtchost != "" {
		p := &coinparam.VertcoinTestNetParams
		if !strings.Contains(conf.Tvtchost, ":") {
			conf.Tvtchost = conf.Tvtchost + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, 0, conf.ReSync, conf.Tower,
			conf.Tvtchost, p)
		if err != nil {
			return err
		}
	}
	// try vertcoin mainnet
	if conf.Vtchost != "" {
		p := &coinparam.VertcoinParams
		if !strings.Contains(conf.Vtchost, ":") {
			conf.Vtchost = conf.Vtchost + ":" + p.DefaultPort
		}
		err = node.LinkBaseWallet(
			key, p.StartHeight, conf.ReSync, conf.Tower,
			conf.Vtchost, p)
		if err != nil {
			return err
		}

	}
	return nil
}

func main() {

	conf := config{
		LitHomeDir: defaultLitHomeDirName,
		ConfigFile: defaultConfigFile,
		Rpcport:    defaultRpcport,
	}

	// Pre-parse the command line options to see if an alternative config
	// file or the version flag was specified.  Any errors aside from the
	// help message error can be ignored here since they will be caught by
	// the final parse below.
	preconf := conf
	preParser := newConfigParser(&preconf, flags.HelpFlag)
	_, err := preParser.Parse()
	if err != nil { // if there is some sort of error while parsing the CLI arguments
		if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
			fmt.Fprintln(os.Stderr, err)
			log.Fatal(err)
			return
			// return nil, nil, err
		}
	}

	// appName := filepath.Base(os.Args[0])
	// appName = strings.TrimSuffix(appName, filepath.Ext(appName))
	// usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
	// if preconf.ShowVersion {
	// 	fmt.Println(appName, "version", version())
	// 	os.Exit(0)
	// }

	// Load additional config from file
	var configFileError error
	parser := newConfigParser(&conf, flags.Default) // Single line command to read all the CLI params passed

	// creates a directory in the absolute sense
	if _, err := os.Stat(preconf.LitHomeDir); os.IsNotExist(err) {
		os.Mkdir(preconf.LitHomeDir, 0700)
		fmt.Println("Creating a new config file")
		err1 := createDefaultConfigFile(preconf.LitHomeDir) // Source of error
		if err1 != nil {
			fmt.Fprintf(os.Stderr, "Error creating a "+
				"default config file: %v\n", err)
		}
	}

	if err != nil {
		fmt.Println("Error while creating a directory")
		fmt.Println(err)
	}

	if !(preconf.ConfigFile != defaultConfigFile) {
		// passing works fine.
		// fmt.Println("Watch out")
		// fmt.Println(filepath.Join(preconf.LitHomeDir))
		if _, err := os.Stat(filepath.Join(filepath.Join(preconf.LitHomeDir), "lit.conf")); os.IsNotExist(err) {
			if err != nil {
				fmt.Println(err)
			}
			fmt.Println("Creating a new config file")
			err1 := createDefaultConfigFile(filepath.Join(preconf.LitHomeDir)) // Source of error
			if err1 != nil {
				fmt.Fprintf(os.Stderr, "Error creating a "+
					"default config file: %v\n", err)
			}
		}
		preconf.ConfigFile = filepath.Join(filepath.Join(preconf.LitHomeDir), "lit.conf")
		err := flags.NewIniParser(parser).ParseFile(preconf.ConfigFile) // lets parse the config file provided, if any
		if err != nil {
			if _, ok := err.(*os.PathError); !ok {
				fmt.Fprintf(os.Stderr, "Error parsing config "+
					"file: %v\n", err)
				// fmt.Fprintln(os.Stderr, usageMessage)
				log.Fatal(err)
				// return nil, nil, err
			}
			configFileError = err
		}
	}

	// Parse command line options again to ensure they take precedence.
	remainingArgs, err := parser.Parse() // no extra work, free overloading.
	if err != nil {
		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
			// fmt.Fprintln(os.Stderr, usageMessage)
		}
		log.Fatal(err)
		// return nil, nil, err
	}

	if configFileError != nil {
		fmt.Printf("%v", configFileError)
	}

	if remainingArgs != nil {
		//fmt.Printf("%v", remainingArgs)
	}

	logFilePath := filepath.Join(conf.LitHomeDir, "lit.log")

	logfile, err := os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	defer logfile.Close()

	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	if conf.Verbose {
		logOutput := io.MultiWriter(os.Stdout, logfile)
		log.SetOutput(logOutput)
	} else {
		log.SetOutput(logfile)
	}

	// Allow node with no linked wallets, for testing.
	// TODO Should update tests and disallow nodes without wallets later.
	//	if conf.Tn3host == "" && conf.Lt4host == "" && conf.Reghost == "" {
	//		log.Fatal("error: no network specified; use -tn3, -reg, -lt4")
	//	}

	// Keys: the litNode, and wallits, all get 32 byte keys.
	// Right now though, they all get the *same* key.  For lit as a single binary
	// now, all using the same key makes sense; could split up later.

	keyFilePath := filepath.Join(conf.LitHomeDir, defaultKeyFileName)

	// read key file (generate if not found)
	key, err := lnutil.ReadKeyFile(keyFilePath)
	if err != nil {
		log.Fatal(err)
	}

	// Setup LN node.  Activate Tower if in hard mode.
	// give node and below file pathof lit home directoy
	node, err := qln.NewLitNode(key, conf.LitHomeDir)
	if err != nil {
		log.Fatal(err)
	}

	// node is up; link wallets based on args
	err = linkWallets(node, key, &conf)
	if err != nil {
		log.Fatal(err)
	}

	rpcl := new(litrpc.LitRPC)
	rpcl.Node = node
	rpcl.OffButton = make(chan bool, 1)

	litrpc.RPCListen(rpcl, conf.Rpcport)
	litbamf.BamfListen(conf.Rpcport, conf.LitHomeDir)

	<-rpcl.OffButton
	fmt.Printf("Got stop request\n")
	time.Sleep(time.Second)

	return
	// New directory being created over at PWD
	// conf file being created at /
}

func createDefaultConfigFile(destinationPath string) error {

	// We assume sample config file path is same as binary TODO: change to ~/.lit/config/
	path, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		return err
	}
	sampleConfigPath := filepath.Join(path, defaultConfigFilename)

	// We generate a random user and password
	randomBytes := make([]byte, 20)
	_, err = rand.Read(randomBytes)
	if err != nil {
		return err
	}
	generatedRPCUser := base64.StdEncoding.EncodeToString(randomBytes)

	_, err = rand.Read(randomBytes)
	if err != nil {
		return err
	}
	generatedRPCPass := base64.StdEncoding.EncodeToString(randomBytes)

	src, err := os.Open(sampleConfigPath)
	if err != nil {
		return err
	}
	defer src.Close()

	dest, err := os.OpenFile(filepath.Join(destinationPath, defaultConfigFilename),
		os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	defer dest.Close()

	// We copy every line from the sample config file to the destination,
	// only replacing the two lines for rpcuser and rpcpass
	reader := bufio.NewReader(src)
	for err != io.EOF {
		var line string
		line, err = reader.ReadString('\n')
		if err != nil && err != io.EOF {
			return err
		}

		if strings.Contains(line, "rpcuser=") {
			line = "rpcuser=" + generatedRPCUser + "\n"
		} else if strings.Contains(line, "rpcpass=") {
			line = "rpcpass=" + generatedRPCPass + "\n"
		}

		if _, err := dest.WriteString(line); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

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

func path_exists(name string) bool {
	_, err := os.Stat(name)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}

func handle_err(err error) {
	if err != nil {
		g_ctx.Errorf("%v\n", err.Error())
		//panic(err.Error())

		if g_ctx != nil {
			g_ctx.Exit(1)
		}
		os.Exit(1)
	}
}

func is_git_repo(dirname string) bool {
	return path_exists(filepath.Join(dirname, ".git"))
}

func copytree(dstdir, srcdir string) error {
	var err error

	if !path_exists(dstdir) {
		err = os.MkdirAll(dstdir, 0755)
		if err != nil {
			return err
		}
	}

	err = filepath.Walk(srcdir, func(path string, info os.FileInfo, err error) error {
		rel := ""
		rel, err = filepath.Rel(srcdir, path)
		out := filepath.Join(dstdir, rel)
		fmode := info.Mode()
		if fmode.IsDir() {
			err = os.MkdirAll(out, fmode.Perm())
			if err != nil {
				return err
			}
		} else if fmode.IsRegular() {
			dst, err := os.OpenFile(out, os.O_CREATE|os.O_RDWR, fmode.Perm())
			if err != nil {
				return nil
			}
			src, err := os.Open(path)
			if err != nil {
				return nil
			}
			_, err = io.Copy(dst, src)
			if err != nil {
				return nil
			}
		} else if (fmode & os.ModeSymlink) != 0 {
			rlink, err := os.Readlink(path)
			if err != nil {
				return err
			}
			err = os.Symlink(rlink, out)
			if err != nil {
				return err
			}
		} else {
			return fmt.Errorf("unhandled mode (%v) for path [%s]", fmode, path)
		}
		return nil
	})
	return err
}

// EOF
<commit_msg>utils.copytree: close destination. return errors<commit_after>package main

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

func path_exists(name string) bool {
	_, err := os.Stat(name)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}

func handle_err(err error) {
	if err != nil {
		g_ctx.Errorf("%v\n", err.Error())
		//panic(err.Error())

		if g_ctx != nil {
			g_ctx.Exit(1)
		}
		os.Exit(1)
	}
}

func is_git_repo(dirname string) bool {
	return path_exists(filepath.Join(dirname, ".git"))
}

func copytree(dstdir, srcdir string) error {
	var err error

	if !path_exists(dstdir) {
		err = os.MkdirAll(dstdir, 0755)
		if err != nil {
			return err
		}
	}

	err = filepath.Walk(srcdir, func(path string, info os.FileInfo, err error) error {
		rel := ""
		rel, err = filepath.Rel(srcdir, path)
		out := filepath.Join(dstdir, rel)
		fmode := info.Mode()
		if fmode.IsDir() {
			err = os.MkdirAll(out, fmode.Perm())
			if err != nil {
				return err
			}
		} else if fmode.IsRegular() {
			dst, err := os.OpenFile(out, os.O_CREATE|os.O_RDWR, fmode.Perm())
			if err != nil {
				return err
			}
			defer func() { err = dst.Close() }()
			src, err := os.Open(path)
			if err != nil {
				return err
			}
			_, err = io.Copy(dst, src)
			if err != nil {
				return err
			}
		} else if (fmode & os.ModeSymlink) != 0 {
			rlink, err := os.Readlink(path)
			if err != nil {
				return err
			}
			err = os.Symlink(rlink, out)
			if err != nil {
				return err
			}
		} else {
			return fmt.Errorf("unhandled mode (%v) for path [%s]", fmode, path)
		}
		return nil
	})
	return err
}

// EOF
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"encoding/hex"
	"io"
	"sort"

	"github.com/wvanbergen/kazoo-go"
)

func getGroupName(url string) string {
	m := md5.New()
	m.Write([]byte(url))
	s := hex.EncodeToString(m.Sum(nil))
	return s
}

func discardBody(r io.Reader) {
	tempBuf := make([]byte, 4096)
	for {
		_, e := r.Read(tempBuf)
		if e != nil {
			break
		}
	}
}

func retrievePartitionLeaders(partitions kazoo.PartitionList) (partitionLeaders, error) {

	pls := make(partitionLeaders, 0, len(partitions))
	for _, partition := range partitions {
		leader, err := partition.Leader()
		if err != nil {
			return nil, err
		}

		pl := partitionLeader{id: partition.ID, leader: leader, partition: partition}
		pls = append(pls, pl)
	}

	return pls, nil
}

// Divides a set of partitions between a set of consumers.
func dividePartitionsBetweenConsumers(consumers kazoo.ConsumergroupInstanceList, partitions partitionLeaders) map[string][]*kazoo.Partition {
	result := make(map[string][]*kazoo.Partition)

	plen := len(partitions)
	clen := len(consumers)
	if clen == 0 {
		return result
	}

	sort.Sort(partitions)
	sort.Sort(consumers)

	n := plen / clen
	m := plen % clen
	p := 0
	for i, consumer := range consumers {
		first := p
		last := first + n
		if m > 0 && i < m {
			last++
		}
		if last > plen {
			last = plen
		}

		for _, pl := range partitions[first:last] {
			result[consumer.ID] = append(result[consumer.ID], pl.partition)
		}
		p = last
	}

	return result
}

type partitionLeader struct {
	id        int32
	leader    int32
	partition *kazoo.Partition
}

// A sortable slice of PartitionLeader structs
type partitionLeaders []partitionLeader

func (pls partitionLeaders) Len() int {
	return len(pls)
}

func (pls partitionLeaders) Less(i, j int) bool {
	return pls[i].leader < pls[j].leader || (pls[i].leader == pls[j].leader && pls[i].id < pls[j].id)
}

func (s partitionLeaders) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
<commit_msg>Remove discardBody from utils.go<commit_after>package main

import (
	"crypto/md5"
	"encoding/hex"
	"sort"

	"github.com/wvanbergen/kazoo-go"
)

func getGroupName(url string) string {
	m := md5.New()
	m.Write([]byte(url))
	s := hex.EncodeToString(m.Sum(nil))
	return s
}

func retrievePartitionLeaders(partitions kazoo.PartitionList) (partitionLeaders, error) {

	pls := make(partitionLeaders, 0, len(partitions))
	for _, partition := range partitions {
		leader, err := partition.Leader()
		if err != nil {
			return nil, err
		}

		pl := partitionLeader{id: partition.ID, leader: leader, partition: partition}
		pls = append(pls, pl)
	}

	return pls, nil
}

// Divides a set of partitions between a set of consumers.
func dividePartitionsBetweenConsumers(consumers kazoo.ConsumergroupInstanceList, partitions partitionLeaders) map[string][]*kazoo.Partition {
	result := make(map[string][]*kazoo.Partition)

	plen := len(partitions)
	clen := len(consumers)
	if clen == 0 {
		return result
	}

	sort.Sort(partitions)
	sort.Sort(consumers)

	n := plen / clen
	m := plen % clen
	p := 0
	for i, consumer := range consumers {
		first := p
		last := first + n
		if m > 0 && i < m {
			last++
		}
		if last > plen {
			last = plen
		}

		for _, pl := range partitions[first:last] {
			result[consumer.ID] = append(result[consumer.ID], pl.partition)
		}
		p = last
	}

	return result
}

type partitionLeader struct {
	id        int32
	leader    int32
	partition *kazoo.Partition
}

// A sortable slice of PartitionLeader structs
type partitionLeaders []partitionLeader

func (pls partitionLeaders) Len() int {
	return len(pls)
}

func (pls partitionLeaders) Less(i, j int) bool {
	return pls[i].leader < pls[j].leader || (pls[i].leader == pls[j].leader && pls[i].id < pls[j].id)
}

func (s partitionLeaders) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
<|endoftext|>


<commit_before>package main

import (
	pb "github.com/clawio/service.localstore.meta/proto"
	"io"
	"mime"
	"os"
	"path"
)

func (s *server) getMeta(p string) (*pb.Metadata, error) {
	finfo, err := os.Stat(p)
	if err != nil {
		return &pb.Metadata{}, err
	}

	m := &pb.Metadata{}
	m.Id = "TODO"
	m.Path = path.Clean(p)
	m.Size = uint32(finfo.Size())
	m.IsContainer = finfo.IsDir()
	m.Modified = uint32(finfo.ModTime().Unix())
	m.Etag = "TODO"
	m.Permissions = 0
	m.MimeType = mime.TypeByExtension(path.Ext(m.Path))

	return m, nil
}

func copyFile(src, dst string, size int64) (err error) {
	reader, err := os.Open(src)
	if err != nil {
		return err
	}
	defer reader.Close()

	writer, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer writer.Close()

	_, err = io.CopyN(writer, reader, size)
	if err != nil {
		return err
	}
	return nil
}

func copyDir(src, dst string) (err error) {
	err = os.Mkdir(dst, dirPerm)
	if err != nil {
		return err
	}

	directory, err := os.Open(src)
	if err != nil {
		return err
	}
	defer directory.Close()

	objects, err := directory.Readdir(-1)

	for _, obj := range objects {

		_src := path.Join(src, obj.Name())
		_dst := path.Join(dst, obj.Name())

		if obj.IsDir() {
			// create sub-directories - recursively
			err = copyDir(_src, _dst)
			if err != nil {
				return err
			}
		} else {
			// perform copy
			err = copyFile(_src, _dst, obj.Size())
			if err != nil {
				return err
			}
		}
	}
	return
}
<commit_msg>Default mime to octet-stream<commit_after>package main

import (
	pb "github.com/clawio/service.localstore.meta/proto"
	"io"
	"mime"
	"os"
	"path"
)

func (s *server) getMeta(p string) (*pb.Metadata, error) {
	finfo, err := os.Stat(p)
	if err != nil {
		return &pb.Metadata{}, err
	}

	m := &pb.Metadata{}
	m.Id = "TODO"
	m.Path = path.Clean(p)
	m.Size = uint32(finfo.Size())
	m.IsContainer = finfo.IsDir()
	m.Modified = uint32(finfo.ModTime().Unix())
	m.Etag = "TODO"
	m.Permissions = 0
	m.MimeType = mime.TypeByExtension(path.Ext(m.Path))

	if m.MimeType == "" {
		m.MimeType = "application/octet-stream"
	}

	return m, nil
}

func copyFile(src, dst string, size int64) (err error) {
	reader, err := os.Open(src)
	if err != nil {
		return err
	}
	defer reader.Close()

	writer, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer writer.Close()

	_, err = io.CopyN(writer, reader, size)
	if err != nil {
		return err
	}
	return nil
}

func copyDir(src, dst string) (err error) {
	err = os.Mkdir(dst, dirPerm)
	if err != nil {
		return err
	}

	directory, err := os.Open(src)
	if err != nil {
		return err
	}
	defer directory.Close()

	objects, err := directory.Readdir(-1)

	for _, obj := range objects {

		_src := path.Join(src, obj.Name())
		_dst := path.Join(dst, obj.Name())

		if obj.IsDir() {
			// create sub-directories - recursively
			err = copyDir(_src, _dst)
			if err != nil {
				return err
			}
		} else {
			// perform copy
			err = copyFile(_src, _dst, obj.Size())
			if err != nil {
				return err
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package citadel

import (
	"fmt"
	"strings"

	"github.com/samalba/dockerclient"
)

// ValidateContainer ensures that the required fields are set on the container
func ValidateContainer(c *Container) error {
	switch {
	case c.Cpus == 0:
		return fmt.Errorf("container cannot have cpus equal to 0")
	case c.Memory == 0:
		return fmt.Errorf("container cannot have memory equal to 0")
	case c.Image == "":
		return fmt.Errorf("container must have an image")
	case c.Name == "":
		return fmt.Errorf("container must have a name")
	case c.Type == "":
		return fmt.Errorf("container must have a type")
	}

	return nil
}

func asCitadelContainer(container *dockerclient.Container, engine *Engine) (*Container, error) {
	info, err := engine.client.InspectContainer(container.Id)
	if err != nil {
		return nil, err
	}

	var ports []*Port

	for _, port := range container.Ports {
		p := &Port{
			Proto: port.Type,
			Port:  port.PublicPort,
		}
		ports = append(ports, p)
	}

	placement := &Placement{
		Engine:     engine,
		InternalIP: info.NetworkSettings.IpAddress,
		Ports:      ports,
	}

	var (
		cType  = ""
		labels = []string{}
		env    = make(map[string]string)
	)

	for _, e := range info.Config.Env {
		vals := strings.Split(e, "=")
		k, v := vals[0], vals[1]

		switch k {
		case "_citadel_type":
			cType = v
		case "_citadel_labels":
			labels = strings.Split(v, ",")
		case "HOME", "DEBIAN_FRONTEND", "PATH":
			continue
		default:
			env[k] = v
		}
	}

	return &Container{
		Name:        strings.TrimPrefix(info.Name, "/"),
		Image:       container.Image,
		Cpus:        float64(info.Config.CpuShares) / 100.0 * engine.Cpus,
		Memory:      float64(info.Config.Memory / 1024 / 1024),
		Environment: env,
		Hostname:    info.Config.Hostname,
		Domainname:  info.Config.Domainname,
		Type:        cType,
		Labels:      labels,
		Placement:   placement,
	}, nil
}
<commit_msg>Add container port to utils<commit_after>package citadel

import (
	"fmt"
	"strings"

	"github.com/samalba/dockerclient"
)

// ValidateContainer ensures that the required fields are set on the container
func ValidateContainer(c *Container) error {
	switch {
	case c.Cpus == 0:
		return fmt.Errorf("container cannot have cpus equal to 0")
	case c.Memory == 0:
		return fmt.Errorf("container cannot have memory equal to 0")
	case c.Image == "":
		return fmt.Errorf("container must have an image")
	case c.Name == "":
		return fmt.Errorf("container must have a name")
	case c.Type == "":
		return fmt.Errorf("container must have a type")
	}

	return nil
}

func asCitadelContainer(container *dockerclient.Container, engine *Engine) (*Container, error) {
	info, err := engine.client.InspectContainer(container.Id)
	if err != nil {
		return nil, err
	}

	var ports []*Port
	for _, port := range container.Ports {
		p := &Port{
			Proto:         port.Type,
			Port:          port.PublicPort,
			ContainerPort: port.PrivatePort,
		}
		ports = append(ports, p)
	}

	placement := &Placement{
		Engine:     engine,
		InternalIP: info.NetworkSettings.IpAddress,
		Ports:      ports,
	}

	var (
		cType  = ""
		labels = []string{}
		env    = make(map[string]string)
	)

	for _, e := range info.Config.Env {
		vals := strings.Split(e, "=")
		k, v := vals[0], vals[1]

		switch k {
		case "_citadel_type":
			cType = v
		case "_citadel_labels":
			labels = strings.Split(v, ",")
		case "HOME", "DEBIAN_FRONTEND", "PATH":
			continue
		default:
			env[k] = v
		}
	}

	return &Container{
		Name:        strings.TrimPrefix(info.Name, "/"),
		Image:       container.Image,
		Cpus:        float64(info.Config.CpuShares) / 100.0 * engine.Cpus,
		Memory:      float64(info.Config.Memory / 1024 / 1024),
		Environment: env,
		Hostname:    info.Config.Hostname,
		Domainname:  info.Config.Domainname,
		Type:        cType,
		Labels:      labels,
		Placement:   placement,
	}, nil
}
<|endoftext|>


<commit_before>package storage

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/containers/storage/pkg/homedir"
	"github.com/containers/storage/pkg/idtools"
	"github.com/containers/storage/pkg/system"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
func ParseIDMapping(UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap string) (*IDMappingOptions, error) {
	options := IDMappingOptions{
		HostUIDMapping: true,
		HostGIDMapping: true,
	}
	if subGIDMap == "" && subUIDMap != "" {
		subGIDMap = subUIDMap
	}
	if subUIDMap == "" && subGIDMap != "" {
		subUIDMap = subGIDMap
	}
	if len(GIDMapSlice) == 0 && len(UIDMapSlice) != 0 {
		GIDMapSlice = UIDMapSlice
	}
	if len(UIDMapSlice) == 0 && len(GIDMapSlice) != 0 {
		UIDMapSlice = GIDMapSlice
	}
	if len(UIDMapSlice) == 0 && subUIDMap == "" && os.Getuid() != 0 {
		UIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getuid())}
	}
	if len(GIDMapSlice) == 0 && subGIDMap == "" && os.Getuid() != 0 {
		GIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getgid())}
	}

	if subUIDMap != "" && subGIDMap != "" {
		mappings, err := idtools.NewIDMappings(subUIDMap, subGIDMap)
		if err != nil {
			return nil, errors.Wrapf(err, "failed to create NewIDMappings for uidmap=%s gidmap=%s", subUIDMap, subGIDMap)
		}
		options.UIDMap = mappings.UIDs()
		options.GIDMap = mappings.GIDs()
	}
	parsedUIDMap, err := idtools.ParseIDMap(UIDMapSlice, "UID")
	if err != nil {
		return nil, errors.Wrapf(err, "failed to create ParseUIDMap UID=%s", UIDMapSlice)
	}
	parsedGIDMap, err := idtools.ParseIDMap(GIDMapSlice, "GID")
	if err != nil {
		return nil, errors.Wrapf(err, "failed to create ParseGIDMap GID=%s", UIDMapSlice)
	}
	options.UIDMap = append(options.UIDMap, parsedUIDMap...)
	options.GIDMap = append(options.GIDMap, parsedGIDMap...)
	if len(options.UIDMap) > 0 {
		options.HostUIDMapping = false
	}
	if len(options.GIDMap) > 0 {
		options.HostGIDMapping = false
	}
	return &options, nil
}

// GetRootlessRuntimeDir returns the runtime directory when running as non root
func GetRootlessRuntimeDir(rootlessUID int) (string, error) {
	path, err := getRootlessRuntimeDir(rootlessUID)
	if err != nil {
		return "", err
	}
	path = filepath.Join(path, "containers")
	if err := os.MkdirAll(path, 0700); err != nil {
		return "", errors.Wrapf(err, "unable to make rootless runtime dir %s", path)
	}
	return path, nil
}

type rootlessRuntimeDirEnvironment interface {
	getProcCommandFile() string
	getRunUserDir() string
	getTmpPerUserDir() string

	homeDirGetRuntimeDir() (string, error)
	systemLstat(string) (*system.StatT, error)
	homedirGet() string
}

type rootlessRuntimeDirEnvironmentImplementation struct {
	procCommandFile string
	runUserDir      string
	tmpPerUserDir   string
}

func (env rootlessRuntimeDirEnvironmentImplementation) getProcCommandFile() string {
	return env.procCommandFile
}
func (env rootlessRuntimeDirEnvironmentImplementation) getRunUserDir() string {
	return env.runUserDir
}
func (env rootlessRuntimeDirEnvironmentImplementation) getTmpPerUserDir() string {
	return env.tmpPerUserDir
}
func (rootlessRuntimeDirEnvironmentImplementation) homeDirGetRuntimeDir() (string, error) {
	return homedir.GetRuntimeDir()
}
func (rootlessRuntimeDirEnvironmentImplementation) systemLstat(path string) (*system.StatT, error) {
	return system.Lstat(path)
}
func (rootlessRuntimeDirEnvironmentImplementation) homedirGet() string {
	return homedir.Get()
}

func isRootlessRuntimeDirOwner(dir string, env rootlessRuntimeDirEnvironment) bool {
	st, err := env.systemLstat(dir)
	return err == nil && int(st.UID()) == os.Getuid() && st.Mode()&0700 == 0700 && st.Mode()&0066 == 0000
}

// getRootlessRuntimeDirIsolated is an internal implementation detail of getRootlessRuntimeDir to allow testing.
// Everyone but the tests this is intended for should only call getRootlessRuntimeDir, never this function.
func getRootlessRuntimeDirIsolated(env rootlessRuntimeDirEnvironment) (string, error) {
	runtimeDir, err := env.homeDirGetRuntimeDir()
	if err == nil {
		return runtimeDir, nil
	}

	initCommand, err := ioutil.ReadFile(env.getProcCommandFile())
	if err != nil || string(initCommand) == "systemd" {
		runUserDir := env.getRunUserDir()
		if isRootlessRuntimeDirOwner(runUserDir, env) {
			return runUserDir, nil
		}
	}

	tmpPerUserDir := env.getTmpPerUserDir()
	if _, err := env.systemLstat(tmpPerUserDir); os.IsNotExist(err) {
		if err := os.Mkdir(tmpPerUserDir, 0700); err != nil {
			logrus.Errorf("failed to create temp directory for user: %v", err)
		} else {
			return tmpPerUserDir, nil
		}
	} else if isRootlessRuntimeDirOwner(tmpPerUserDir, env) {
		return tmpPerUserDir, nil
	}

	homeDir := env.homedirGet()
	if homeDir == "" {
		return "", errors.New("neither XDG_RUNTIME_DIR not temp dir nor HOME was set non-empty")
	}
	resolvedHomeDir, err := filepath.EvalSymlinks(homeDir)
	if err != nil {
		return "", errors.Wrapf(err, "cannot resolve %s", homeDir)
	}
	return filepath.Join(resolvedHomeDir, "rundir"), nil
}

func getRootlessRuntimeDir(rootlessUID int) (string, error) {
	return getRootlessRuntimeDirIsolated(
		rootlessRuntimeDirEnvironmentImplementation{
			"/proc/1/comm",
			fmt.Sprintf("/run/user/%d", rootlessUID),
			fmt.Sprintf("%s/containers-user-%d", os.TempDir(), rootlessUID),
		},
	)
}

// getRootlessDirInfo returns the parent path of where the storage for containers and
// volumes will be in rootless mode
func getRootlessDirInfo(rootlessUID int) (string, string, error) {
	rootlessRuntime, err := GetRootlessRuntimeDir(rootlessUID)
	if err != nil {
		return "", "", err
	}

	dataDir, err := homedir.GetDataHome()
	if err == nil {
		return dataDir, rootlessRuntime, nil
	}

	home := homedir.Get()
	if home == "" {
		return "", "", errors.Wrapf(err, "neither XDG_DATA_HOME nor HOME was set non-empty")
	}
	// runc doesn't like symlinks in the rootfs path, and at least
	// on CoreOS /home is a symlink to /var/home, so resolve any symlink.
	resolvedHome, err := filepath.EvalSymlinks(home)
	if err != nil {
		return "", "", errors.Wrapf(err, "cannot resolve %s", home)
	}
	dataDir = filepath.Join(resolvedHome, ".local", "share")

	return dataDir, rootlessRuntime, nil
}

// getRootlessStorageOpts returns the storage opts for containers running as non root
func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOptions, error) {
	var opts StoreOptions

	dataDir, rootlessRuntime, err := getRootlessDirInfo(rootlessUID)
	if err != nil {
		return opts, err
	}
	opts.RunRoot = rootlessRuntime
	opts.GraphRoot = filepath.Join(dataDir, "containers", "storage")
	if systemOpts.RootlessStoragePath != "" {
		opts.RootlessStoragePath = systemOpts.RootlessStoragePath
	} else {
		opts.RootlessStoragePath = opts.GraphRoot
	}
	if path, err := exec.LookPath("fuse-overlayfs"); err == nil {
		opts.GraphDriverName = "overlay"
		opts.GraphDriverOptions = []string{fmt.Sprintf("overlay.mount_program=%s", path)}
		for _, o := range systemOpts.GraphDriverOptions {
			if strings.Contains(o, "ignore_chown_errors") {
				opts.GraphDriverOptions = append(opts.GraphDriverOptions, o)
				break
			}
		}
	} else {
		opts.GraphDriverName = "vfs"
	}
	return opts, nil
}

func getRootlessUID() int {
	uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
	if uidEnv != "" {
		u, _ := strconv.Atoi(uidEnv)
		return u
	}
	return os.Geteuid()
}

// DefaultStoreOptionsAutoDetectUID returns the default storage ops for containers
func DefaultStoreOptionsAutoDetectUID() (StoreOptions, error) {
	uid := getRootlessUID()
	return DefaultStoreOptions(uid != 0, uid)
}

// defaultStoreOptionsIsolated is an internal implementation detail of DefaultStoreOptions to allow testing.
// Everyone but the tests this is intended for should only call DefaultStoreOptions, never this function.
func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf string) (StoreOptions, error) {
	var (
		defaultRootlessRunRoot   string
		defaultRootlessGraphRoot string
		err                      error
	)
	storageOpts := defaultStoreOptions
	if rootless && rootlessUID != 0 {
		storageOpts, err = getRootlessStorageOpts(rootlessUID, storageOpts)
		if err != nil {
			return storageOpts, err
		}
	}
	_, err = os.Stat(storageConf)
	if err != nil && !os.IsNotExist(err) {
		return storageOpts, errors.Wrapf(err, "cannot stat %s", storageConf)
	}
	if err == nil {
		defaultRootlessRunRoot = storageOpts.RunRoot
		defaultRootlessGraphRoot = storageOpts.GraphRoot
		storageOpts = StoreOptions{}
		reloadConfigurationFileIfNeeded(storageConf, &storageOpts)
	}
	if storageOpts.RunRoot != "" {
		runRoot, err := expandEnvPath(storageOpts.RunRoot, rootlessUID)
		if err != nil {
			return storageOpts, err
		}
		storageOpts.RunRoot = runRoot
	}
	if storageOpts.GraphRoot != "" {
		graphRoot, err := expandEnvPath(storageOpts.GraphRoot, rootlessUID)
		if err != nil {
			return storageOpts, err
		}
		storageOpts.GraphRoot = graphRoot
	}

	if rootless && rootlessUID != 0 {
		if err == nil {
			// If the file did not specify a graphroot or runroot,
			// set sane defaults so we don't try and use root-owned
			// directories
			if storageOpts.RunRoot == "" {
				storageOpts.RunRoot = defaultRootlessRunRoot
			}
			if storageOpts.GraphRoot == "" {
				storageOpts.GraphRoot = defaultRootlessGraphRoot
			}
			if storageOpts.RootlessStoragePath != "" {
				rootlessStoragePath, err := expandEnvPath(storageOpts.RootlessStoragePath, rootlessUID)
				if err != nil {
					return storageOpts, err
				}
				storageOpts.GraphRoot = rootlessStoragePath
			}
		}
	}
	return storageOpts, nil
}

// DefaultStoreOptions returns the default storage ops for containers
func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
	storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0)
	if err != nil {
		return defaultStoreOptions, err
	}
	return defaultStoreOptionsIsolated(rootless, rootlessUID, storageConf)
}

func expandEnvPath(path string, rootlessUID int) (string, error) {
	path = strings.Replace(path, "$UID", strconv.Itoa(rootlessUID), -1)
	path = os.ExpandEnv(path)
	return path, nil
}

func validateMountOptions(mountOptions []string) error {
	var Empty struct{}
	// Add invalid options for ImageMount() here.
	invalidOptions := map[string]struct{}{
		"rw": Empty,
	}

	for _, opt := range mountOptions {
		if _, ok := invalidOptions[opt]; ok {
			return fmt.Errorf(" %q option not supported", opt)
		}
	}
	return nil
}
<commit_msg>Fix usage of rootless_storage_path from system storage.conf file<commit_after>package storage

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/containers/storage/pkg/homedir"
	"github.com/containers/storage/pkg/idtools"
	"github.com/containers/storage/pkg/system"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
func ParseIDMapping(UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap string) (*IDMappingOptions, error) {
	options := IDMappingOptions{
		HostUIDMapping: true,
		HostGIDMapping: true,
	}
	if subGIDMap == "" && subUIDMap != "" {
		subGIDMap = subUIDMap
	}
	if subUIDMap == "" && subGIDMap != "" {
		subUIDMap = subGIDMap
	}
	if len(GIDMapSlice) == 0 && len(UIDMapSlice) != 0 {
		GIDMapSlice = UIDMapSlice
	}
	if len(UIDMapSlice) == 0 && len(GIDMapSlice) != 0 {
		UIDMapSlice = GIDMapSlice
	}
	if len(UIDMapSlice) == 0 && subUIDMap == "" && os.Getuid() != 0 {
		UIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getuid())}
	}
	if len(GIDMapSlice) == 0 && subGIDMap == "" && os.Getuid() != 0 {
		GIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getgid())}
	}

	if subUIDMap != "" && subGIDMap != "" {
		mappings, err := idtools.NewIDMappings(subUIDMap, subGIDMap)
		if err != nil {
			return nil, errors.Wrapf(err, "failed to create NewIDMappings for uidmap=%s gidmap=%s", subUIDMap, subGIDMap)
		}
		options.UIDMap = mappings.UIDs()
		options.GIDMap = mappings.GIDs()
	}
	parsedUIDMap, err := idtools.ParseIDMap(UIDMapSlice, "UID")
	if err != nil {
		return nil, errors.Wrapf(err, "failed to create ParseUIDMap UID=%s", UIDMapSlice)
	}
	parsedGIDMap, err := idtools.ParseIDMap(GIDMapSlice, "GID")
	if err != nil {
		return nil, errors.Wrapf(err, "failed to create ParseGIDMap GID=%s", UIDMapSlice)
	}
	options.UIDMap = append(options.UIDMap, parsedUIDMap...)
	options.GIDMap = append(options.GIDMap, parsedGIDMap...)
	if len(options.UIDMap) > 0 {
		options.HostUIDMapping = false
	}
	if len(options.GIDMap) > 0 {
		options.HostGIDMapping = false
	}
	return &options, nil
}

// GetRootlessRuntimeDir returns the runtime directory when running as non root
func GetRootlessRuntimeDir(rootlessUID int) (string, error) {
	path, err := getRootlessRuntimeDir(rootlessUID)
	if err != nil {
		return "", err
	}
	path = filepath.Join(path, "containers")
	if err := os.MkdirAll(path, 0700); err != nil {
		return "", errors.Wrapf(err, "unable to make rootless runtime dir %s", path)
	}
	return path, nil
}

type rootlessRuntimeDirEnvironment interface {
	getProcCommandFile() string
	getRunUserDir() string
	getTmpPerUserDir() string

	homeDirGetRuntimeDir() (string, error)
	systemLstat(string) (*system.StatT, error)
	homedirGet() string
}

type rootlessRuntimeDirEnvironmentImplementation struct {
	procCommandFile string
	runUserDir      string
	tmpPerUserDir   string
}

func (env rootlessRuntimeDirEnvironmentImplementation) getProcCommandFile() string {
	return env.procCommandFile
}
func (env rootlessRuntimeDirEnvironmentImplementation) getRunUserDir() string {
	return env.runUserDir
}
func (env rootlessRuntimeDirEnvironmentImplementation) getTmpPerUserDir() string {
	return env.tmpPerUserDir
}
func (rootlessRuntimeDirEnvironmentImplementation) homeDirGetRuntimeDir() (string, error) {
	return homedir.GetRuntimeDir()
}
func (rootlessRuntimeDirEnvironmentImplementation) systemLstat(path string) (*system.StatT, error) {
	return system.Lstat(path)
}
func (rootlessRuntimeDirEnvironmentImplementation) homedirGet() string {
	return homedir.Get()
}

func isRootlessRuntimeDirOwner(dir string, env rootlessRuntimeDirEnvironment) bool {
	st, err := env.systemLstat(dir)
	return err == nil && int(st.UID()) == os.Getuid() && st.Mode()&0700 == 0700 && st.Mode()&0066 == 0000
}

// getRootlessRuntimeDirIsolated is an internal implementation detail of getRootlessRuntimeDir to allow testing.
// Everyone but the tests this is intended for should only call getRootlessRuntimeDir, never this function.
func getRootlessRuntimeDirIsolated(env rootlessRuntimeDirEnvironment) (string, error) {
	runtimeDir, err := env.homeDirGetRuntimeDir()
	if err == nil {
		return runtimeDir, nil
	}

	initCommand, err := ioutil.ReadFile(env.getProcCommandFile())
	if err != nil || string(initCommand) == "systemd" {
		runUserDir := env.getRunUserDir()
		if isRootlessRuntimeDirOwner(runUserDir, env) {
			return runUserDir, nil
		}
	}

	tmpPerUserDir := env.getTmpPerUserDir()
	if _, err := env.systemLstat(tmpPerUserDir); os.IsNotExist(err) {
		if err := os.Mkdir(tmpPerUserDir, 0700); err != nil {
			logrus.Errorf("failed to create temp directory for user: %v", err)
		} else {
			return tmpPerUserDir, nil
		}
	} else if isRootlessRuntimeDirOwner(tmpPerUserDir, env) {
		return tmpPerUserDir, nil
	}

	homeDir := env.homedirGet()
	if homeDir == "" {
		return "", errors.New("neither XDG_RUNTIME_DIR not temp dir nor HOME was set non-empty")
	}
	resolvedHomeDir, err := filepath.EvalSymlinks(homeDir)
	if err != nil {
		return "", errors.Wrapf(err, "cannot resolve %s", homeDir)
	}
	return filepath.Join(resolvedHomeDir, "rundir"), nil
}

func getRootlessRuntimeDir(rootlessUID int) (string, error) {
	return getRootlessRuntimeDirIsolated(
		rootlessRuntimeDirEnvironmentImplementation{
			"/proc/1/comm",
			fmt.Sprintf("/run/user/%d", rootlessUID),
			fmt.Sprintf("%s/containers-user-%d", os.TempDir(), rootlessUID),
		},
	)
}

// getRootlessDirInfo returns the parent path of where the storage for containers and
// volumes will be in rootless mode
func getRootlessDirInfo(rootlessUID int) (string, string, error) {
	rootlessRuntime, err := GetRootlessRuntimeDir(rootlessUID)
	if err != nil {
		return "", "", err
	}

	dataDir, err := homedir.GetDataHome()
	if err == nil {
		return dataDir, rootlessRuntime, nil
	}

	home := homedir.Get()
	if home == "" {
		return "", "", errors.Wrapf(err, "neither XDG_DATA_HOME nor HOME was set non-empty")
	}
	// runc doesn't like symlinks in the rootfs path, and at least
	// on CoreOS /home is a symlink to /var/home, so resolve any symlink.
	resolvedHome, err := filepath.EvalSymlinks(home)
	if err != nil {
		return "", "", errors.Wrapf(err, "cannot resolve %s", home)
	}
	dataDir = filepath.Join(resolvedHome, ".local", "share")

	return dataDir, rootlessRuntime, nil
}

// getRootlessStorageOpts returns the storage opts for containers running as non root
func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOptions, error) {
	var opts StoreOptions

	dataDir, rootlessRuntime, err := getRootlessDirInfo(rootlessUID)
	if err != nil {
		return opts, err
	}
	opts.RunRoot = rootlessRuntime
	if systemOpts.RootlessStoragePath != "" {
		opts.GraphRoot = systemOpts.RootlessStoragePath
	} else {
		opts.GraphRoot = filepath.Join(dataDir, "containers", "storage")
	}
	if path, err := exec.LookPath("fuse-overlayfs"); err == nil {
		opts.GraphDriverName = "overlay"
		opts.GraphDriverOptions = []string{fmt.Sprintf("overlay.mount_program=%s", path)}
		for _, o := range systemOpts.GraphDriverOptions {
			if strings.Contains(o, "ignore_chown_errors") {
				opts.GraphDriverOptions = append(opts.GraphDriverOptions, o)
				break
			}
		}
	} else {
		opts.GraphDriverName = "vfs"
	}
	return opts, nil
}

func getRootlessUID() int {
	uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
	if uidEnv != "" {
		u, _ := strconv.Atoi(uidEnv)
		return u
	}
	return os.Geteuid()
}

// DefaultStoreOptionsAutoDetectUID returns the default storage ops for containers
func DefaultStoreOptionsAutoDetectUID() (StoreOptions, error) {
	uid := getRootlessUID()
	return DefaultStoreOptions(uid != 0, uid)
}

// defaultStoreOptionsIsolated is an internal implementation detail of DefaultStoreOptions to allow testing.
// Everyone but the tests this is intended for should only call DefaultStoreOptions, never this function.
func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf string) (StoreOptions, error) {
	var (
		defaultRootlessRunRoot   string
		defaultRootlessGraphRoot string
		err                      error
	)
	storageOpts := defaultStoreOptions
	if rootless && rootlessUID != 0 {
		storageOpts, err = getRootlessStorageOpts(rootlessUID, storageOpts)
		if err != nil {
			return storageOpts, err
		}
	}
	_, err = os.Stat(storageConf)
	if err != nil && !os.IsNotExist(err) {
		return storageOpts, errors.Wrapf(err, "cannot stat %s", storageConf)
	}
	if err == nil {
		defaultRootlessRunRoot = storageOpts.RunRoot
		defaultRootlessGraphRoot = storageOpts.GraphRoot
		storageOpts = StoreOptions{}
		reloadConfigurationFileIfNeeded(storageConf, &storageOpts)
		if rootless && rootlessUID != 0 {
			// If the file did not specify a graphroot or runroot,
			// set sane defaults so we don't try and use root-owned
			// directories
			if storageOpts.RunRoot == "" {
				storageOpts.RunRoot = defaultRootlessRunRoot
			}
			if storageOpts.GraphRoot == "" {
				storageOpts.GraphRoot = defaultRootlessGraphRoot
			}
		}
	}
	if storageOpts.RunRoot != "" {
		runRoot, err := expandEnvPath(storageOpts.RunRoot, rootlessUID)
		if err != nil {
			return storageOpts, err
		}
		storageOpts.RunRoot = runRoot
	}
	if storageOpts.GraphRoot != "" {
		graphRoot, err := expandEnvPath(storageOpts.GraphRoot, rootlessUID)
		if err != nil {
			return storageOpts, err
		}
		storageOpts.GraphRoot = graphRoot
	}

	return storageOpts, nil
}

// DefaultStoreOptions returns the default storage ops for containers
func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
	storageConf, err := DefaultConfigFile(rootless && rootlessUID != 0)
	if err != nil {
		return defaultStoreOptions, err
	}
	return defaultStoreOptionsIsolated(rootless, rootlessUID, storageConf)
}

func expandEnvPath(path string, rootlessUID int) (string, error) {
	path = strings.Replace(path, "$UID", strconv.Itoa(rootlessUID), -1)
	path = os.ExpandEnv(path)
	return path, nil
}

func validateMountOptions(mountOptions []string) error {
	var Empty struct{}
	// Add invalid options for ImageMount() here.
	invalidOptions := map[string]struct{}{
		"rw": Empty,
	}

	for _, opt := range mountOptions {
		if _, ok := invalidOptions[opt]; ok {
			return fmt.Errorf(" %q option not supported", opt)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package app

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"
)

// A Logger represents an active logging object that generates lines of output.
type Logger interface {
	// Log logs a message using the default formats for its operands.
	// Spaces are always added between operands and a newline is appended.
	Log(v ...interface{})

	// Logf logs a message according to a format specifier.
	Logf(format string, v ...interface{})

	// Error logs an error using the default formats for its operands.
	// Spaces are always added between operands and a newline is appended.
	Error(v ...interface{})

	// Errorf logs an error according to a format specifier.
	Errorf(format string, v ...interface{})
}

const (
	defaultColor string = "\033[00m"
	accentColor  string = "\033[94m"
	errColor     string = "\033[91m"
)

// NewLogger creates a logger that writes on the given writer.
// Logs are written only if debug is enabled.
// It is safe for concurrent access.
func NewLogger(w io.Writer, debug bool) Logger {
	logger := newLogger(w, debug)
	return NewConcurrentLogger(logger)
}

type logger struct {
	writer io.Writer
	debug  bool
}

func newLogger(w io.Writer, debug bool) *logger {
	return &logger{
		writer: w,
		debug:  debug,
	}
}

func (l *logger) Log(v ...interface{}) {
	if !l.debug {
		return
	}
	printLogPrefix(l.writer, "Log  ", accentColor)
	fmt.Fprintln(l.writer, v...)
}

func (l *logger) Logf(format string, v ...interface{}) {
	if !l.debug {
		return
	}
	printLogPrefix(l.writer, "Log  ", accentColor)
	fmt.Fprintf(l.writer, format, v...)
	fmt.Fprintln(l.writer)
}

func (l *logger) Error(v ...interface{}) {
	printLogPrefix(l.writer, "Error", errColor)
	fmt.Fprintln(l.writer, v...)
}

func (l *logger) Errorf(format string, v ...interface{}) {
	printLogPrefix(l.writer, "Error", errColor)
	fmt.Fprintf(l.writer, format, v...)
	fmt.Fprintln(l.writer)
}

func printLogPrefix(w io.Writer, level, color string) {
	file, line := caller()
	now := time.Now().Format("2006/01/02 15:04:05")
	fmt.Fprintf(w,
		"%s%s%s %s %s:%v |> ",
		color,
		strings.ToUpper(level),
		defaultColor,
		now,
		file,
		line,
	)
}

func caller() (file string, line int) {
	_, file, line, _ = runtime.Caller(3)
	file = filepath.Base(file)
	return
}

// NewConsole creates a logger that writes messages on standard outputs.
// Logs are written on stdout, only if debug is enabled.
// Errors are written on stderr.
// It is safe for concurrent access.
func NewConsole(debug bool) Logger {
	logger := newConsole(debug)
	return NewConcurrentLogger(logger)
}

type console struct {
	std Logger
	err Logger
}

func newConsole(debug bool) *console {
	return &console{
		std: newLogger(os.Stdout, debug),
		err: newLogger(os.Stderr, debug),
	}
}

func (c *console) Log(v ...interface{}) {
	c.std.Log(v...)
}

func (c *console) Logf(format string, v ...interface{}) {
	c.std.Logf(format, v...)
}

func (c *console) Error(v ...interface{}) {
	c.err.Error(v...)
}

func (c *console) Errorf(format string, v ...interface{}) {
	c.err.Errorf(format, v...)
}

// NewMultiLogger creates a logger that aggregate multiple loggers.
func NewMultiLogger(loggers ...Logger) Logger {
	return &multiLogger{
		loggers: loggers,
	}
}

type multiLogger struct {
	loggers []Logger
}

func (l *multiLogger) Log(v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Log(v...)
	}
}

func (l *multiLogger) Logf(format string, v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Logf(format, v...)
	}
}

func (l *multiLogger) Error(v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Error(v...)
	}
}

func (l *multiLogger) Errorf(format string, v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Errorf(format, v...)
	}
}

// NewConcurrentLogger  decorates the given logger to ensure concurrent access
// safety.
func NewConcurrentLogger(l Logger) Logger {
	return &concurrentLogger{
		logger: l,
	}
}

type concurrentLogger struct {
	mutex  sync.Mutex
	logger Logger
}

func (l *concurrentLogger) Log(v ...interface{}) {
	l.mutex.Lock()
	l.logger.Log(v...)
	l.mutex.Unlock()
}

func (l *concurrentLogger) Logf(format string, v ...interface{}) {
	l.mutex.Lock()
	l.logger.Logf(format, v...)
	l.mutex.Unlock()
}

func (l *concurrentLogger) Error(v ...interface{}) {
	l.mutex.Lock()
	l.logger.Error(v...)
	l.mutex.Unlock()
}

func (l *concurrentLogger) Errorf(format string, v ...interface{}) {
	l.mutex.Lock()
	l.logger.Errorf(format, v...)
	l.mutex.Unlock()
}
<commit_msg>Remove caller in logs and better colors<commit_after>package app

import (
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"time"
)

// A Logger represents an active logging object that generates lines of output.
type Logger interface {
	// Log logs a message using the default formats for its operands.
	// Spaces are always added between operands and a newline is appended.
	Log(v ...interface{})

	// Logf logs a message according to a format specifier.
	Logf(format string, v ...interface{})

	// Error logs an error using the default formats for its operands.
	// Spaces are always added between operands and a newline is appended.
	Error(v ...interface{})

	// Errorf logs an error according to a format specifier.
	Errorf(format string, v ...interface{})
}

const (
	defaultColor string = "\033[00m"
	accentColor  string = "\033[94m"
	errColor     string = "\033[91m"
)

// NewLogger creates a logger that writes on the given writer.
// Logs are written only if debug is enabled.
// It is safe for concurrent access.
func NewLogger(w io.Writer, debug bool) Logger {
	logger := newLogger(w, debug)
	return NewConcurrentLogger(logger)
}

type logger struct {
	writer io.Writer
	debug  bool
}

func newLogger(w io.Writer, debug bool) *logger {
	return &logger{
		writer: w,
		debug:  debug,
	}
}

func (l *logger) Log(v ...interface{}) {
	if !l.debug {
		return
	}
	printLogPrefix(l.writer, "Log  ", accentColor)
	fmt.Fprintln(l.writer, v...)
}

func (l *logger) Logf(format string, v ...interface{}) {
	if !l.debug {
		return
	}
	printLogPrefix(l.writer, "Log  ", accentColor)
	fmt.Fprintf(l.writer, format, v...)
	fmt.Fprintln(l.writer)
}

func (l *logger) Error(v ...interface{}) {
	printLogPrefix(l.writer, "Error", errColor)
	fmt.Fprintln(l.writer, v...)
}

func (l *logger) Errorf(format string, v ...interface{}) {
	printLogPrefix(l.writer, "Error", errColor)
	fmt.Fprintf(l.writer, format, v...)
	fmt.Fprintln(l.writer)
}

func printLogPrefix(w io.Writer, level, color string) {
	now := time.Now().Format("2006/01/02 15:04:05")
	fmt.Fprintf(w,
		"%s%s%s %s %s|>%s ",
		color,
		strings.ToUpper(level),
		defaultColor,
		now,
		color,
		defaultColor,
	)
}

// NewConsole creates a logger that writes messages on standard outputs.
// Logs are written on stdout, only if debug is enabled.
// Errors are written on stderr.
// It is safe for concurrent access.
func NewConsole(debug bool) Logger {
	logger := newConsole(debug)
	return NewConcurrentLogger(logger)
}

type console struct {
	std Logger
	err Logger
}

func newConsole(debug bool) *console {
	return &console{
		std: newLogger(os.Stdout, debug),
		err: newLogger(os.Stderr, debug),
	}
}

func (c *console) Log(v ...interface{}) {
	c.std.Log(v...)
}

func (c *console) Logf(format string, v ...interface{}) {
	c.std.Logf(format, v...)
}

func (c *console) Error(v ...interface{}) {
	c.err.Error(v...)
}

func (c *console) Errorf(format string, v ...interface{}) {
	c.err.Errorf(format, v...)
}

// NewMultiLogger creates a logger that aggregate multiple loggers.
func NewMultiLogger(loggers ...Logger) Logger {
	return &multiLogger{
		loggers: loggers,
	}
}

type multiLogger struct {
	loggers []Logger
}

func (l *multiLogger) Log(v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Log(v...)
	}
}

func (l *multiLogger) Logf(format string, v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Logf(format, v...)
	}
}

func (l *multiLogger) Error(v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Error(v...)
	}
}

func (l *multiLogger) Errorf(format string, v ...interface{}) {
	for _, logger := range l.loggers {
		logger.Errorf(format, v...)
	}
}

// NewConcurrentLogger  decorates the given logger to ensure concurrent access
// safety.
func NewConcurrentLogger(l Logger) Logger {
	return &concurrentLogger{
		logger: l,
	}
}

type concurrentLogger struct {
	mutex  sync.Mutex
	logger Logger
}

func (l *concurrentLogger) Log(v ...interface{}) {
	l.mutex.Lock()
	l.logger.Log(v...)
	l.mutex.Unlock()
}

func (l *concurrentLogger) Logf(format string, v ...interface{}) {
	l.mutex.Lock()
	l.logger.Logf(format, v...)
	l.mutex.Unlock()
}

func (l *concurrentLogger) Error(v ...interface{}) {
	l.mutex.Lock()
	l.logger.Error(v...)
	l.mutex.Unlock()
}

func (l *concurrentLogger) Errorf(format string, v ...interface{}) {
	l.mutex.Lock()
	l.logger.Errorf(format, v...)
	l.mutex.Unlock()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/btcsuite/btclog"
	"github.com/btcsuite/seelog"
	"github.com/lightningnetwork/lnd/chainntnfs"
	"github.com/lightningnetwork/lnd/channeldb"
	"github.com/lightningnetwork/lnd/discovery"
	"github.com/lightningnetwork/lnd/htlcswitch"
	"github.com/lightningnetwork/lnd/lnwallet"
	"github.com/lightningnetwork/lnd/routing"
	"github.com/roasbeef/btcd/connmgr"
)

// Loggers per subsystem.  Note that backendLog is a seelog logger that all of
// the subsystem loggers route their messages to.  When adding new subsystems,
// add a reference here, to the subsystemLoggers map, and the useLogger
// function.
var (
	backendLog = seelog.Disabled
	ltndLog    = btclog.Disabled
	lnwlLog    = btclog.Disabled
	peerLog    = btclog.Disabled
	discLog    = btclog.Disabled
	fndgLog    = btclog.Disabled
	rpcsLog    = btclog.Disabled
	srvrLog    = btclog.Disabled
	ntfnLog    = btclog.Disabled
	chdbLog    = btclog.Disabled
	hswcLog    = btclog.Disabled
	utxnLog    = btclog.Disabled
	brarLog    = btclog.Disabled
	cmgrLog    = btclog.Disabled
	crtrLog    = btclog.Disabled
)

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

// useLogger updates the logger references for subsystemID to logger.  Invalid
// subsystems are ignored.
func useLogger(subsystemID string, logger btclog.Logger) {
	if _, ok := subsystemLoggers[subsystemID]; !ok {
		return
	}
	subsystemLoggers[subsystemID] = logger

	switch subsystemID {
	case "LTND":
		ltndLog = logger

	case "LNWL":
		lnwlLog = logger
		lnwallet.UseLogger(logger)

	case "PEER":
		peerLog = logger

	case "DISC":
		discLog = logger
		discovery.UseLogger(logger)

	case "RPCS":
		rpcsLog = logger

	case "SRVR":
		srvrLog = logger

	case "NTFN":
		ntfnLog = logger
		chainntnfs.UseLogger(logger)

	case "CHDB":
		chdbLog = logger
		channeldb.UseLogger(logger)

	case "FNDG":
		fndgLog = logger

	case "HSWC":
		hswcLog = logger
		htlcswitch.UseLogger(logger)

	case "UTXN":
		utxnLog = logger

	case "BRAR":
		brarLog = logger

	case "CMGR":
		cmgrLog = logger
		connmgr.UseLogger(logger)

	case "CRTR":
		crtrLog = logger
		routing.UseLogger(crtrLog)
	}
}

// initSeelogLogger initializes a new seelog logger that is used as the backend
// for all logging subsystems.
func initSeelogLogger(logFile string) {
	config := `
	<seelog type="adaptive" mininterval="2000000" maxinterval="100000000"
		critmsgcount="500" minlevel="trace">
		<outputs formatid="all">
			<console />
			<rollingfile type="size" filename="%s" maxsize="10485760" maxrolls="3" />
		</outputs>
		<formats>
			<format id="all" format="%%Time %%Date [%%LEV] %%Msg%%n" />
		</formats>
	</seelog>`
	config = fmt.Sprintf(config, logFile)

	logger, err := seelog.LoggerFromConfigAsString(config)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to create logger: %v", err)
		os.Exit(1)
	}

	backendLog = logger
}

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

	// Default to info if the log level is invalid.
	level, ok := btclog.LogLevelFromString(logLevel)
	if !ok {
		level = btclog.InfoLvl
	}

	// Create new logger for the subsystem if needed.
	if logger == btclog.Disabled {
		logger = btclog.NewSubsystemLogger(backendLog, subsystemID+": ")
		useLogger(subsystemID, logger)
	}
	logger.SetLevel(level)
}

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

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

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

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

import (
	"fmt"
	"os"

	"github.com/btcsuite/btclog"
	"github.com/btcsuite/seelog"
	"github.com/lightninglabs/neutrino"
	"github.com/lightningnetwork/lnd/chainntnfs"
	"github.com/lightningnetwork/lnd/channeldb"
	"github.com/lightningnetwork/lnd/discovery"
	"github.com/lightningnetwork/lnd/htlcswitch"
	"github.com/lightningnetwork/lnd/lnwallet"
	"github.com/lightningnetwork/lnd/routing"
	"github.com/roasbeef/btcd/connmgr"
)

// Loggers per subsystem.  Note that backendLog is a seelog logger that all of
// the subsystem loggers route their messages to.  When adding new subsystems,
// add a reference here, to the subsystemLoggers map, and the useLogger
// function.
var (
	backendLog = seelog.Disabled
	ltndLog    = btclog.Disabled
	lnwlLog    = btclog.Disabled
	peerLog    = btclog.Disabled
	discLog    = btclog.Disabled
	fndgLog    = btclog.Disabled
	rpcsLog    = btclog.Disabled
	srvrLog    = btclog.Disabled
	ntfnLog    = btclog.Disabled
	chdbLog    = btclog.Disabled
	hswcLog    = btclog.Disabled
	utxnLog    = btclog.Disabled
	brarLog    = btclog.Disabled
	cmgrLog    = btclog.Disabled
	crtrLog    = btclog.Disabled
	btcnLog    = btclog.Disabled
)

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

// useLogger updates the logger references for subsystemID to logger.  Invalid
// subsystems are ignored.
func useLogger(subsystemID string, logger btclog.Logger) {
	if _, ok := subsystemLoggers[subsystemID]; !ok {
		return
	}
	subsystemLoggers[subsystemID] = logger

	switch subsystemID {
	case "LTND":
		ltndLog = logger

	case "LNWL":
		lnwlLog = logger
		lnwallet.UseLogger(logger)

	case "PEER":
		peerLog = logger

	case "DISC":
		discLog = logger
		discovery.UseLogger(logger)

	case "RPCS":
		rpcsLog = logger

	case "SRVR":
		srvrLog = logger

	case "NTFN":
		ntfnLog = logger
		chainntnfs.UseLogger(logger)

	case "CHDB":
		chdbLog = logger
		channeldb.UseLogger(logger)

	case "FNDG":
		fndgLog = logger

	case "HSWC":
		hswcLog = logger
		htlcswitch.UseLogger(logger)

	case "UTXN":
		utxnLog = logger

	case "BRAR":
		brarLog = logger

	case "CMGR":
		cmgrLog = logger
		connmgr.UseLogger(logger)

	case "CRTR":
		crtrLog = logger
		routing.UseLogger(crtrLog)

	case "BTCN":
		btcnLog = logger
		neutrino.UseLogger(logger)
	}
}

// initSeelogLogger initializes a new seelog logger that is used as the backend
// for all logging subsystems.
func initSeelogLogger(logFile string) {
	config := `
	<seelog type="adaptive" mininterval="2000000" maxinterval="100000000"
		critmsgcount="500" minlevel="trace">
		<outputs formatid="all">
			<console />
			<rollingfile type="size" filename="%s" maxsize="10485760" maxrolls="3" />
		</outputs>
		<formats>
			<format id="all" format="%%Time %%Date [%%LEV] %%Msg%%n" />
		</formats>
	</seelog>`
	config = fmt.Sprintf(config, logFile)

	logger, err := seelog.LoggerFromConfigAsString(config)
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to create logger: %v", err)
		os.Exit(1)
	}

	backendLog = logger
}

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

	// Default to info if the log level is invalid.
	level, ok := btclog.LogLevelFromString(logLevel)
	if !ok {
		level = btclog.InfoLvl
	}

	// Create new logger for the subsystem if needed.
	if logger == btclog.Disabled {
		logger = btclog.NewSubsystemLogger(backendLog, subsystemID+": ")
		useLogger(subsystemID, logger)
	}
	logger.SetLevel(level)
}

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

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

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

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


<commit_before>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package ptypes

// IntWeight returns number of bits set to 1 in x.
func IntWeight(x uint64) (w int) {
	for x > 0 {
		w++
		x &= (x - 1)
	}
	return w
}

// ClosestInt returns integer closest to x with the same weight.
func ClosestInt(x uint64) (ci uint64, ok bool) {
	for i := uint(0); i < 63; i++ {
		if (x>>i)&1 != (x >> (i + 1) & 1) {
			x ^= 1<<i | 1<<(i+1)
			return x, true
		}
	}
	return 0, false // If all bits are 0 or 1.
}
<commit_msg>Add time/space compexity analysis for ptypes.ClosestInt function<commit_after>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package ptypes

// IntWeight returns number of bits set to 1 in x.
func IntWeight(x uint64) (w int) {
	for x > 0 {
		w++
		x &= (x - 1)
	}
	return w
}

// ClosestInt returns integer closest to x with the same weight.
// The time complexity is O(n), where n is the integer width.
// The O(1) additional space is needed.
func ClosestInt(x uint64) (ci uint64, ok bool) {
	for i := uint(0); i < 63; i++ {
		if (x>>i)&1 != x>>(i+1)&1 {
			x ^= 1<<i | 1<<(i+1)
			return x, true
		}
	}
	return 0, false // If all bits are 0 or 1.
}
<|endoftext|>