<commit_before>package pqueue

import (
	"firempq/common"
	"firempq/db"
	"firempq/log"
	"firempq/testutils"
	"testing"

	. "firempq/testutils"

	"time"

	. "github.com/smartystreets/goconvey/convey"
)

func CreateTestQueue() *PQueue {
	log.InitLogging()
	log.SetLevel(1)
	db.SetDatabase(testutils.NewInMemDBService())
	desc := common.NewServiceDescription(common.STYPE_PRIORITY_QUEUE, 54634673456, "name")
	return NewPQueue(desc, 100, 1000)
}

func cmp(t *testing.T, a, b string) {
	if a != b {
		t.Error("Unexpected value '" + a + "'. Expecting: '" + b + "'")
	}
}

func TestPushPopAndTimeUnlockItems(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Test push and pop messages", t, func() {
		q.Push("data1", "p1", 10000, 0, 12)
		q.Push("data2", "p2", 10000, 0, 12)
		VerifyServiceSize(q, 2)
		VerifyItems(q.Pop(10000, 0, 10, true), 2, "data1", "p1", "data2", "p2")
		VerifyServiceSize(q, 2)

		// Unlock item data1 it should become available again.
		q.UpdateLock("data1", 0)
		q.update(common.Uts() + 110)
		VerifySingleItem(q.Pop(10000, 0, 1, true), "data1", "p1")
		VerifyServiceSize(q, 2)

		q.DeleteLockedById("data1")
		VerifyServiceSize(q, 1)
		q.DeleteLockedById("data2")
		VerifyServiceSize(q, 0)
	})
}

func TestAutoExpiration(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Two messages should expire, one message should still be in the queue", t, func() {
		q.Push("data1", "p1", 1000, 0, 12)
		q.Push("data2", "p2", 1000, 0, 12)
		q.Push("data3", "p3", 10000, 0, 12)
		VerifyServiceSize(q, 3)
		q.update(common.Uts() + 1300)
		VerifyServiceSize(q, 1)
	})
}

func TestUnlockById(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Locked message should become visible again after it gets unlocked", t, func() {
		q.Push("data1", "p1", 1000, 0, 12)
		q.Push("data2", "p2", 1000, 0, 12)
		VerifyItems(q.Pop(10000, 0, 10, true), 2, "data1", "p1", "data2", "p2")
		VerifyItems(q.Pop(10000, 0, 10, true), 0)
		q.UnlockMessageById("data2")
		VerifyItems(q.Pop(10000, 0, 10, true), 1, "data2", "p2")
	})
}

func TestDeleteById(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Delete not locked message", t, func() {
		q.Push("data1", "p1", 1000, 0, 12)
		VerifyServiceSize(q, 1)
		q.DeleteById("data1")
		VerifyServiceSize(q, 0)
		VerifyItems(q.Pop(10000, 0, 10, true), 0)
	})
}

func TestDeleteLockedById(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Locked message should be removed", t, func() {
		q.Push("data1", "p1", 10000, 0, 12)
		q.Push("data2", "p2", 10000, 0, 12)
		VerifyItems(q.Pop(10000, 0, 10, true), 2, "data1", "p1", "data2", "p2")
		q.DeleteLockedById("data1")
		q.DeleteLockedById("data2")
		VerifyServiceSize(q, 0)
	})
}

func TestPopWaitBatch(t *testing.T) {
	q := CreateTestQueue()
	go func() {
		time.Sleep(time.Second / 10)
		q.Push("d1", "1", 10000, 0, 12)
		q.Push("d2", "2", 10000, 0, 12)
		q.Push("d3", "3", 10000, 0, 12)
	}()
	Convey("Messages should be delivered after 0.1 seconds", t, func() {
		VerifyItems(q.Pop(10000, 1000, 10, true), 3, "d1", "1", "d2", "2", "d3", "3")
	})
}

func TestDeliveryDelay(t *testing.T) {
	q := CreateTestQueue()
	q.StartUpdate()
	Convey("Message delivery delay should be delayed at least for 0.1 seconds", t, func() {
		q.Push("data1", "p1", 10000, 120, 12)
		startTs := time.Now().Nanosecond()
		VerifyItems(q.Pop(10000, 1000, 10, true), 1, "data1", "p1")
		finishTs := time.Now().Nanosecond()
		So(finishTs-startTs, ShouldBeGreaterThan, time.Second/10)
	})
	q.Close()
}
<commit_msg>One more intense unit test for pqueue.<commit_after>package pqueue

import (
	"firempq/common"
	"firempq/db"
	"firempq/log"
	"firempq/testutils"
	"testing"

	. "firempq/testutils"

	"time"

	. "github.com/smartystreets/goconvey/convey"
)

func CreateTestQueue() *PQueue {
	log.InitLogging()
	log.SetLevel(1)
	db.SetDatabase(testutils.NewInMemDBService())
	desc := common.NewServiceDescription(common.STYPE_PRIORITY_QUEUE, 54634673456, "name")
	return NewPQueue(desc, 100, 1000)
}

func cmp(t *testing.T, a, b string) {
	if a != b {
		t.Error("Unexpected value '" + a + "'. Expecting: '" + b + "'")
	}
}

func TestPushPopAndTimeUnlockItems(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Test push and pop messages", t, func() {
		q.Push("data1", "p1", 10000, 0, 12)
		q.Push("data2", "p2", 10000, 0, 12)
		VerifyServiceSize(q, 2)
		VerifyItems(q.Pop(10000, 0, 10, true), 2, "data1", "p1", "data2", "p2")
		VerifyServiceSize(q, 2)

		// Unlock item data1 it should become available again.
		q.UpdateLock("data1", 0)
		q.update(common.Uts() + 110)
		VerifySingleItem(q.Pop(10000, 0, 1, true), "data1", "p1")
		VerifyServiceSize(q, 2)

		q.DeleteLockedById("data1")
		VerifyServiceSize(q, 1)
		q.DeleteLockedById("data2")
		VerifyServiceSize(q, 0)
	})
}

func TestAutoExpiration(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Two messages should expire, one message should still be in the queue", t, func() {
		q.Push("data1", "p1", 1000, 0, 12)
		q.Push("data2", "p2", 1000, 0, 12)
		q.Push("data3", "p3", 10000, 0, 12)
		VerifyServiceSize(q, 3)
		q.update(common.Uts() + 1300)
		VerifyServiceSize(q, 1)
	})
}

func TestUnlockById(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Locked message should become visible again after it gets unlocked", t, func() {
		q.Push("data1", "p1", 1000, 0, 12)
		q.Push("data2", "p2", 1000, 0, 12)
		VerifyItems(q.Pop(10000, 0, 10, true), 2, "data1", "p1", "data2", "p2")
		VerifyItems(q.Pop(10000, 0, 10, true), 0)
		q.UnlockMessageById("data2")
		VerifyItems(q.Pop(10000, 0, 10, true), 1, "data2", "p2")
	})
}

func TestDeleteById(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Delete not locked message", t, func() {
		q.Push("data1", "p1", 1000, 0, 12)
		VerifyServiceSize(q, 1)
		q.DeleteById("data1")
		VerifyServiceSize(q, 0)
		VerifyItems(q.Pop(10000, 0, 10, true), 0)
	})
}

func TestDeleteLockedById(t *testing.T) {
	q := CreateTestQueue()
	defer q.Clear()
	Convey("Locked message should be removed", t, func() {
		q.Push("data1", "p1", 10000, 0, 12)
		q.Push("data2", "p2", 10000, 0, 12)
		VerifyItems(q.Pop(10000, 0, 10, true), 2, "data1", "p1", "data2", "p2")
		q.DeleteLockedById("data1")
		q.DeleteLockedById("data2")
		VerifyServiceSize(q, 0)
	})
}

func TestPopWaitBatch(t *testing.T) {
	q := CreateTestQueue()
	go func() {
		time.Sleep(time.Second / 10)
		q.Push("d1", "1", 10000, 0, 12)
		q.Push("d2", "2", 10000, 0, 12)
		q.Push("d3", "3", 10000, 0, 12)
	}()
	Convey("Messages should be delivered after 0.1 seconds", t, func() {
		VerifyItems(q.Pop(10000, 1000, 10, true), 3, "d1", "1", "d2", "2", "d3", "3")
	})
}

func TestDeliveryDelay(t *testing.T) {
	q := CreateTestQueue()
	q.StartUpdate()
	Convey("Message delivery delay should be delayed at least for 0.1 seconds", t, func() {
		q.Push("data1", "p1", 10000, 120, 12)
		startTs := time.Now().UnixNano()
		VerifyItems(q.Pop(10000, 1000, 10, true), 1, "data1", "p1")
		finishTs := time.Now().UnixNano()
		So(finishTs-startTs, ShouldBeGreaterThan, time.Second/10)
	})
	q.Close()
}

func TestPushLotsOfMessages(t *testing.T) {
	q := CreateTestQueue()
	q.StartUpdate()
	totalMsg := 10000
	Convey("10k messages should be pushed and received", t, func() {
		for i := 0; i < totalMsg; i++ {
			q.Push("", " ", 100000, 0, 10)
		}
		counter := 0
		loops := 0
		for counter < totalMsg && loops < totalMsg {
			resp, ok := q.Pop(0, 10, 10, false).(*common.ItemsResponse)
			if !ok {
				break
			}
			counter += len(resp.GetItems())
		}
		So(counter, ShouldEqual, totalMsg)

	})
	q.Close()
}
<|endoftext|>


<commit_before>package g

import (
	"log"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/CMGS/consistent"
	"github.com/open-falcon/common/model"
	"github.com/toolkits/net"
	"github.com/toolkits/slice"
)

var Root string

func InitRootDir() {
	var err error
	Root, err = os.Getwd()
	if err != nil {
		log.Fatalln("getwd fail:", err)
	}
}

var LocalIps []string

func InitLocalIps() {
	var err error
	LocalIps, err = net.IntranetIP()
	if err != nil {
		log.Fatalln("get intranet ip fail:", err)
	}
}

var (
	HbsClient       *SingleConnRpcClient
	Transfers       *consistent.Consistent
	TransferClients map[string]*SingleConnRpcClient = map[string]*SingleConnRpcClient{}
)

func InitRpcClients() {
	if Config().Heartbeat.Enabled {
		HbsClient = &SingleConnRpcClient{
			RpcServer: Config().Heartbeat.Addr,
			Timeout:   time.Duration(Config().Heartbeat.Timeout) * time.Millisecond,
		}
	}

	if Config().Transfer.Enabled {
		Transfers = consistent.New()
		for _, transfer := range Config().Transfer.Addrs {
			Transfers.Add(transfer)
		}
	}
}

func SendToTransfer(metrics []*model.MetricValue) {
	if len(metrics) == 0 {
		return
	}

	debug := Config().Debug

	if debug {
		log.Printf("=> <Total=%d> %v\n", len(metrics), metrics[0])
	}

	var resp model.TransferResponse
	for offset := 0; offset < Transfers.Len(); offset++ {
		addr, _ := Transfers.Get(metrics[0].Endpoint, offset)
		if _, ok := TransferClients[addr]; !ok {
			TransferClients[addr] = &SingleConnRpcClient{
				RpcServer: addr,
				Timeout:   time.Duration(Config().Transfer.Timeout) * time.Millisecond,
			}
		}
		err := TransferClients[addr].Call("Transfer.Update", metrics, &resp)
		if err == nil {
			break
		}
		delete(TransferClients, addr)
		log.Println("call Transfer.Update fail", err)
	}

	if debug {
		log.Println("<=", &resp)
	}
}

var (
	reportUrls     map[string]string
	reportUrlsLock = new(sync.RWMutex)
)

func ReportUrls() map[string]string {
	reportUrlsLock.RLock()
	defer reportUrlsLock.RUnlock()
	return reportUrls
}

func SetReportUrls(urls map[string]string) {
	reportUrlsLock.RLock()
	defer reportUrlsLock.RUnlock()
	reportUrls = urls
}

var (
	reportPorts     []int64
	reportPortsLock = new(sync.RWMutex)
)

func ReportPorts() []int64 {
	reportPortsLock.RLock()
	defer reportPortsLock.RUnlock()
	return reportPorts
}

func SetReportPorts(ports []int64) {
	reportPortsLock.Lock()
	defer reportPortsLock.Unlock()
	reportPorts = ports
}

var (
	duPaths     []string
	duPathsLock = new(sync.RWMutex)
)

func DuPaths() []string {
	duPathsLock.RLock()
	defer duPathsLock.RUnlock()
	return duPaths
}

func SetDuPaths(paths []string) {
	duPathsLock.Lock()
	defer duPathsLock.Unlock()
	duPaths = paths
}

var (
	// tags => {1=>name, 2=>cmdline}
	// e.g. 'name=falcon-agent'=>{1=>falcon-agent}
	// e.g. 'cmdline=xx'=>{2=>xx}
	reportProcs     map[string]map[int]string
	reportProcsLock = new(sync.RWMutex)
)

func ReportProcs() map[string]map[int]string {
	reportProcsLock.RLock()
	defer reportProcsLock.RUnlock()
	return reportProcs
}

func SetReportProcs(procs map[string]map[int]string) {
	reportProcsLock.Lock()
	defer reportProcsLock.Unlock()
	reportProcs = procs
}

var (
	ips     []string
	ipsLock = new(sync.Mutex)
)

func TrustableIps() []string {
	ipsLock.Lock()
	defer ipsLock.Unlock()
	return ips
}

func SetTrustableIps(ipStr string) {
	arr := strings.Split(ipStr, ",")
	ipsLock.Lock()
	defer ipsLock.Unlock()
	ips = arr
}

func IsTrustable(remoteAddr string) bool {
	ip := remoteAddr
	idx := strings.LastIndex(remoteAddr, ":")
	if idx > 0 {
		ip = remoteAddr[0:idx]
	}

	if ip == "127.0.0.1" {
		return true
	}

	return slice.ContainsString(TrustableIps(), ip)
}
<commit_msg>output failed transfer addr<commit_after>package g

import (
	"log"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/CMGS/consistent"
	"github.com/open-falcon/common/model"
	"github.com/toolkits/net"
	"github.com/toolkits/slice"
)

var Root string

func InitRootDir() {
	var err error
	Root, err = os.Getwd()
	if err != nil {
		log.Fatalln("getwd fail:", err)
	}
}

var LocalIps []string

func InitLocalIps() {
	var err error
	LocalIps, err = net.IntranetIP()
	if err != nil {
		log.Fatalln("get intranet ip fail:", err)
	}
}

var (
	HbsClient       *SingleConnRpcClient
	Transfers       *consistent.Consistent
	TransferClients map[string]*SingleConnRpcClient = map[string]*SingleConnRpcClient{}
)

func InitRpcClients() {
	if Config().Heartbeat.Enabled {
		HbsClient = &SingleConnRpcClient{
			RpcServer: Config().Heartbeat.Addr,
			Timeout:   time.Duration(Config().Heartbeat.Timeout) * time.Millisecond,
		}
	}

	if Config().Transfer.Enabled {
		Transfers = consistent.New()
		for _, transfer := range Config().Transfer.Addrs {
			Transfers.Add(transfer)
		}
	}
}

func SendToTransfer(metrics []*model.MetricValue) {
	if len(metrics) == 0 {
		return
	}

	debug := Config().Debug

	if debug {
		log.Printf("=> <Total=%d> %v\n", len(metrics), metrics[0])
	}

	var resp model.TransferResponse
	for offset := 0; offset < Transfers.Len(); offset++ {
		addr, _ := Transfers.Get(metrics[0].Endpoint, offset)
		if _, ok := TransferClients[addr]; !ok {
			TransferClients[addr] = &SingleConnRpcClient{
				RpcServer: addr,
				Timeout:   time.Duration(Config().Transfer.Timeout) * time.Millisecond,
			}
		}
		err := TransferClients[addr].Call("Transfer.Update", metrics, &resp)
		if err == nil {
			break
		}
		delete(TransferClients, addr)
		log.Println("call Transfer.Update fail", addr, err)
	}

	if debug {
		log.Println("<=", &resp)
	}
}

var (
	reportUrls     map[string]string
	reportUrlsLock = new(sync.RWMutex)
)

func ReportUrls() map[string]string {
	reportUrlsLock.RLock()
	defer reportUrlsLock.RUnlock()
	return reportUrls
}

func SetReportUrls(urls map[string]string) {
	reportUrlsLock.RLock()
	defer reportUrlsLock.RUnlock()
	reportUrls = urls
}

var (
	reportPorts     []int64
	reportPortsLock = new(sync.RWMutex)
)

func ReportPorts() []int64 {
	reportPortsLock.RLock()
	defer reportPortsLock.RUnlock()
	return reportPorts
}

func SetReportPorts(ports []int64) {
	reportPortsLock.Lock()
	defer reportPortsLock.Unlock()
	reportPorts = ports
}

var (
	duPaths     []string
	duPathsLock = new(sync.RWMutex)
)

func DuPaths() []string {
	duPathsLock.RLock()
	defer duPathsLock.RUnlock()
	return duPaths
}

func SetDuPaths(paths []string) {
	duPathsLock.Lock()
	defer duPathsLock.Unlock()
	duPaths = paths
}

var (
	// tags => {1=>name, 2=>cmdline}
	// e.g. 'name=falcon-agent'=>{1=>falcon-agent}
	// e.g. 'cmdline=xx'=>{2=>xx}
	reportProcs     map[string]map[int]string
	reportProcsLock = new(sync.RWMutex)
)

func ReportProcs() map[string]map[int]string {
	reportProcsLock.RLock()
	defer reportProcsLock.RUnlock()
	return reportProcs
}

func SetReportProcs(procs map[string]map[int]string) {
	reportProcsLock.Lock()
	defer reportProcsLock.Unlock()
	reportProcs = procs
}

var (
	ips     []string
	ipsLock = new(sync.Mutex)
)

func TrustableIps() []string {
	ipsLock.Lock()
	defer ipsLock.Unlock()
	return ips
}

func SetTrustableIps(ipStr string) {
	arr := strings.Split(ipStr, ",")
	ipsLock.Lock()
	defer ipsLock.Unlock()
	ips = arr
}

func IsTrustable(remoteAddr string) bool {
	ip := remoteAddr
	idx := strings.LastIndex(remoteAddr, ":")
	if idx > 0 {
		ip = remoteAddr[0:idx]
	}

	if ip == "127.0.0.1" {
		return true
	}

	return slice.ContainsString(TrustableIps(), ip)
}
<|endoftext|>


<commit_before>package ga

import (
	"log"
	"math"
	"math/rand"
	"sort"
	"strconv"
	"strings"
	"time"

	server "github.com/sunfish-shogi/sunfish4-ga/shogiserver"
)

type GAManager struct {
	Config Config

	server   server.ShogiServer
	indMap   map[string]*individual
	normal   *individual
	allInds  []*individual
	currInds []*individual
}

func NewGAManager(config Config) *GAManager {
	validateConfig(config)
	return &GAManager{
		Config:  config,
		indMap:  make(map[string]*individual),
		allInds: make([]*individual, 0, 1024),
	}
}

func (ga *GAManager) Run() error {
	defer ga.Destroy()

	err := ga.Start()
	if err != nil {
		return err
	}

	for gn := 1; ; gn++ {
		ga.PrintGeneration(gn)

		time.Sleep(ga.Config.Duration)

		err = ga.Next()
		if err != nil {
			log.Println(err)
		}
	}
}

func (ga *GAManager) Start() error {
	err := ga.server.Setup()
	if err != nil {
		return err
	}

	var ok bool
	ga.normal, ok = ga.newIndividual(generateNormalValues(ga.Config), "normal")
	if !ok {
		log.Fatal("fatal error: failed to generate normal player")
	}

	ga.currInds = make([]*individual, 0, ga.Config.NumberOfIndividual)
	for len(ga.currInds) < ga.Config.NumberOfIndividual {
		ind, ok := ga.newIndividual(generateRandomValues(ga.Config), "")
		if ok {
			ga.currInds = append(ga.currInds, ind)
		}
	}

	err = startIndividuals(append(ga.currInds, ga.normal))
	return err
}

type indsDescLowerScoreOrder []*individual

func (inds indsDescLowerScoreOrder) Len() int      { return len(inds) }
func (inds indsDescLowerScoreOrder) Swap(i, j int) { inds[i], inds[j] = inds[j], inds[i] }
func (inds indsDescLowerScoreOrder) Less(i, j int) bool {
	return inds[i].scoreLower > inds[j].scoreLower
}

type indsDescScoreOrder []*individual

func (inds indsDescScoreOrder) Len() int           { return len(inds) }
func (inds indsDescScoreOrder) Swap(i, j int)      { inds[i], inds[j] = inds[j], inds[i] }
func (inds indsDescScoreOrder) Less(i, j int) bool { return inds[i].score > inds[j].score }

func (ga *GAManager) Next() error {
	rate, err := ga.server.MakeRate()
	if err != nil {
		return err
	}

	for _, ind := range ga.indMap {
		ind.score = 0
	}
	for pi := range rate.Players {
		for _, player := range rate.Players[pi] {
			if ind, ok := ga.indMap[player.Name]; ok {
				ind.score = player.Rate
				ci := confidenceInterval95(player.Win, player.Loss)
				ind.scoreLower = player.Rate - ci
				ind.scoreUpper = player.Rate + ci
			}
		}
	}
	for _, ind := range ga.indMap {
		if ind.id != ga.normal.id {
			ind.score -= ga.normal.score
		}
	}

	// Sort by Score
	sort.Stable(indsDescLowerScoreOrder(ga.allInds))
	sort.Stable(indsDescScoreOrder(ga.currInds))

	// Print Scores
	log.Println("Score")
	for i := range ga.currInds {
		log.Printf("%s %0.3f [%0.3f, %0.3f]", ga.currInds[i].id, ga.currInds[i].score, ga.currInds[i].scoreLower, ga.currInds[i].scoreUpper)
	}
	log.Println()

	// New Generation
	inds := make([]*individual, 0, ga.Config.NumberOfIndividual)

	// Elitism
	log.Printf("elite: %s", ga.allInds[0].id)
	inds = append(inds, ga.allInds[0])

	i := 0
	if ga.currInds[i].id == ga.allInds[0].id {
		i++
	}
	log.Printf("elite: %s", ga.currInds[i].id)
	inds = append(inds, ga.currInds[i])

	// Random
	numberOfRandomPlayers := ga.Config.NumberOfIndividual / 4
	for i := 0; i < numberOfRandomPlayers; {
		ind, ok := ga.newIndividual(generateRandomValues(ga.Config), "")
		if ok {
			log.Printf("random: => %s", ind.id)
			inds = append(inds, ind)
			i++
		}
	}

	for {
		if len(inds) >= ga.Config.NumberOfIndividual {
			break
		}

		i1 := ga.selectIndividual("")
		i2 := ga.selectIndividual(i1.id)

		ind, ok := ga.crossover(i1, i2)
		if ok {
			log.Printf("crossover: %s x %s => %s", i1.id, i2.id, ind.id)

			if rand.Intn(8) < 1 /* 1/8 */ {
				ga.mutate(ind)
				log.Printf("mutate: %s", ind.id)
			}

			inds = append(inds, ind)
			continue
		}

		ind, ok = ga.newIndividual(generateRandomValues(ga.Config), "")
		if ok {
			log.Printf("random: => %s", ind.id)
			inds = append(inds, ind)
		}
	}
	log.Println()

	// Stop Previous Generation
	stopIndividuals(ga.currInds)

	// Replace to New Generation
	ga.currInds = inds

	// Start Next Generation
	startIndividuals(ga.currInds)

	return nil
}

func (ga *GAManager) selectIndividual(excludeID string) *individual {
	weight := make([]int, len(ga.currInds))
	var sum int
	for i := range weight {
		if ga.currInds[i].id != excludeID {
			if i == 0 {
				weight[0] = 1024
			} else {
				weight[i] = weight[i-1]*9/10 + 1
			}
			sum += weight[i]
		}
	}

	r := rand.Intn(sum)

	for i := range weight {
		r -= weight[i]
		if r <= 0 {
			return ga.currInds[i]
		}
	}
	return ga.currInds[0]
}

func (ga *GAManager) crossover(i1, i2 *individual) (*individual, bool) {
	values := make([]int32, len(ga.Config.Params))
	for i := range values {
		if rand.Intn(2) == 0 {
			values[i] = i1.values[i]
		} else {
			values[i] = i2.values[i]
		}
	}
	return ga.newIndividual(values, "")
}

func (ga *GAManager) mutate(ind *individual) {
	n := rand.Intn(2) + 1
	for ; n > 0; n-- {
		i := rand.Intn(len(ind.values))
		min := ga.Config.Params[i].MinimumValue
		max := ga.Config.Params[i].MaximumValue
		t := min + rand.Int31n(max-min+1)
		ind.values[i] = t
	}
}

func (ga *GAManager) PrintGeneration(gn int) {
	log.Printf("Generation: %d\n", gn)
	for i := range ga.currInds {
		ss := make([]string, len(ga.currInds[i].values))
		for vi, v := range ga.currInds[i].values {
			ss[vi] = strconv.Itoa(int(v))
		}
		log.Printf("%s [%s]\n", ga.currInds[i].id, strings.Join(ss, ","))
	}
	log.Println()
}

func (ga *GAManager) Destroy() {
	ga.normal.stopWithClean()
	for i := range ga.currInds {
		ga.currInds[i].stopWithClean()
	}
	ga.server.Stop()
}

func (ga *GAManager) newIndividual(values []int32, customID string) (*individual, bool) {
	ind := newIndividual(ga.Config, values, customID)

	if _, exists := ga.indMap[ind.id]; exists {
		return nil, false
	}

	ga.indMap[ind.id] = ind
	if customID == "" {
		ga.allInds = append(ga.allInds, ind)
	}
	return ind, true
}

func confidenceInterval95(win, loss float64) float64 {
	if win == 0 || loss == 0 {
		return 0
	}

	n := win + loss
	q := win / n

	if n <= 1 {
		return 0
	}

	// standard deviation
	a := n / (n - 1)
	sd := 173.7 * a / math.Sqrt(n*q*(1-q))

	// 95% confidence interval
	return sd * 2
}
<commit_msg>Fix lower/upper score<commit_after>package ga

import (
	"log"
	"math"
	"math/rand"
	"sort"
	"strconv"
	"strings"
	"time"

	server "github.com/sunfish-shogi/sunfish4-ga/shogiserver"
)

type GAManager struct {
	Config Config

	server   server.ShogiServer
	indMap   map[string]*individual
	normal   *individual
	allInds  []*individual
	currInds []*individual
}

func NewGAManager(config Config) *GAManager {
	validateConfig(config)
	return &GAManager{
		Config:  config,
		indMap:  make(map[string]*individual),
		allInds: make([]*individual, 0, 1024),
	}
}

func (ga *GAManager) Run() error {
	defer ga.Destroy()

	err := ga.Start()
	if err != nil {
		return err
	}

	for gn := 1; ; gn++ {
		ga.PrintGeneration(gn)

		time.Sleep(ga.Config.Duration)

		err = ga.Next()
		if err != nil {
			log.Println(err)
		}
	}
}

func (ga *GAManager) Start() error {
	err := ga.server.Setup()
	if err != nil {
		return err
	}

	var ok bool
	ga.normal, ok = ga.newIndividual(generateNormalValues(ga.Config), "normal")
	if !ok {
		log.Fatal("fatal error: failed to generate normal player")
	}

	ga.currInds = make([]*individual, 0, ga.Config.NumberOfIndividual)
	for len(ga.currInds) < ga.Config.NumberOfIndividual {
		ind, ok := ga.newIndividual(generateRandomValues(ga.Config), "")
		if ok {
			ga.currInds = append(ga.currInds, ind)
		}
	}

	err = startIndividuals(append(ga.currInds, ga.normal))
	return err
}

type indsDescLowerScoreOrder []*individual

func (inds indsDescLowerScoreOrder) Len() int      { return len(inds) }
func (inds indsDescLowerScoreOrder) Swap(i, j int) { inds[i], inds[j] = inds[j], inds[i] }
func (inds indsDescLowerScoreOrder) Less(i, j int) bool {
	return inds[i].scoreLower > inds[j].scoreLower
}

type indsDescScoreOrder []*individual

func (inds indsDescScoreOrder) Len() int           { return len(inds) }
func (inds indsDescScoreOrder) Swap(i, j int)      { inds[i], inds[j] = inds[j], inds[i] }
func (inds indsDescScoreOrder) Less(i, j int) bool { return inds[i].score > inds[j].score }

func (ga *GAManager) Next() error {
	rate, err := ga.server.MakeRate()
	if err != nil {
		return err
	}

	for _, ind := range ga.indMap {
		ind.score = 0
	}
	for pi := range rate.Players {
		for _, player := range rate.Players[pi] {
			if ind, ok := ga.indMap[player.Name]; ok {
				ind.score = player.Rate
				ci := confidenceInterval95(player.Win, player.Loss)
				ind.scoreLower = player.Rate - ci
				ind.scoreUpper = player.Rate + ci
			}
		}
	}
	for _, ind := range ga.indMap {
		if ind.id != ga.normal.id {
			ind.score -= ga.normal.score
			ind.scoreLower -= ga.normal.score
			ind.scoreUpper -= ga.normal.score
		}
	}

	// Sort by Score
	sort.Stable(indsDescLowerScoreOrder(ga.allInds))
	sort.Stable(indsDescScoreOrder(ga.currInds))

	// Print Scores
	log.Println("Score")
	for i := range ga.currInds {
		log.Printf("%s %0.3f [%0.3f, %0.3f]", ga.currInds[i].id, ga.currInds[i].score, ga.currInds[i].scoreLower, ga.currInds[i].scoreUpper)
	}
	log.Println()

	// New Generation
	inds := make([]*individual, 0, ga.Config.NumberOfIndividual)

	// Elitism
	log.Printf("elite: %s", ga.allInds[0].id)
	inds = append(inds, ga.allInds[0])

	i := 0
	if ga.currInds[i].id == ga.allInds[0].id {
		i++
	}
	log.Printf("elite: %s", ga.currInds[i].id)
	inds = append(inds, ga.currInds[i])

	// Random
	numberOfRandomPlayers := ga.Config.NumberOfIndividual / 4
	for i := 0; i < numberOfRandomPlayers; {
		ind, ok := ga.newIndividual(generateRandomValues(ga.Config), "")
		if ok {
			log.Printf("random: => %s", ind.id)
			inds = append(inds, ind)
			i++
		}
	}

	for {
		if len(inds) >= ga.Config.NumberOfIndividual {
			break
		}

		i1 := ga.selectIndividual("")
		i2 := ga.selectIndividual(i1.id)

		ind, ok := ga.crossover(i1, i2)
		if ok {
			log.Printf("crossover: %s x %s => %s", i1.id, i2.id, ind.id)

			if rand.Intn(8) < 1 /* 1/8 */ {
				ga.mutate(ind)
				log.Printf("mutate: %s", ind.id)
			}

			inds = append(inds, ind)
			continue
		}

		ind, ok = ga.newIndividual(generateRandomValues(ga.Config), "")
		if ok {
			log.Printf("random: => %s", ind.id)
			inds = append(inds, ind)
		}
	}
	log.Println()

	// Stop Previous Generation
	stopIndividuals(ga.currInds)

	// Replace to New Generation
	ga.currInds = inds

	// Start Next Generation
	startIndividuals(ga.currInds)

	return nil
}

func (ga *GAManager) selectIndividual(excludeID string) *individual {
	weight := make([]int, len(ga.currInds))
	var sum int
	for i := range weight {
		if ga.currInds[i].id != excludeID {
			if i == 0 {
				weight[0] = 1024
			} else {
				weight[i] = weight[i-1]*9/10 + 1
			}
			sum += weight[i]
		}
	}

	r := rand.Intn(sum)

	for i := range weight {
		r -= weight[i]
		if r <= 0 {
			return ga.currInds[i]
		}
	}
	return ga.currInds[0]
}

func (ga *GAManager) crossover(i1, i2 *individual) (*individual, bool) {
	values := make([]int32, len(ga.Config.Params))
	for i := range values {
		if rand.Intn(2) == 0 {
			values[i] = i1.values[i]
		} else {
			values[i] = i2.values[i]
		}
	}
	return ga.newIndividual(values, "")
}

func (ga *GAManager) mutate(ind *individual) {
	n := rand.Intn(2) + 1
	for ; n > 0; n-- {
		i := rand.Intn(len(ind.values))
		min := ga.Config.Params[i].MinimumValue
		max := ga.Config.Params[i].MaximumValue
		t := min + rand.Int31n(max-min+1)
		ind.values[i] = t
	}
}

func (ga *GAManager) PrintGeneration(gn int) {
	log.Printf("Generation: %d\n", gn)
	for i := range ga.currInds {
		ss := make([]string, len(ga.currInds[i].values))
		for vi, v := range ga.currInds[i].values {
			ss[vi] = strconv.Itoa(int(v))
		}
		log.Printf("%s [%s]\n", ga.currInds[i].id, strings.Join(ss, ","))
	}
	log.Println()
}

func (ga *GAManager) Destroy() {
	ga.normal.stopWithClean()
	for i := range ga.currInds {
		ga.currInds[i].stopWithClean()
	}
	ga.server.Stop()
}

func (ga *GAManager) newIndividual(values []int32, customID string) (*individual, bool) {
	ind := newIndividual(ga.Config, values, customID)

	if _, exists := ga.indMap[ind.id]; exists {
		return nil, false
	}

	ga.indMap[ind.id] = ind
	if customID == "" {
		ga.allInds = append(ga.allInds, ind)
	}
	return ind, true
}

func confidenceInterval95(win, loss float64) float64 {
	if win == 0 || loss == 0 {
		return 0
	}

	n := win + loss
	q := win / n

	if n <= 1 {
		return 0
	}

	// standard deviation
	a := n / (n - 1)
	sd := 173.7 * a / math.Sqrt(n*q*(1-q))

	// 95% confidence interval
	return sd * 2
}
<|endoftext|>


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

package net

import (
	"net"

	"github.com/fatedier/frp/utils/log"
)

// Conn is the interface of connections used in frp.
type Conn interface {
	net.Conn
	log.Logger
}

type WrapLogConn struct {
	net.Conn
	log.Logger
}

func WrapConn(c net.Conn) Conn {
	return WrapLogConn{
		Conn:   c,
		Logger: log.NewPrefixLogger(""),
	}
}

type Listener interface {
	Accept() (Conn, error)
	Close() error
	log.Logger
}
<commit_msg>net: add WrapReadWriteCloserConn<commit_after>// Copyright 2016 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package net

import (
	"io"
	"net"
	"time"

	"github.com/fatedier/frp/utils/log"
)

// Conn is the interface of connections used in frp.
type Conn interface {
	net.Conn
	log.Logger
}

type WrapLogConn struct {
	net.Conn
	log.Logger
}

func WrapConn(c net.Conn) Conn {
	return &WrapLogConn{
		Conn:   c,
		Logger: log.NewPrefixLogger(""),
	}
}

type WrapReadWriteCloserConn struct {
	io.ReadWriteCloser
	log.Logger
}

func (conn *WrapReadWriteCloserConn) LocalAddr() net.Addr {
	return nil
}

func (conn *WrapReadWriteCloserConn) RemoteAddr() net.Addr {
	return nil
}

func (conn *WrapReadWriteCloserConn) SetDeadline(t time.Time) error {
	return nil
}

func (conn *WrapReadWriteCloserConn) SetReadDeadline(t time.Time) error {
	return nil
}

func (conn *WrapReadWriteCloserConn) SetWriteDeadline(t time.Time) error {
	return nil
}

func WrapReadWriteCloserToConn(rwc io.ReadWriteCloser) Conn {
	return &WrapReadWriteCloserConn{
		ReadWriteCloser: rwc,
		Logger:          log.NewPrefixLogger(""),
	}
}

type Listener interface {
	Accept() (Conn, error)
	Close() error
	log.Logger
}
<|endoftext|>


<commit_before>package clickhouse

import (
	"errors"
	"fmt"
	"strings"
)

type (
	Column  string
	Columns []string
	Row     []interface{}
	Rows    []Row
	Array   []interface{}
)

func NewHttpTransport() HttpTransport {
	return HttpTransport{}
}

func NewConn(host string, t Transport) *Conn {
	if strings.Index(host, "http://") < 0 && strings.Index(host, "https://") < 0 {
		host = "http://" + host
	}
	host = strings.TrimRight(host, "/") + "/"

	return &Conn{
		Host:      host,
		transport: t,
	}
}

func NewQuery(stmt string, args ...interface{}) Query {
	return Query{
		Stmt: stmt,
		args: args,
	}
}

func BuildInsert(tbl string, cols Columns, row Row) (Query, error) {
	return BuildMultiInsert(tbl, cols, Rows{row})
}

func BuildMultiInsert(tbl string, cols Columns, rows Rows) (Query, error) {
	var (
		stmt string
		args []interface{}
	)

	colCount := len(cols)
	rowCount := len(rows)
	args = make([]interface{}, colCount*rowCount)
	argi := 0
	for _, row := range rows {
		if len(row) != colCount {
			return Query{}, errors.New("Amount of row items does not match column count")
		}
		for _, val := range row {
			args[argi] = val
			argi++
		}
	}

	binds := strings.Repeat("?,", colCount)
	binds = "(" + binds[:len(binds)-1] + "),"
	batch := strings.Repeat(binds, rowCount)
	batch = batch[:len(batch)-1]

	stmt = fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", tbl, strings.Join(cols, ","), batch)

	return NewQuery(stmt, args...), nil
}
<commit_msg>Fix panic in helpers.go:71 if rows or cols is empty in multi insert<commit_after>package clickhouse

import (
	"errors"
	"fmt"
	"strings"
)

type (
	Column  string
	Columns []string
	Row     []interface{}
	Rows    []Row
	Array   []interface{}
)

func NewHttpTransport() HttpTransport {
	return HttpTransport{}
}

func NewConn(host string, t Transport) *Conn {
	if strings.Index(host, "http://") < 0 && strings.Index(host, "https://") < 0 {
		host = "http://" + host
	}
	host = strings.TrimRight(host, "/") + "/"

	return &Conn{
		Host:      host,
		transport: t,
	}
}

func NewQuery(stmt string, args ...interface{}) Query {
	return Query{
		Stmt: stmt,
		args: args,
	}
}

func BuildInsert(tbl string, cols Columns, row Row) (Query, error) {
	return BuildMultiInsert(tbl, cols, Rows{row})
}

func BuildMultiInsert(tbl string, cols Columns, rows Rows) (Query, error) {
	var (
		stmt string
		args []interface{}
	)

	if len(cols) == 0 || len(rows) == 0 {
		return Query{}, errors.New("Rows and Cols can't be empty")
	}

	colCount := len(cols)
	rowCount := len(rows)
	args = make([]interface{}, colCount*rowCount)
	argi := 0

	for _, row := range rows {
		if len(row) != colCount {
			return Query{}, errors.New("Amount of row items does not match column count")
		}
		for _, val := range row {
			args[argi] = val
			argi++
		}
	}

	binds := strings.Repeat("?,", colCount)
	binds = "(" + binds[:len(binds)-1] + "),"
	batch := strings.Repeat(binds, rowCount)
	batch = batch[:len(batch)-1]

	stmt = fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", tbl, strings.Join(cols, ","), batch)

	return NewQuery(stmt, args...), nil
}
<|endoftext|>


<commit_before>package main

import (
	"html"
	"log"
	"math/rand"
	"strconv"
	"time"
)

// Get the scores for a game.
func (g CAHGame) Scores() string {
	var str string = ""
	for _, value := range g.Players {
		str += value.Player.String() + " - " + strconv.Itoa(value.Points) + "\n"
	}
	return str
}

// Get the settings for a game.
func (gs GameSettings) String() string {
	var onOff string
	if gs.MysteryPlayer {
		onOff = "On"
	} else {
		onOff = "Off"
	}
	tmp := "Mystery Player - " + onOff + "\n"
	if gs.TradeInCardsEveryRound {
		onOff = "On"
	} else {
		onOff = "Off"
	}
	tmp += "Trade in 2 cards every round - " + onOff + "\n"
	if gs.PickWorstToo {
		onOff = "On"
	} else {
		onOff = "Off"
	}
	tmp += "Pick the worst answer also " + onOff + "\n"
	tmp += "Each player has " + strconv.Itoa(gs.NumCardsInHand) + " cards in their hand."
	return tmp + "\n\nUse command '/changesettings' to change these settings."
}

// Shuffle an array of strings.
func shuffle(arr []int) {
	t := time.Now()
	rand.Seed(int64(t.Nanosecond()))

	for i := len(arr) - 1; i > 0; i-- {
		j := rand.Intn(i)
		arr[i], arr[j] = arr[j], arr[i]
	}
}

// This function shuffles the answers so they don't come out in the same order every time.
func ShuffleAnswers(arr [][]string) {
	t := time.Now()
	rand.Seed(int64(t.Nanosecond()))

	for i := len(arr) - 1; i > 0; i-- {
		j := rand.Intn(i)
		arr[i], arr[j] = arr[j], arr[i]
	}
}

// This function checks to see if we have answer cards from all the players.
func DoWeHaveAllAnswers(Players map[string]PlayerGameInfo) bool {
	for _, value := range Players {
		if !value.IsCardTzar && value.AnswerBeingPlayed == "" {
			return false
		}
	}
	return true
}

// This function will deal a player's hand or add cards to the player's hand
func DealPlayerHand(Game CAHGame, Hand []int) []int {
	for len(Hand) < Game.Settings.NumCardsInHand {
		log.Printf("Dealing card %v to user.", Game.NumACardsLeft)
		Hand = append(Hand, Game.ShuffledAnswerCards[Game.NumACardsLeft])
		Game.NumACardsLeft -= 1
		if Game.NumACardsLeft == -1 {
			ReshuffleACards(Game)
		}
	}
	return Hand
}

//This function reshuffles the answer cards of a game.
func ReshuffleACards(Game CAHGame) {
	shuffle(Game.ShuffledAnswerCards)
	Game.NumACardsLeft = len(Game.ShuffledAnswerCards) - 1
}

//This function reshuffles the question cards of a game.
func ReshuffleQCards(Game CAHGame) {
	shuffle(Game.ShuffledQuestionCards)
	Game.NumQCardsLeft = len(Game.ShuffledQuestionCards) - 1
}

// This function goes through a game and determines if someone has won.
func DidSomeoneWin(Game CAHGame) (PlayerGameInfo, bool) {
	for _, value := range Game.Players {
		if value.Points == Game.Settings.NumPointsToWin {
			return value, true
		}
	}
	return PlayerGameInfo{}, false
}

// This function builds the list of submitted answers to be available for the players.
func BuildAnswerList(Game CAHGame) [][]string {
	answers := make([][]string, len(Game.Players))
	for i := range answers {
		answers[i] = make([]string, 1)
	}
	i := 0
	for _, value := range Game.Players {
		answers[i][0] = html.UnescapeString(value.AnswerBeingPlayed)
		i++
	}
	ShuffleAnswers(answers)
	return answers
}
<commit_msg>Better rand seed declaration<commit_after>package main

import (
	"html"
	"log"
	"math/rand"
	"strconv"
	"time"
)

// Get the scores for a game.
func (g CAHGame) Scores() string {
	var str string = ""
	for _, value := range g.Players {
		str += value.Player.String() + " - " + strconv.Itoa(value.Points) + "\n"
	}
	return str
}

// Get the settings for a game.
func (gs GameSettings) String() string {
	var onOff string
	if gs.MysteryPlayer {
		onOff = "On"
	} else {
		onOff = "Off"
	}
	tmp := "Mystery Player - " + onOff + "\n"
	if gs.TradeInCardsEveryRound {
		onOff = "On"
	} else {
		onOff = "Off"
	}
	tmp += "Trade in 2 cards every round - " + onOff + "\n"
	if gs.PickWorstToo {
		onOff = "On"
	} else {
		onOff = "Off"
	}
	tmp += "Pick the worst answer also " + onOff + "\n"
	tmp += "Each player has " + strconv.Itoa(gs.NumCardsInHand) + " cards in their hand."
	return tmp + "\n\nUse command '/changesettings' to change these settings."
}

// Shuffle an array of strings.
func shuffle(arr []int) {
	rand.Seed(time.Now().UnixNano())

	for i := len(arr) - 1; i > 0; i-- {
		j := rand.Intn(i)
		arr[i], arr[j] = arr[j], arr[i]
	}
}

// This function shuffles the answers so they don't come out in the same order every time.
func ShuffleAnswers(arr [][]string) {
	rand.Seed(time.Now().UnixNano())

	for i := len(arr) - 1; i > 0; i-- {
		j := rand.Intn(i)
		arr[i], arr[j] = arr[j], arr[i]
	}
}

// This function checks to see if we have answer cards from all the players.
func DoWeHaveAllAnswers(Players map[string]PlayerGameInfo) bool {
	for _, value := range Players {
		if !value.IsCardTzar && value.AnswerBeingPlayed == "" {
			return false
		}
	}
	return true
}

// This function will deal a player's hand or add cards to the player's hand
func DealPlayerHand(Game CAHGame, Hand []int) []int {
	for len(Hand) < Game.Settings.NumCardsInHand {
		log.Printf("Dealing card %v to user.", Game.NumACardsLeft)
		Hand = append(Hand, Game.ShuffledAnswerCards[Game.NumACardsLeft])
		Game.NumACardsLeft -= 1
		if Game.NumACardsLeft == -1 {
			ReshuffleACards(Game)
		}
	}
	return Hand
}

//This function reshuffles the answer cards of a game.
func ReshuffleACards(Game CAHGame) {
	shuffle(Game.ShuffledAnswerCards)
	Game.NumACardsLeft = len(Game.ShuffledAnswerCards) - 1
}

//This function reshuffles the question cards of a game.
func ReshuffleQCards(Game CAHGame) {
	shuffle(Game.ShuffledQuestionCards)
	Game.NumQCardsLeft = len(Game.ShuffledQuestionCards) - 1
}

// This function goes through a game and determines if someone has won.
func DidSomeoneWin(Game CAHGame) (PlayerGameInfo, bool) {
	for _, value := range Game.Players {
		if value.Points == Game.Settings.NumPointsToWin {
			return value, true
		}
	}
	return PlayerGameInfo{}, false
}

// This function builds the list of submitted answers to be available for the players.
func BuildAnswerList(Game CAHGame) [][]string {
	answers := make([][]string, len(Game.Players))
	for i := range answers {
		answers[i] = make([]string, 1)
	}
	i := 0
	for _, value := range Game.Players {
		answers[i][0] = html.UnescapeString(value.AnswerBeingPlayed)
		i++
	}
	ShuffleAnswers(answers)
	return answers
}
<|endoftext|>


<commit_before>package coretest

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

func CheckPort(network, address string, timeout time.Duration) error {
	errc := make(chan error, 1)
	go func() {
		_, err := net.Dial(network, address)
		errc <- err
	}()
	select {
	case <-time.After(timeout):
		return fmt.Errorf("%s:%s timed out after %s seconds.",
			network, address, timeout)
	case err := <-errc:
		if err != nil {
			return err
		}
	}
	return nil
}

func IsLink(f os.FileInfo) bool {
	return f.Mode()&os.ModeSymlink != 0
}
<commit_msg>Clean up<commit_after>package coretest

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

func CheckPort(network, address string, timeout time.Duration) error {
	errc := make(chan error, 1)
	go func() {
		_, err := net.Dial(network, address)
		errc <- err
	}()
	select {
	case <-time.After(timeout):
		return fmt.Errorf("%s:%s timed out after %s seconds.",
			network, address, timeout)
	case err := <-errc:
		return err
	}
}

func IsLink(f os.FileInfo) bool {
	return f.Mode()&os.ModeSymlink != 0
}
<|endoftext|>


<commit_before>package utils

import (
	"errors"
	"io/ioutil"
	"os"
	"path"
	"runtime"
)

var NonExistingTemplateError = errors.New("Template does not exist.")

func LoadTemplate(name string) ([]byte, error) {

	envPath := os.Getenv("APP_PATH")
	if envPath == "" {
		_, filename, _, ok := runtime.Caller(1)

		if !ok {
			return nil, errors.New("Could not find current path.")
		}
		envPath = path.Dir(filename) + "/../"
	}

	filepath := path.Join(envPath + "templates/" + name + ".json")
	file, err := ioutil.ReadFile(filepath)

	if err != nil {
		return nil, NonExistingTemplateError
	}

	return file, nil
}
<commit_msg>Template: nicer app path.<commit_after>package utils

import (
	"errors"
	"io/ioutil"
	"os"
	"path"
	"runtime"
)

var NonExistingTemplateError = errors.New("Template does not exist.")

func LoadTemplate(name string) ([]byte, error) {

	envPath := os.Getenv("APP_PATH")
	if envPath == "" {
		_, filename, _, ok := runtime.Caller(1)

		if !ok {
			return nil, errors.New("Could not find current path.")
		}
		envPath = path.Dir(filename) + "/.."
	}

	filepath := path.Join(envPath + "/templates/" + name + ".json")
	file, err := ioutil.ReadFile(filepath)

	if err != nil {
		return nil, NonExistingTemplateError
	}

	return file, nil
}
<|endoftext|>


<commit_before>package bundle_test

import (
	"io/ioutil"
	"os"
	"testing"

	"github.com/getantibody/antibody/bundle"
	"github.com/stretchr/testify/assert"
)

func TestSuccessfullGitBundles(t *testing.T) {
	table := []struct {
		line, result string
	}{
		{
			"caarlos0/jvm",
			"jvm.plugin.zsh",
		},
		{
			"caarlos0/jvm kind:path",
			"export PATH=\"",
		},
		{
			"caarlos0/jvm kind:path branch:gh-pages",
			"export PATH=\"",
		},
		{
			"caarlos0/jvm kind:dummy",
			"",
		},
	}
	for _, row := range table {
		t.Run(row.line, func(t *testing.T) {
			assert := assert.New(t)
			home := home()
			result, err := bundle.New(home, row.line).Get()
			assert.Contains(result, row.result)
			assert.NoError(err)
		})
	}
}

func TestZshInvalidGitBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	_, err := bundle.New(home, "doesnt exist").Get()
	assert.Error(err)
}

func TestZshLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	assert.NoError(ioutil.WriteFile(home+"/a.sh", []byte("echo 9"), 0644))
	result, err := bundle.New(home, home).Get()
	assert.Contains(result, "a.sh")
	assert.NoError(err)
}

func TestZshInvalidLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	_, err := bundle.New(home, "/asduhasd/asdasda").Get()
	assert.Error(err)
}

func TestPathInvalidLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	_, err := bundle.New(home, "/asduhasd/asdasda kind:path").Get()
	assert.Error(err)
}

func TestPathLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	assert.NoError(ioutil.WriteFile(home+"whatever.sh", []byte(""), 0644))
	result, err := bundle.New(home, home+" kind:path").Get()
	assert.Equal("export PATH=\""+home+":$PATH\"", result)
	assert.NoError(err)
}

func home() string {
	home, err := ioutil.TempDir(os.TempDir(), "antibody")
	if err != nil {
		panic(err.Error())
	}
	return home
}
<commit_msg>added test for repos with no sh files<commit_after>package bundle_test

import (
	"io/ioutil"
	"os"
	"testing"

	"github.com/getantibody/antibody/bundle"
	"github.com/stretchr/testify/assert"
)

func TestSuccessfullGitBundles(t *testing.T) {
	table := []struct {
		line, result string
	}{
		{
			"caarlos0/jvm",
			"jvm.plugin.zsh",
		},
		{
			"caarlos0/jvm kind:path",
			"export PATH=\"",
		},
		{
			"caarlos0/jvm kind:path branch:gh-pages",
			"export PATH=\"",
		},
		{
			"caarlos0/jvm kind:dummy",
			"",
		},
	}
	for _, row := range table {
		t.Run(row.line, func(t *testing.T) {
			assert := assert.New(t)
			home := home()
			result, err := bundle.New(home, row.line).Get()
			assert.Contains(result, row.result)
			assert.NoError(err)
		})
	}
}

func TestZshInvalidGitBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	_, err := bundle.New(home, "doesnt exist").Get()
	assert.Error(err)
}

func TestZshLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	assert.NoError(ioutil.WriteFile(home+"/a.sh", []byte("echo 9"), 0644))
	result, err := bundle.New(home, home).Get()
	assert.Contains(result, "a.sh")
	assert.NoError(err)
}

func TestZshInvalidLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	_, err := bundle.New(home, "/asduhasd/asdasda").Get()
	assert.Error(err)
}

func TestZshBundleWithNoShFiles(t *testing.T) {
	assert := assert.New(t)
	home := home()
	_, err := bundle.New(home, "getantibody/antibody").Get()
	assert.NoError(err)
}

func TestPathInvalidLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	_, err := bundle.New(home, "/asduhasd/asdasda kind:path").Get()
	assert.Error(err)
}

func TestPathLocalBundle(t *testing.T) {
	assert := assert.New(t)
	home := home()
	assert.NoError(ioutil.WriteFile(home+"whatever.sh", []byte(""), 0644))
	result, err := bundle.New(home, home+" kind:path").Get()
	assert.Equal("export PATH=\""+home+":$PATH\"", result)
	assert.NoError(err)
}

func home() string {
	home, err := ioutil.TempDir(os.TempDir(), "antibody")
	if err != nil {
		panic(err.Error())
	}
	return home
}
<|endoftext|>


<commit_before>package colonycore

import (
	"github.com/eaciit/errorlib"
	// "github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	// "log"
	"strconv"
	"strings"
	"time"
)

const (
	/*FILE_TYPE = map[string]string{
		"-": "FILE",
		"d": "DIRECTORY",
		"l": "SYMLINK",
	}*/
	DELIMITER = "/"
)

type FileInfo struct {
	Name         string      `json:"name", bson:"name"`
	Size         float64     `json:"size", bson:"size"`
	User         string      `json:"user", bson:"user"`
	Group        string      `json:"group", bson:"group"`
	Permissions  string      `json:"permissions", bson:"permissions"`
	CreatedDate  time.Time   `json:"createddate", bson:"createddate"`
	LastModified time.Time   `json:"lastmodified", bson:"lastmodified"`
	Type         string      `json:"type", bson:"type"`
	Sub          []*FileInfo `json:"sub", bson:"sub"`
	SubCount     int64       `json:"subcount", bson:"subcount"`
	IsDir        bool        `json:"isdir", bson:"isdir"`
	Path         string      `json:"path", bson:"path"`
	IsEditable   bool        `json:"iseditable", bson:"iseditable"`
}

func ConstructFileInfo(lines string, path string) ([]FileInfo, error) {
	var result []FileInfo

	aLine := strings.Split(lines, "\n")

	if len(aLine) > 1 {
		for _, val := range aLine {
			if val != "" {
				res, e := parse(val, path)
				if e != nil {
					return result, e
				} else {
					result = append(result, res)
				}
			}
		}

		return result, nil
	} else if len(aLine) > 0 {
		res, e := parse(aLine[0], path)
		result = append(result, res)
		return result, e
	}
	return result, nil
}

func parse(line string, path string) (result FileInfo, e error) {
	if line != "" {
		cols := strings.Split(strings.Trim(line, " "), "||")

		if len(cols) == 9 {
			result.Type = strings.TrimSpace(cols[0][:1])
			result.Sub = nil

			if result.Type == "d" {
				result.IsDir = true
			}

			result.Permissions = strings.TrimSpace(cols[0][1:])

			subCount, _ := strconv.ParseInt(strings.TrimSpace(cols[1]), 10, 64)
			result.SubCount = subCount

			result.User = strings.TrimSpace(cols[2])

			result.Group = strings.TrimSpace(cols[3])

			size, _ := strconv.ParseFloat(strings.TrimSpace(cols[4]), 64)
			result.Size = size

			var lastModified time.Time
			str := strings.TrimSpace(cols[5]) + "-" + strings.TrimSpace(cols[6]) + "-" + strings.TrimSpace(cols[7])

			if len(strings.TrimSpace(cols[7])) == 5 {
				str = str + "-" + strconv.Itoa(time.Now().Year())
				lastModified = toolkit.String2Date(str, "MMM-d-H:mm-YYYY")
			} else {
				lastModified = toolkit.String2Date(str, "MMM-d-YYYY")
			}

			result.LastModified = lastModified

			result.Name = strings.TrimSpace(cols[8])

			if len(path) > 1 {
				if path[len(path)-1:] != DELIMITER {
					path = path + DELIMITER
				}

				result.Path = path + result.Name
			}

			result.IsEditable = true
		} else {
			e = errorlib.Error("", "", "parse", "column is not valid")
		}
	}

	return
}
<commit_msg>bug fixing<commit_after>package colonycore

import (
	"github.com/eaciit/errorlib"
	// "github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	// "log"
	"strconv"
	"strings"
	"time"
)

const (
	/*FILE_TYPE = map[string]string{
		"-": "FILE",
		"d": "DIRECTORY",
		"l": "SYMLINK",
	}*/
	DELIMITER = "/"
)

type FileInfo struct {
	Name         string      `json:"name", bson:"name"`
	Size         float64     `json:"size", bson:"size"`
	User         string      `json:"user", bson:"user"`
	Group        string      `json:"group", bson:"group"`
	Permissions  string      `json:"permissions", bson:"permissions"`
	CreatedDate  time.Time   `json:"createddate", bson:"createddate"`
	LastModified time.Time   `json:"lastmodified", bson:"lastmodified"`
	Type         string      `json:"type", bson:"type"`
	Sub          []*FileInfo `json:"sub", bson:"sub"`
	SubCount     int64       `json:"subcount", bson:"subcount"`
	IsDir        bool        `json:"isdir", bson:"isdir"`
	Path         string      `json:"path", bson:"path"`
	IsEditable   bool        `json:"iseditable", bson:"iseditable"`
}

func ConstructFileInfo(lines string, path string) ([]FileInfo, error) {
	if lines != "" {
		var result []FileInfo

		aLine := strings.Split(lines, "\n")

		if len(aLine) > 1 {
			for _, val := range aLine {
				if val != "" {
					res, e := parse(val, path)
					if e != nil {
						return result, e
					} else {
						result = append(result, res)
					}
				}
			}

			return result, nil
		} else if len(aLine) > 0 {
			res, e := parse(aLine[0], path)
			result = append(result, res)
			return result, e
		}
		return result, nil
	}
	return nil, nil
}

func parse(line string, path string) (result FileInfo, e error) {
	if line != "" {
		cols := strings.Split(strings.Trim(line, " "), "||")

		if len(cols) == 9 {
			result.Type = strings.TrimSpace(cols[0][:1])
			result.Sub = nil

			if result.Type == "d" {
				result.IsDir = true
			}

			result.Permissions = strings.TrimSpace(cols[0][1:])

			subCount, _ := strconv.ParseInt(strings.TrimSpace(cols[1]), 10, 64)
			result.SubCount = subCount

			result.User = strings.TrimSpace(cols[2])

			result.Group = strings.TrimSpace(cols[3])

			size, _ := strconv.ParseFloat(strings.TrimSpace(cols[4]), 64)
			result.Size = size

			var lastModified time.Time
			str := strings.TrimSpace(cols[5]) + "-" + strings.TrimSpace(cols[6]) + "-" + strings.TrimSpace(cols[7])

			if len(strings.TrimSpace(cols[7])) == 5 {
				str = str + "-" + strconv.Itoa(time.Now().Year())
				lastModified = toolkit.String2Date(str, "MMM-d-H:mm-YYYY")
			} else {
				lastModified = toolkit.String2Date(str, "MMM-d-YYYY")
			}

			result.LastModified = lastModified

			result.Name = strings.TrimSpace(cols[8])

			if len(path) > 1 {
				if path[len(path)-1:] != DELIMITER {
					path = path + DELIMITER
				}

				result.Path = path + result.Name
			}

			result.IsEditable = true
		} else {
			e = errorlib.Error("", "", "parse", "column is not valid")
		}
	}

	return
}
<|endoftext|>


<commit_before>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

package api

import (
	"sync"
	"unsafe"

	. "github.com/ying32/govcl/vcl/types"
)

var (
	// 事件回调查找表
	eventCallbackMap sync.Map
	// 独立的消息事件查找表
	messageCallbackMap sync.Map
	// ThreadSync
	threadSync   sync.Mutex
	threadSyncFn func()
	// eventId， 2000 起
	eventIds uintptr = 2000
)

// Delphi或者Lazarus的Bool类型转为Go bool
func DBoolToGoBool(val uintptr) bool {
	if val != 0 {
		return true
	}
	return false
}

// Go bool类型转为Delphi或者Lazarus的Bool类型
func GoBoolToDBool(val bool) uintptr {
	if val {
		return 1
	}
	return 0
}

// IsNil 判断一个接口是否为空
// interface{}数据类型定义为 typedef struct { void *type; void *value; } GoInterface;
// 当type与value值都为nil时则为空。
func IsNil(val interface{}) bool {
	ptr := unsafe.Pointer(&val)
	return *(*uintptr)(ptr) == 0 && *(*uintptr)(unsafe.Pointer(uintptr(ptr) + uintptr(unsafe.Sizeof(val)/2))) == 0
}

func getFuncId(val interface{}) uintptr {
	ptr := unsafe.Pointer(&val)
	if *(*uintptr)(ptr) == 0 {
		return 0
	}
	return *(*uintptr)(unsafe.Pointer(uintptr(ptr) + uintptr(unsafe.Sizeof(val)/2)))
}

// hashOf 管不了了，先直接这样吧，防止重复的，虽然会产生很多
func hashOf(val interface{}) uintptr {
	//result := getFuncId(val)
	eventIds++
	return eventIds
}

// 将事件添加到查找表中
func addEventToMap(f interface{}) uintptr {
	p := hashOf(f)
	eventCallbackMap.Store(p, f)
	return p
}

//
func GetaddEventToMapFn() func(f interface{}) uintptr {
	return addEventToMap
}

// 从事件表中查找指定id的函数
func EventCallbackOf(Id uintptr) (interface{}, bool) {
	return eventCallbackMap.Load(Id)
}

// 从事件表中移除指定的函数
func RemoveEventCallbackOf(Id uintptr) {
	eventCallbackMap.Delete(Id)
}

// 添加消息事件到消息表中
func addMessageEventToMap(f interface{}) uintptr {
	p := hashOf(f)
	messageCallbackMap.Store(p, f)
	return p
}

// 从消息表中查找指定id的函数
func MessageCallbackOf(Id uintptr) (interface{}, bool) {
	return messageCallbackMap.Load(Id)
}

// 返回当前需要调用的线程同步函数
func ThreadSyncCallbackFn() func() {
	return threadSyncFn
}

// 设置事件回调函数指针
func SetEventCallback(ptr uintptr) {
	setEventCallback.Call(ptr)
}

// 设置消息事件回调函数指针
func SetMessageCallback(ptr uintptr) {
	setMessageCallback.Call(ptr)
}

// 设置线程同步事件回调函数指针
func SetThreadSyncCallback(ptr uintptr) {
	setThreadSyncCallback.Call(ptr)
}

// 从Delphi/Lazarus字符串数组中获取指定索引的值
func DGetStringArrOf(p uintptr, index int) string {
	r, _, _ := dGetStringArrOf.Call(p, uintptr(index))
	return DStrToGoStr(r)
}

// 获取Delphi/Lazarus字符串长度
func DStrLen(p uintptr) int {
	ret, _, _ := dStrLen.Call(p)
	return int(ret)
}

// Delphi/Lazarus内存操作
func DMove(src, dest uintptr, llen int) {
	dMove.Call(src, dest, uintptr(llen))
}

func DShowMessage(s string) {
	dShowMessage.Call(GoStrToDStr(s))
}

// 应用程序实例
func DGetMainInstance() uintptr {
	ret, _, _ := dGetMainInstance.Call()
	return ret
}

func DMessageDlg(Msg string, DlgType TMsgDlgType, Buttons TMsgDlgButtons, HelpCtx int32) int32 {
	ret, _, _ := dMessageDlg.Call(GoStrToDStr(Msg), uintptr(DlgType), uintptr(Buttons), uintptr(HelpCtx))
	return int32(ret)
}

func DSetReportMemoryLeaksOnShutdown(v bool) {
	dSetReportMemoryLeaksOnShutdown.Call(GoBoolToDBool(v))
}

func DTextToShortCut(val string) TShortCut {
	ret, _, _ := dTextToShortCut.Call(GoStrToDStr(val))
	return TShortCut(ret)
}

func DShortCutToText(val TShortCut) string {
	ret, _, _ := dShortCutToText.Call(uintptr(val))
	return DStrToGoStr(ret)
}

func DSysOpen(filename string) {
	dSysOpen.Call(GoStrToDStr(filename))
}

func DExtractFilePath(filename string) string {
	r, _, _ := dExtractFilePath.Call(GoStrToDStr(filename))
	return DStrToGoStr(r)
}

func DFileExists(filename string) bool {
	r, _, _ := dFileExists.Call(GoStrToDStr(filename))
	return DBoolToGoBool(r)
}

func DSelectDirectory1(options TSelectDirOpts) (bool, string) {
	var ptr uintptr
	r, _, _ := dSelectDirectory1.Call(uintptr(unsafe.Pointer(&ptr)), uintptr(options), 0)
	v := DBoolToGoBool(r)
	if v {
		return true, DStrToGoStr(ptr)
	}
	return false, ""
}

func DSelectDirectory2(caption, root string, options TSelectDirExtOpts, parent uintptr) (bool, string) {
	var ptr uintptr
	r, _, _ := dSelectDirectory2.Call(GoStrToDStr(caption), GoStrToDStr(root), uintptr(unsafe.Pointer(&ptr)),
		uintptr(options), parent)
	v := DBoolToGoBool(r)
	if v {
		return true, DStrToGoStr(ptr)
	}
	return false, ""
}

// 线程同步
func DSynchronize(fn func(), useMsg uintptr) {
	threadSync.Lock()
	defer threadSync.Unlock()
	threadSyncFn = fn
	dSynchronize.Call(useMsg)
	threadSyncFn = nil
}

func DInputBox(aCaption, aPrompt, aDefault string) string {
	r, _, _ := dInputBox.Call(GoStrToDStr(aCaption), GoStrToDStr(aPrompt), GoStrToDStr(aDefault))
	return DStrToGoStr(r)
}

func DInputQuery(aCaption, aPrompt string, value *string) bool {
	if value == nil {
		return false
	}
	var strPtr uintptr
	r, _, _ := dInputQuery.Call(GoStrToDStr(aCaption), GoStrToDStr(aPrompt), GoStrToDStr(*value), uintptr(unsafe.Pointer(&strPtr)))
	if strPtr != 0 {
		*value = DStrToGoStr(strPtr)
	}
	return DBoolToGoBool(r)
}

// DSysLocaled
func DSysLocale(aInfo *TSysLocale) {
	dSysLocale.Call(uintptr(unsafe.Pointer(aInfo)))
}

// Shortcut
//DCreateURLShortCut
func DCreateURLShortCut(aDestPath, aShortCutName, aURL string) {
	dCreateURLShortCut.Call(GoStrToDStr(aDestPath), GoStrToDStr(aShortCutName), GoStrToDStr(aURL))
}

//DCreateShortCut
func DCreateShortCut(aDestPath, aShortCutName, aSrcFileName, aIconFileName, aDescription, aCmdArgs string) bool {
	r, _, _ := dCreateShortCut.Call(GoStrToDStr(aDestPath), GoStrToDStr(aShortCutName), GoStrToDStr(aSrcFileName),
		GoStrToDStr(aIconFileName), GoStrToDStr(aDescription), GoStrToDStr(aCmdArgs))
	return DBoolToGoBool(r)
}

// SetProperty
// DSetPropertyValue
func DSetPropertyValue(instance uintptr, propName, value string) {
	dSetPropertyValue.Call(instance, GoStrToDStr(propName), GoStrToDStr(value))
}

// DSetPropertySecValue
func DSetPropertySecValue(instance uintptr, propName, secPropName, value string) {
	dSetPropertySecValue.Call(instance, GoStrToDStr(propName), GoStrToDStr(secPropName), GoStrToDStr(value))
}

// guid
// DGUIDToString
func DGUIDToString(guid TGUID) string {
	r, _, _ := dGUIDToString.Call(uintptr(unsafe.Pointer(&guid)))
	return DStrToGoStr(r)
}

// DStringToGUID
func DStringToGUID(str string) TGUID {
	var guid TGUID
	dStringToGUID.Call(GoStrToDStr(str), uintptr(unsafe.Pointer(&guid)))
	return guid
}

// DCreateGUID
func DCreateGUID() TGUID {
	var guid TGUID
	dCreateGUID.Call(uintptr(unsafe.Pointer(&guid)))
	return guid
}

// LibResouces
func DGetLibResouceCount() int32 {
	r, _, _ := dGetLibResouceCount.Call()
	return int32(r)
}

func DGetLibResouceItem(aIndex int32) (ret TLibResouce) {
	item := struct {
		Name     uintptr
		ValuePtr uintptr
	}{}
	dGetLibResouceItem.Call(uintptr(aIndex), uintptr(unsafe.Pointer(&item)))
	ret.Name = DStrToGoStr(item.Name)
	ret.Ptr = item.ValuePtr
	return
}

func DModifyLibResouce(aPtr uintptr, aValue string) {
	dModifyLibResouce.Call(aPtr, GoStrToDStr(aValue))
}

// 库的信息
// 获取当前库使用的字符串编码
func DLibStringEncoding() TStringEncoding {
	r, _, _ := dLibStringEncoding.Call()
	return TStringEncoding(r)
}

// 库版本信息
func DLibVersion() uint32 {
	r, _, _ := dLibVersion.Call()
	return uint32(r)
}

func DGetGDKWindowXID(handle uintptr) TXID {
	var aResult TXID
	dGetGDKWindowXID.Call(handle, uintptr(unsafe.Pointer(&aResult)))
	return aResult
}
<commit_msg>fix eventid<commit_after>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

package api

import (
	"reflect"
	"sync"
	"unsafe"

	. "github.com/ying32/govcl/vcl/types"
)

var (
	// 事件回调查找表
	eventCallbackMap sync.Map
	// 独立的消息事件查找表
	messageCallbackMap sync.Map
	// ThreadSync
	threadSync   sync.Mutex
	threadSyncFn func()
	// eventId， 2000 起
	eventIds uintptr = 2000
)

// Delphi或者Lazarus的Bool类型转为Go bool
func DBoolToGoBool(val uintptr) bool {
	if val != 0 {
		return true
	}
	return false
}

// Go bool类型转为Delphi或者Lazarus的Bool类型
func GoBoolToDBool(val bool) uintptr {
	if val {
		return 1
	}
	return 0
}

// IsNil 判断一个接口是否为空
// interface{}数据类型定义为 typedef struct { void *type; void *value; } GoInterface;
// 当type与value值都为nil时则为空。
func IsNil(val interface{}) bool {
	ptr := unsafe.Pointer(&val)
	return *(*uintptr)(ptr) == 0 && *(*uintptr)(unsafe.Pointer(uintptr(ptr) + uintptr(unsafe.Sizeof(val)/2))) == 0
}

func getFuncId(val interface{}) uintptr {
	ptr := unsafe.Pointer(&val)
	if *(*uintptr)(ptr) == 0 {
		return 0
	}
	return *(*uintptr)(unsafe.Pointer(uintptr(ptr) + uintptr(unsafe.Sizeof(val)/2)))
}

// hashOf 管不了了，先直接这样吧，防止重复的，虽然会产生很多
func hashOf(val interface{}) uintptr {
	if reflect.ValueOf(val).Pointer() == 0 {
		return 0
	}
	//result := getFuncId(val)
	eventIds++
	return eventIds
}

// 将事件添加到查找表中
func addEventToMap(f interface{}) uintptr {
	p := hashOf(f)
	eventCallbackMap.Store(p, f)
	return p
}

//
func GetaddEventToMapFn() func(f interface{}) uintptr {
	return addEventToMap
}

// 从事件表中查找指定id的函数
func EventCallbackOf(Id uintptr) (interface{}, bool) {
	return eventCallbackMap.Load(Id)
}

// 从事件表中移除指定的函数
func RemoveEventCallbackOf(Id uintptr) {
	eventCallbackMap.Delete(Id)
}

// 添加消息事件到消息表中
func addMessageEventToMap(f interface{}) uintptr {
	p := hashOf(f)
	messageCallbackMap.Store(p, f)
	return p
}

// 从消息表中查找指定id的函数
func MessageCallbackOf(Id uintptr) (interface{}, bool) {
	return messageCallbackMap.Load(Id)
}

// 返回当前需要调用的线程同步函数
func ThreadSyncCallbackFn() func() {
	return threadSyncFn
}

// 设置事件回调函数指针
func SetEventCallback(ptr uintptr) {
	setEventCallback.Call(ptr)
}

// 设置消息事件回调函数指针
func SetMessageCallback(ptr uintptr) {
	setMessageCallback.Call(ptr)
}

// 设置线程同步事件回调函数指针
func SetThreadSyncCallback(ptr uintptr) {
	setThreadSyncCallback.Call(ptr)
}

// 从Delphi/Lazarus字符串数组中获取指定索引的值
func DGetStringArrOf(p uintptr, index int) string {
	r, _, _ := dGetStringArrOf.Call(p, uintptr(index))
	return DStrToGoStr(r)
}

// 获取Delphi/Lazarus字符串长度
func DStrLen(p uintptr) int {
	ret, _, _ := dStrLen.Call(p)
	return int(ret)
}

// Delphi/Lazarus内存操作
func DMove(src, dest uintptr, llen int) {
	dMove.Call(src, dest, uintptr(llen))
}

func DShowMessage(s string) {
	dShowMessage.Call(GoStrToDStr(s))
}

// 应用程序实例
func DGetMainInstance() uintptr {
	ret, _, _ := dGetMainInstance.Call()
	return ret
}

func DMessageDlg(Msg string, DlgType TMsgDlgType, Buttons TMsgDlgButtons, HelpCtx int32) int32 {
	ret, _, _ := dMessageDlg.Call(GoStrToDStr(Msg), uintptr(DlgType), uintptr(Buttons), uintptr(HelpCtx))
	return int32(ret)
}

func DSetReportMemoryLeaksOnShutdown(v bool) {
	dSetReportMemoryLeaksOnShutdown.Call(GoBoolToDBool(v))
}

func DTextToShortCut(val string) TShortCut {
	ret, _, _ := dTextToShortCut.Call(GoStrToDStr(val))
	return TShortCut(ret)
}

func DShortCutToText(val TShortCut) string {
	ret, _, _ := dShortCutToText.Call(uintptr(val))
	return DStrToGoStr(ret)
}

func DSysOpen(filename string) {
	dSysOpen.Call(GoStrToDStr(filename))
}

func DExtractFilePath(filename string) string {
	r, _, _ := dExtractFilePath.Call(GoStrToDStr(filename))
	return DStrToGoStr(r)
}

func DFileExists(filename string) bool {
	r, _, _ := dFileExists.Call(GoStrToDStr(filename))
	return DBoolToGoBool(r)
}

func DSelectDirectory1(options TSelectDirOpts) (bool, string) {
	var ptr uintptr
	r, _, _ := dSelectDirectory1.Call(uintptr(unsafe.Pointer(&ptr)), uintptr(options), 0)
	v := DBoolToGoBool(r)
	if v {
		return true, DStrToGoStr(ptr)
	}
	return false, ""
}

func DSelectDirectory2(caption, root string, options TSelectDirExtOpts, parent uintptr) (bool, string) {
	var ptr uintptr
	r, _, _ := dSelectDirectory2.Call(GoStrToDStr(caption), GoStrToDStr(root), uintptr(unsafe.Pointer(&ptr)),
		uintptr(options), parent)
	v := DBoolToGoBool(r)
	if v {
		return true, DStrToGoStr(ptr)
	}
	return false, ""
}

// 线程同步
func DSynchronize(fn func(), useMsg uintptr) {
	threadSync.Lock()
	defer threadSync.Unlock()
	threadSyncFn = fn
	dSynchronize.Call(useMsg)
	threadSyncFn = nil
}

func DInputBox(aCaption, aPrompt, aDefault string) string {
	r, _, _ := dInputBox.Call(GoStrToDStr(aCaption), GoStrToDStr(aPrompt), GoStrToDStr(aDefault))
	return DStrToGoStr(r)
}

func DInputQuery(aCaption, aPrompt string, value *string) bool {
	if value == nil {
		return false
	}
	var strPtr uintptr
	r, _, _ := dInputQuery.Call(GoStrToDStr(aCaption), GoStrToDStr(aPrompt), GoStrToDStr(*value), uintptr(unsafe.Pointer(&strPtr)))
	if strPtr != 0 {
		*value = DStrToGoStr(strPtr)
	}
	return DBoolToGoBool(r)
}

// DSysLocaled
func DSysLocale(aInfo *TSysLocale) {
	dSysLocale.Call(uintptr(unsafe.Pointer(aInfo)))
}

// Shortcut
//DCreateURLShortCut
func DCreateURLShortCut(aDestPath, aShortCutName, aURL string) {
	dCreateURLShortCut.Call(GoStrToDStr(aDestPath), GoStrToDStr(aShortCutName), GoStrToDStr(aURL))
}

//DCreateShortCut
func DCreateShortCut(aDestPath, aShortCutName, aSrcFileName, aIconFileName, aDescription, aCmdArgs string) bool {
	r, _, _ := dCreateShortCut.Call(GoStrToDStr(aDestPath), GoStrToDStr(aShortCutName), GoStrToDStr(aSrcFileName),
		GoStrToDStr(aIconFileName), GoStrToDStr(aDescription), GoStrToDStr(aCmdArgs))
	return DBoolToGoBool(r)
}

// SetProperty
// DSetPropertyValue
func DSetPropertyValue(instance uintptr, propName, value string) {
	dSetPropertyValue.Call(instance, GoStrToDStr(propName), GoStrToDStr(value))
}

// DSetPropertySecValue
func DSetPropertySecValue(instance uintptr, propName, secPropName, value string) {
	dSetPropertySecValue.Call(instance, GoStrToDStr(propName), GoStrToDStr(secPropName), GoStrToDStr(value))
}

// guid
// DGUIDToString
func DGUIDToString(guid TGUID) string {
	r, _, _ := dGUIDToString.Call(uintptr(unsafe.Pointer(&guid)))
	return DStrToGoStr(r)
}

// DStringToGUID
func DStringToGUID(str string) TGUID {
	var guid TGUID
	dStringToGUID.Call(GoStrToDStr(str), uintptr(unsafe.Pointer(&guid)))
	return guid
}

// DCreateGUID
func DCreateGUID() TGUID {
	var guid TGUID
	dCreateGUID.Call(uintptr(unsafe.Pointer(&guid)))
	return guid
}

// LibResouces
func DGetLibResouceCount() int32 {
	r, _, _ := dGetLibResouceCount.Call()
	return int32(r)
}

func DGetLibResouceItem(aIndex int32) (ret TLibResouce) {
	item := struct {
		Name     uintptr
		ValuePtr uintptr
	}{}
	dGetLibResouceItem.Call(uintptr(aIndex), uintptr(unsafe.Pointer(&item)))
	ret.Name = DStrToGoStr(item.Name)
	ret.Ptr = item.ValuePtr
	return
}

func DModifyLibResouce(aPtr uintptr, aValue string) {
	dModifyLibResouce.Call(aPtr, GoStrToDStr(aValue))
}

// 库的信息
// 获取当前库使用的字符串编码
func DLibStringEncoding() TStringEncoding {
	r, _, _ := dLibStringEncoding.Call()
	return TStringEncoding(r)
}

// 库版本信息
func DLibVersion() uint32 {
	r, _, _ := dLibVersion.Call()
	return uint32(r)
}

func DGetGDKWindowXID(handle uintptr) TXID {
	var aResult TXID
	dGetGDKWindowXID.Call(handle, uintptr(unsafe.Pointer(&aResult)))
	return aResult
}
<|endoftext|>


<commit_before>package vcs

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

	"github.com/gogits/git"
)

type GitRepositoryNative struct {
	dir string
	u   *git.Repository
}

func OpenGitRepositoryNative(dir string) (*GitRepositoryNative, error) {
	r, err := git.OpenRepository(dir)
	if err != nil {
		return nil, err
	}
	return &GitRepositoryNative{dir, r}, nil
}

func (r *GitRepositoryNative) ResolveRevision(spec string) (CommitID, error) {
	id, _ := r.ResolveBranch(spec)
	if id != "" {
		return id, nil
	}
	return r.ResolveTag(spec)
}

func (r *GitRepositoryNative) ResolveBranch(name string) (CommitID, error) {
	id, err := r.u.GetCommitIdOfBranch(name)
	return CommitID(id), err
}

func (r *GitRepositoryNative) ResolveTag(name string) (CommitID, error) {
	id, err := r.u.GetCommitIdOfTag(name)
	return CommitID(id), err
}

func (r *GitRepositoryNative) GetCommit(id CommitID) (*Commit, error) {
	c, err := r.u.GetCommit(string(id))
	if err != nil {
		return nil, err
	}

	return r.makeCommit(c)
}

func (r *GitRepositoryNative) CommitLog(to CommitID) ([]*Commit, error) {
	c, err := r.u.GetCommit(string(to))
	if err != nil {
		return nil, err
	}

	cs, err := c.CommitsBefore()
	if err != nil {
		return nil, err
	}

	commits := make([]*Commit, cs.Len())
	for i, c := 0, cs.Front(); c != nil; c = c.Next() {
		commits[i], err = r.makeCommit(c.Value.(*git.Commit))
		if err != nil {
			return nil, err
		}

		i++
	}
	return commits, nil
}

func (r *GitRepositoryNative) makeCommit(c *git.Commit) (*Commit, error) {
	var parents []CommitID
	if pc := c.ParentCount(); pc > 0 {
		parents = make([]CommitID, pc)
		for i := 0; i < pc; i++ {
			pid, err := c.ParentId(i)
			if err != nil {
				return nil, err
			}
			parents[i] = CommitID(pid.String())
		}
	}

	return &Commit{
		ID:        CommitID(c.Id.String()),
		Author:    Signature{c.Author.Name, c.Author.Email, c.Author.When},
		Committer: &Signature{c.Committer.Name, c.Committer.Email, c.Committer.When},
		Message:   strings.TrimSuffix(c.CommitMessage, "\n"),
		Parents:   parents,
	}, nil
}

func (r *GitRepositoryNative) FileSystem(at CommitID) (FileSystem, error) {
	c, err := r.u.GetCommit(string(at))
	if err != nil {
		return nil, err
	}
	return &gitFSNative{r.dir, &c.Tree, at, r.u}, nil
}

type gitFSNative struct {
	dir  string
	tree *git.Tree
	at   CommitID

	repo *git.Repository
}

func (fs *gitFSNative) getEntry(path string) (*git.TreeEntry, error) {
	e, err := fs.tree.GetTreeEntryByPath(path)
	if err == git.ErrNotExist {
		c, err := fs.repo.GetCommitOfRelPath(string(fs.at), path)
		if err != nil {
			if err.Error() == "Length must be 40" {
				// this is when `git log` called by GetCommitOfRelPath returns
				// empty (which means the file is not found)
				err = git.ErrNotExist
			}
			return nil, standardizeGitError(err)
		}
		e, err = c.Tree.GetTreeEntryByPath(path)
	}
	return e, err
}

func (fs *gitFSNative) Open(name string) (ReadSeekCloser, error) {
	e, err := fs.getEntry(name)
	if err != nil {
		return nil, err
	}

	data, err := e.Blob().Data()
	if err != nil {
		return nil, err
	}

	return nopCloser{bytes.NewReader(data)}, nil
}

func (fs *gitFSNative) Lstat(path string) (os.FileInfo, error) {
	return fs.Stat(path)
}

func (fs *gitFSNative) Stat(path string) (os.FileInfo, error) {
	path = filepath.Clean(path)

	if path == "." {
		return &fileInfo{mode: os.ModeDir}, nil
	}

	// TODO(sqs): follow symlinks (as Stat is required to do)
	return fs.getEntry(path)
}

func (fs *gitFSNative) ReadDir(path string) ([]os.FileInfo, error) {
	path = filepath.Clean(path)

	var subtree *git.Tree
	var err error
	if path == "." {
		subtree = fs.tree
	} else {
		subtree, err = fs.tree.SubTree(path)
		if err != nil {
			return nil, standardizeGitError(err)
		}
	}

	entries := subtree.ListEntries()
	fis := make([]os.FileInfo, len(entries))
	for i, e := range entries {
		fis[i] = e
	}
	return fis, nil
}

func (fs *gitFSNative) String() string {
	return fmt.Sprintf("git repository %s commit %s (native)", fs.dir, fs.at)
}

type nopCloser struct {
	io.ReadSeeker
}

func (nc nopCloser) Close() error { return nil }

func standardizeGitError(err error) error {
	if err == git.ErrNotExist {
		return os.ErrNotExist
	}
	return err
}
<commit_msg>Fix git Open; bytes.NewReader expects []byte<commit_after>package vcs

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

	"github.com/gogits/git"
)

type GitRepositoryNative struct {
	dir string
	u   *git.Repository
}

func OpenGitRepositoryNative(dir string) (*GitRepositoryNative, error) {
	r, err := git.OpenRepository(dir)
	if err != nil {
		return nil, err
	}
	return &GitRepositoryNative{dir, r}, nil
}

func (r *GitRepositoryNative) ResolveRevision(spec string) (CommitID, error) {
	id, _ := r.ResolveBranch(spec)
	if id != "" {
		return id, nil
	}
	return r.ResolveTag(spec)
}

func (r *GitRepositoryNative) ResolveBranch(name string) (CommitID, error) {
	id, err := r.u.GetCommitIdOfBranch(name)
	return CommitID(id), err
}

func (r *GitRepositoryNative) ResolveTag(name string) (CommitID, error) {
	id, err := r.u.GetCommitIdOfTag(name)
	return CommitID(id), err
}

func (r *GitRepositoryNative) GetCommit(id CommitID) (*Commit, error) {
	c, err := r.u.GetCommit(string(id))
	if err != nil {
		return nil, err
	}

	return r.makeCommit(c)
}

func (r *GitRepositoryNative) CommitLog(to CommitID) ([]*Commit, error) {
	c, err := r.u.GetCommit(string(to))
	if err != nil {
		return nil, err
	}

	cs, err := c.CommitsBefore()
	if err != nil {
		return nil, err
	}

	commits := make([]*Commit, cs.Len())
	for i, c := 0, cs.Front(); c != nil; c = c.Next() {
		commits[i], err = r.makeCommit(c.Value.(*git.Commit))
		if err != nil {
			return nil, err
		}

		i++
	}
	return commits, nil
}

func (r *GitRepositoryNative) makeCommit(c *git.Commit) (*Commit, error) {
	var parents []CommitID
	if pc := c.ParentCount(); pc > 0 {
		parents = make([]CommitID, pc)
		for i := 0; i < pc; i++ {
			pid, err := c.ParentId(i)
			if err != nil {
				return nil, err
			}
			parents[i] = CommitID(pid.String())
		}
	}

	return &Commit{
		ID:        CommitID(c.Id.String()),
		Author:    Signature{c.Author.Name, c.Author.Email, c.Author.When},
		Committer: &Signature{c.Committer.Name, c.Committer.Email, c.Committer.When},
		Message:   strings.TrimSuffix(c.CommitMessage, "\n"),
		Parents:   parents,
	}, nil
}

func (r *GitRepositoryNative) FileSystem(at CommitID) (FileSystem, error) {
	c, err := r.u.GetCommit(string(at))
	if err != nil {
		return nil, err
	}
	return &gitFSNative{r.dir, &c.Tree, at, r.u}, nil
}

type gitFSNative struct {
	dir  string
	tree *git.Tree
	at   CommitID

	repo *git.Repository
}

func (fs *gitFSNative) getEntry(path string) (*git.TreeEntry, error) {
	e, err := fs.tree.GetTreeEntryByPath(path)
	if err == git.ErrNotExist {
		c, err := fs.repo.GetCommitOfRelPath(string(fs.at), path)
		if err != nil {
			if err.Error() == "Length must be 40" {
				// this is when `git log` called by GetCommitOfRelPath returns
				// empty (which means the file is not found)
				err = git.ErrNotExist
			}
			return nil, standardizeGitError(err)
		}
		e, err = c.Tree.GetTreeEntryByPath(path)
	}
	return e, err
}

func (fs *gitFSNative) Open(name string) (ReadSeekCloser, error) {
	e, err := fs.getEntry(name)
	if err != nil {
		return nil, err
	}

	data, err := e.Blob().Data()
	if err != nil {
		return nil, err
	}

	b, err := ioutil.ReadAll(data)
	if err != nil {
		return nil, err
	}

	return nopCloser{bytes.NewReader(b)}, nil
}

func (fs *gitFSNative) Lstat(path string) (os.FileInfo, error) {
	return fs.Stat(path)
}

func (fs *gitFSNative) Stat(path string) (os.FileInfo, error) {
	path = filepath.Clean(path)

	if path == "." {
		return &fileInfo{mode: os.ModeDir}, nil
	}

	// TODO(sqs): follow symlinks (as Stat is required to do)
	return fs.getEntry(path)
}

func (fs *gitFSNative) ReadDir(path string) ([]os.FileInfo, error) {
	path = filepath.Clean(path)

	var subtree *git.Tree
	var err error
	if path == "." {
		subtree = fs.tree
	} else {
		subtree, err = fs.tree.SubTree(path)
		if err != nil {
			return nil, standardizeGitError(err)
		}
	}

	entries := subtree.ListEntries()
	fis := make([]os.FileInfo, len(entries))
	for i, e := range entries {
		fis[i] = e
	}
	return fis, nil
}

func (fs *gitFSNative) String() string {
	return fmt.Sprintf("git repository %s commit %s (native)", fs.dir, fs.at)
}

type nopCloser struct {
	io.ReadSeeker
}

func (nc nopCloser) Close() error { return nil }

func standardizeGitError(err error) error {
	if err == git.ErrNotExist {
		return os.ErrNotExist
	}
	return err
}
<|endoftext|>


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

package verify

import (
	"fmt"
	"strings"

	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/graph"
	"github.com/jacobsa/comeback/repr"
	"golang.org/x/net/context"
)

const (
	filePrefix = "f:"
	dirPrefix  = "d:"
)

// Create a visitor for the DAG of blobs in the supplied bucket. Node names are
// expected to be generated by FormatNodeName.
//
// The visitor reads directory blobs, parses them, and emits their children as
// adjacent nodes. For file nodes, the visitor verifies that their score exists
// (according to allScores), and verifies that the blob can be loaded if
// readFiles is true.
//
// It is expected that the blob store's Load method does score verification for
// us.
func NewVisitor(
	readFiles bool,
	allScores []blob.Score,
	bs blob.Store) (v graph.Visitor) {
	typed := &visitor{
		readFiles:   readFiles,
		blobStore:   bs,
		knownScores: make(map[blob.Score]struct{}),
	}

	for _, score := range allScores {
		typed.knownScores[score] = struct{}{}
	}

	v = typed
	return
}

// Create a node name that can be consumed by the visitor and by ParseNodeName.
// If dir is false, the node represents a file.
func FormatNodeName(
	dir bool,
	score blob.Score) (node string) {
	if dir {
		node = dirPrefix + score.Hex()
	} else {
		node = filePrefix + score.Hex()
	}

	return
}

// Parse a node name created by FormatNodeName.
func ParseNodeName(
	node string) (dir bool, score blob.Score, err error) {
	var hexScore string

	switch {
	case strings.HasPrefix(node, filePrefix):
		hexScore = strings.TrimPrefix(node, filePrefix)

	case strings.HasPrefix(node, dirPrefix):
		dir = true
		hexScore = strings.TrimPrefix(node, dirPrefix)

	default:
		err = fmt.Errorf("Unknown prefix")
		return
	}

	score, err = blob.ParseHexScore(hexScore)
	if err != nil {
		err = fmt.Errorf("ParseHexScore: %v", err)
		return
	}

	return
}

////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////

type visitor struct {
	readFiles   bool
	blobStore   blob.Store
	knownScores map[blob.Score]struct{}
}

func (v *visitor) visitFile(
	ctx context.Context,
	score blob.Score) (err error) {
	// If reading files is disabled, simply check that the score is known.
	if !v.readFiles {
		_, ok := v.knownScores[score]
		if !ok {
			err = fmt.Errorf("Unknown file score: %s", score.Hex())
			return
		}

		return
	}

	// Make sure we can load the blob contents. Presumably the blob store
	// verifies the score (of the ciphertext) on the way through.
	_, err = v.blobStore.Load(score)
	if err != nil {
		err = fmt.Errorf("Load(%s): %v", score.Hex(), err)
		return
	}

	return
}

func (v *visitor) visitDir(
	ctx context.Context,
	score blob.Score) (adjacent []string, err error) {
	// Load the blob contents.
	contents, err := v.blobStore.Load(score)
	if err != nil {
		err = fmt.Errorf("Load(%s): %v", score.Hex(), err)
		return
	}

	// Parse the listing.
	listing, err := repr.UnmarshalDir(contents)
	if err != nil {
		err = fmt.Errorf("UnmarshalDir(%s): %v", score.Hex(), err)
		return
	}

	// Return a node for each score in each entry.
	for _, entry := range listing {
		// Is this a directory?
		var dir bool
		switch entry.Type {
		case fs.TypeFile:
			dir = false

		case fs.TypeDirectory:
			dir = true

		default:
			err = fmt.Errorf("Dir %s: unknown entry type %v", score.Hex(), entry.Type)
			return
		}

		// Return a node for each score.
		for _, score := range entry.Scores {
			adjacent = append(adjacent, FormatNodeName(dir, score))
		}
	}

	return
}

func (v *visitor) Visit(
	ctx context.Context,
	node string) (adjacent []string, err error) {
	// Parse the node name.
	dir, score, err := ParseNodeName(node)
	if err != nil {
		err = fmt.Errorf("ParseNodeName(%q): %v", node, err)
		return
	}

	if dir {
		adjacent, err = v.visitDir(ctx, score)
		return
	} else {
		err = v.visitFile(ctx, score)
		return
	}
}
<commit_msg>Added support for symlinks.<commit_after>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package verify

import (
	"fmt"
	"strings"

	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/graph"
	"github.com/jacobsa/comeback/repr"
	"golang.org/x/net/context"
)

const (
	filePrefix = "f:"
	dirPrefix  = "d:"
)

// Create a visitor for the DAG of blobs in the supplied bucket. Node names are
// expected to be generated by FormatNodeName.
//
// The visitor reads directory blobs, parses them, and emits their children as
// adjacent nodes. For file nodes, the visitor verifies that their score exists
// (according to allScores), and verifies that the blob can be loaded if
// readFiles is true.
//
// It is expected that the blob store's Load method does score verification for
// us.
func NewVisitor(
	readFiles bool,
	allScores []blob.Score,
	bs blob.Store) (v graph.Visitor) {
	typed := &visitor{
		readFiles:   readFiles,
		blobStore:   bs,
		knownScores: make(map[blob.Score]struct{}),
	}

	for _, score := range allScores {
		typed.knownScores[score] = struct{}{}
	}

	v = typed
	return
}

// Create a node name that can be consumed by the visitor and by ParseNodeName.
// If dir is false, the node represents a file.
func FormatNodeName(
	dir bool,
	score blob.Score) (node string) {
	if dir {
		node = dirPrefix + score.Hex()
	} else {
		node = filePrefix + score.Hex()
	}

	return
}

// Parse a node name created by FormatNodeName.
func ParseNodeName(
	node string) (dir bool, score blob.Score, err error) {
	var hexScore string

	switch {
	case strings.HasPrefix(node, filePrefix):
		hexScore = strings.TrimPrefix(node, filePrefix)

	case strings.HasPrefix(node, dirPrefix):
		dir = true
		hexScore = strings.TrimPrefix(node, dirPrefix)

	default:
		err = fmt.Errorf("Unknown prefix")
		return
	}

	score, err = blob.ParseHexScore(hexScore)
	if err != nil {
		err = fmt.Errorf("ParseHexScore: %v", err)
		return
	}

	return
}

////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////

type visitor struct {
	readFiles   bool
	blobStore   blob.Store
	knownScores map[blob.Score]struct{}
}

func (v *visitor) visitFile(
	ctx context.Context,
	score blob.Score) (err error) {
	// If reading files is disabled, simply check that the score is known.
	if !v.readFiles {
		_, ok := v.knownScores[score]
		if !ok {
			err = fmt.Errorf("Unknown file score: %s", score.Hex())
			return
		}

		return
	}

	// Make sure we can load the blob contents. Presumably the blob store
	// verifies the score (of the ciphertext) on the way through.
	_, err = v.blobStore.Load(score)
	if err != nil {
		err = fmt.Errorf("Load(%s): %v", score.Hex(), err)
		return
	}

	return
}

func (v *visitor) visitDir(
	ctx context.Context,
	score blob.Score) (adjacent []string, err error) {
	// Load the blob contents.
	contents, err := v.blobStore.Load(score)
	if err != nil {
		err = fmt.Errorf("Load(%s): %v", score.Hex(), err)
		return
	}

	// Parse the listing.
	listing, err := repr.UnmarshalDir(contents)
	if err != nil {
		err = fmt.Errorf("UnmarshalDir(%s): %v", score.Hex(), err)
		return
	}

	// Return a node for each score in each entry.
	for _, entry := range listing {
		// Is this a directory?
		var dir bool
		switch entry.Type {
		case fs.TypeFile:
			dir = false

		case fs.TypeDirectory:
			dir = true

		case fs.TypeSymlink:
			if len(entry.Scores) != 0 {
				err = fmt.Errorf(
					"Dir %s: symlink unexpectedly contains scores",
					score.Hex())

				return
			}

		default:
			err = fmt.Errorf("Dir %s: unknown entry type %v", score.Hex(), entry.Type)
			return
		}

		// Return a node for each score.
		for _, score := range entry.Scores {
			adjacent = append(adjacent, FormatNodeName(dir, score))
		}
	}

	return
}

func (v *visitor) Visit(
	ctx context.Context,
	node string) (adjacent []string, err error) {
	// Parse the node name.
	dir, score, err := ParseNodeName(node)
	if err != nil {
		err = fmt.Errorf("ParseNodeName(%q): %v", node, err)
		return
	}

	if dir {
		adjacent, err = v.visitDir(ctx, score)
		return
	} else {
		err = v.visitFile(ctx, score)
		return
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"io"
	"strings"

	cmds "github.com/jbenet/go-ipfs/commands"
	u "github.com/jbenet/go-ipfs/util"

	tail "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/ActiveState/tail"
)

// Golang os.Args overrides * and replaces the character argument with
// an array which includes every file in the user's CWD. As a
// workaround, we use 'all' instead. The util library still uses * so
// we convert it at this step.
var logAllKeyword = "all"

var LogCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Interact with the daemon log output",
		ShortDescription: `
'ipfs log' contains utility commands to affect or read the logging
output of a running daemon.
`,
	},

	Subcommands: map[string]*cmds.Command{
		"level": logLevelCmd,
		"tail":  logTailCmd,
	},
}

var logLevelCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Change the logging level",
		ShortDescription: `
'ipfs log level' is a utility command used to change the logging
output of a running daemon.
`,
	},

	Arguments: []cmds.Argument{
		// TODO use a different keyword for 'all' because all can theoretically
		// clash with a subsystem name
		cmds.StringArg("subsystem", true, false, fmt.Sprintf("the subsystem logging identifier. Use '%s' for all subsystems.", logAllKeyword)),
		cmds.StringArg("level", true, false, "one of: debug, info, notice, warning, error, critical"),
	},
	Run: func(req cmds.Request, res cmds.Response) {

		args := req.Arguments()
		subsystem, level := args[0], args[1]

		if subsystem == logAllKeyword {
			subsystem = "*"
		}

		if err := u.SetLogLevel(subsystem, level); err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		s := fmt.Sprintf("Changed log level of '%s' to '%s'", subsystem, level)
		log.Info(s)
		res.SetOutput(&MessageOutput{s})
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: MessageTextMarshaler,
	},
	Type: MessageOutput{},
}

var logTailCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Read the logs",
		ShortDescription: `
'ipfs log tail' is a utility command used to read log output as it is written.
`,
	},

	Run: func(req cmds.Request, res cmds.Response) {
		path := fmt.Sprintf("%s/logs/events.log", req.Context().ConfigRoot)

		outChan := make(chan interface{})

		go func() {
			defer close(outChan)

			t, err := tail.TailFile(path, tail.Config{
				Location:  &tail.SeekInfo{0, 2},
				Follow:    true,
				MustExist: true,
				Logger:    tail.DiscardingLogger,
			})
			if err != nil {
				fmt.Println(err.Error())
				return
			}
			defer t.Stop()

			for line := range t.Lines {
				if line.Err != nil {
					fmt.Println(err.Error())
					return
				}
				// TODO: unpack the line text into a struct and output that
				outChan <- &MessageOutput{line.Text}
			}
		}()

		res.SetOutput((<-chan interface{})(outChan))
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			outChan, ok := res.Output().(<-chan interface{})
			if !ok {
				return nil, u.ErrCast()
			}

			return &cmds.ChannelMarshaler{
				Channel: outChan,
				Marshaler: func(v interface{}) (io.Reader, error) {
					output := v.(*MessageOutput)
					return strings.NewReader(output.Message + "\n"), nil
				},
			}, nil
		},
	},
	Type: MessageOutput{},
}
<commit_msg>core/commands: log tail: Return from goroutine when request context closes, resolves #659<commit_after>package commands

import (
	"fmt"
	"io"
	"strings"

	cmds "github.com/jbenet/go-ipfs/commands"
	u "github.com/jbenet/go-ipfs/util"

	tail "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/ActiveState/tail"
)

// Golang os.Args overrides * and replaces the character argument with
// an array which includes every file in the user's CWD. As a
// workaround, we use 'all' instead. The util library still uses * so
// we convert it at this step.
var logAllKeyword = "all"

var LogCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Interact with the daemon log output",
		ShortDescription: `
'ipfs log' contains utility commands to affect or read the logging
output of a running daemon.
`,
	},

	Subcommands: map[string]*cmds.Command{
		"level": logLevelCmd,
		"tail":  logTailCmd,
	},
}

var logLevelCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Change the logging level",
		ShortDescription: `
'ipfs log level' is a utility command used to change the logging
output of a running daemon.
`,
	},

	Arguments: []cmds.Argument{
		// TODO use a different keyword for 'all' because all can theoretically
		// clash with a subsystem name
		cmds.StringArg("subsystem", true, false, fmt.Sprintf("the subsystem logging identifier. Use '%s' for all subsystems.", logAllKeyword)),
		cmds.StringArg("level", true, false, "one of: debug, info, notice, warning, error, critical"),
	},
	Run: func(req cmds.Request, res cmds.Response) {

		args := req.Arguments()
		subsystem, level := args[0], args[1]

		if subsystem == logAllKeyword {
			subsystem = "*"
		}

		if err := u.SetLogLevel(subsystem, level); err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		s := fmt.Sprintf("Changed log level of '%s' to '%s'", subsystem, level)
		log.Info(s)
		res.SetOutput(&MessageOutput{s})
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: MessageTextMarshaler,
	},
	Type: MessageOutput{},
}

var logTailCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Read the logs",
		ShortDescription: `
'ipfs log tail' is a utility command used to read log output as it is written.
`,
	},

	Run: func(req cmds.Request, res cmds.Response) {
		path := fmt.Sprintf("%s/logs/events.log", req.Context().ConfigRoot)

		outChan := make(chan interface{})

		go func() {
			defer close(outChan)

			t, err := tail.TailFile(path, tail.Config{
				Location:  &tail.SeekInfo{0, 2},
				Follow:    true,
				MustExist: true,
				Logger:    tail.DiscardingLogger,
			})
			if err != nil {
				fmt.Println(err.Error())
				return
			}
			defer t.Stop()

			done := req.Context().Context.Done()

			for line := range t.Lines {
				// return when context closes
				select {
				case <-done:
					return
				default:
				}

				if line.Err != nil {
					fmt.Println(err.Error())
					return
				}
				// TODO: unpack the line text into a struct and output that
				outChan <- &MessageOutput{line.Text}
			}
		}()

		res.SetOutput((<-chan interface{})(outChan))
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			outChan, ok := res.Output().(<-chan interface{})
			if !ok {
				return nil, u.ErrCast()
			}

			return &cmds.ChannelMarshaler{
				Channel: outChan,
				Marshaler: func(v interface{}) (io.Reader, error) {
					output := v.(*MessageOutput)
					return strings.NewReader(output.Message + "\n"), nil
				},
			}, nil
		},
	},
	Type: MessageOutput{},
}
<|endoftext|>