<commit_before>package schedule

import (
	"github.com/0xfoo/punchcard/git"
	"io/ioutil"
	"math/rand"
	"strings"
	"time"
)

// RandomSchedule creates random commits over the past 365/366 days.
// These commits will be created in the location specified in the command.
func RandomSchedule(min, max int, location string) {
	git.Init(location)
	days := getDaysSinceDateMinusOneYear(time.Now())
	for day := range days {
		rnd := getRandomNumber(min, max)
		commits := RandomCommits(day, rnd)
		for commit := range commits {
			// TODO git add and commit file with given
			filename := "filename"
			git.Add(location, filename)
			git.Commit(location, commit.message, commit.dateTime.String())
		}
	}
}

// RandomCommits returns a channel of random commits for a given day.
func RandomCommits(day time.Time, rnd int) chan Commit {
	commitChannel := make(chan Commit)
	go func() {
		for i := 0; i < rnd; i++ {
			commitChannel <- Commit{
				dateTime: getRandomTime(day),
				message:  getRandomCommitMessage(),
			}
		}
		close(commitChannel)
	}()
	return commitChannel
}

// getRandomTime sets a random time on the given date.
func getRandomTime(day time.Time) time.Time {
	hours := time.Duration(getRandomNumber(0, 23)) * time.Hour
	minutes := time.Duration(getRandomNumber(0, 59)) * time.Minute
	seconds := time.Duration(getRandomNumber(0, 59)) * time.Second
	return day.Add(hours + minutes + seconds)
}

func getRandomCommitMessage() string {
	content, _ := ioutil.ReadFile(COMMIT_MESSAGE_BASE)
	words := strings.Split(string(content), " ")
	return getRandomWords(words, getRandomNumber(4, 8))
}

// getRandomNumber returns a number in the range of min and max.
func getRandomNumber(min, max int) int {
	if min == max {
		return min
	}
	return rand.Intn(max-min) + min
}

func getRandomWords(words []string, numberOfWords int) string {
	rndWords := make([]string, numberOfWords)
	for i := 0; i < numberOfWords; i++ {
		rndWords = append(rndWords, words(getRandomNumber(0, len(words))))
	}
	return strings.Join(rndWords, " ")
}
<commit_msg>Minor refactoring, using time in nanos as filename.<commit_after>package schedule

import (
	"github.com/0xfoo/punchcard/git"
	"io/ioutil"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

// RandomSchedule creates random commits over the past 365/366 days.
// These commits will be created in the location specified in the command.
func RandomSchedule(min, max int, location string) {
	git.Init(location)
	days := getDaysSinceDateMinusOneYear(time.Now())
	for day := range days {
		rnd := getRandomNumber(min, max)
		commits := RandomCommits(day, rnd)
		for commit := range commits {
			filename := strconv.Itoa(time.Now().Nanosecond())
			git.Add(location, filename)
			git.Commit(location, commit.message, commit.dateTime.String())
		}
	}
}

// RandomCommits returns a channel of random commits for a given day.
func RandomCommits(day time.Time, rnd int) chan Commit {
	commitChannel := make(chan Commit)
	go func() {
		for i := 0; i < rnd; i++ {
			commitChannel <- Commit{
				dateTime: getRandomTime(day),
				message:  getRandomCommitMessage(8),
			}
		}
		close(commitChannel)
	}()
	return commitChannel
}

// getRandomTime sets a random time on the given date.
func getRandomTime(day time.Time) time.Time {
	hours := time.Duration(getRandomNumber(0, 23)) * time.Hour
	minutes := time.Duration(getRandomNumber(0, 59)) * time.Minute
	seconds := time.Duration(getRandomNumber(0, 59)) * time.Second
	return day.Add(hours + minutes + seconds)
}

func getRandomCommitMessage(length int) string {
	content, _ := ioutil.ReadFile(COMMIT_MESSAGE_BASE)
	words := strings.Split(string(content), " ")
	return getRandomWords(words, getRandomNumber(1, length))
}

// getRandomNumber returns a number in the range of min and max.
func getRandomNumber(min, max int) int {
	if min == max {
		return min
	}
	return rand.Intn(max-min) + min
}

func getRandomWords(inWords []string, numWords int) string {
	outWords := make([]string, numWords)
	for i := 0; i < numWords; i++ {
		outWords = append(outWords, inWords[getRandomNumber(0, len(inWords))])
	}
	return strings.Join(outWords, " ")
}
<|endoftext|>


<commit_before>package sidecarhttp

import (
	"net/http"
	_ "net/http/pprof"
	"time"

	"github.com/Nitro/memberlist"
	"github.com/Nitro/sidecar/catalog"
	"github.com/gorilla/mux"
	log "github.com/sirupsen/logrus"
)

func makeHandler(fn func(http.ResponseWriter, *http.Request,
	*memberlist.Memberlist, *catalog.ServicesState, map[string]string),
	list *memberlist.Memberlist, state *catalog.ServicesState) http.HandlerFunc {

	return func(response http.ResponseWriter, req *http.Request) {
		fn(response, req, list, state, mux.Vars(req))
	}
}

func serversHandler(response http.ResponseWriter, req *http.Request, list *memberlist.Memberlist, state *catalog.ServicesState, params map[string]string) {
	defer req.Body.Close()

	response.Header().Set("Content-Type", "text/html")
	state.RLock()
	defer state.RUnlock()

	response.Write(
		[]byte(`

 			<meta http-equiv="refresh" content="4">

` + state.Format(list) + "
"))
}

type Member struct {
	Node    *memberlist.Node
	Updated time.Time
}

func uiRedirectHandler(response http.ResponseWriter, req *http.Request) {
	http.Redirect(response, req, "/ui/", 301)
}

func ServeHttp(list *memberlist.Memberlist, state *catalog.ServicesState) {
	srvrsHandle := makeHandler(serversHandler, list, state)
	staticFs := http.FileServer(http.Dir("views/static"))
	uiFs := http.FileServer(http.Dir("ui/app"))

	api := &SidecarApi{state: state, list: list}

	router := mux.NewRouter()
	router.HandleFunc("/", uiRedirectHandler).Methods("GET")
	router.HandleFunc("/servers", srvrsHandle).Methods("GET")
	router.PathPrefix("/static").Handler(http.StripPrefix("/static", staticFs))
	router.PathPrefix("/ui").Handler(http.StripPrefix("/ui", uiFs))
	router.PathPrefix("/api").Handler(http.StripPrefix("/api", api.HttpMux()))

	http.Handle("/", router)

	err := http.ListenAndServe("0.0.0.0:7777", nil)
	if err != nil {
		log.Fatalf("Can't start HTTP server: %s", err)
	}
}
<commit_msg>Add DEPRECATED mounts for /watch /state<commit_after>package sidecarhttp

import (
	"net/http"
	_ "net/http/pprof"
	"time"

	"github.com/Nitro/memberlist"
	"github.com/Nitro/sidecar/catalog"
	"github.com/gorilla/mux"
	log "github.com/sirupsen/logrus"
)

func makeHandler(fn func(http.ResponseWriter, *http.Request,
	*memberlist.Memberlist, *catalog.ServicesState, map[string]string),
	list *memberlist.Memberlist, state *catalog.ServicesState) http.HandlerFunc {

	return func(response http.ResponseWriter, req *http.Request) {
		fn(response, req, list, state, mux.Vars(req))
	}
}

func serversHandler(response http.ResponseWriter, req *http.Request, list *memberlist.Memberlist, state *catalog.ServicesState, params map[string]string) {
	defer req.Body.Close()

	response.Header().Set("Content-Type", "text/html")
	state.RLock()
	defer state.RUnlock()

	response.Write(
		[]byte(`

 			<meta http-equiv="refresh" content="4">

` + state.Format(list) + "
"))
}

type Member struct {
	Node    *memberlist.Node
	Updated time.Time
}

func uiRedirectHandler(response http.ResponseWriter, req *http.Request) {
	http.Redirect(response, req, "/ui/", 301)
}

func ServeHttp(list *memberlist.Memberlist, state *catalog.ServicesState) {
	srvrsHandle := makeHandler(serversHandler, list, state)
	staticFs := http.FileServer(http.Dir("views/static"))
	uiFs := http.FileServer(http.Dir("ui/app"))

	api := &SidecarApi{state: state, list: list}

	router := mux.NewRouter()
	router.HandleFunc("/", uiRedirectHandler).Methods("GET")
	router.HandleFunc("/servers", srvrsHandle).Methods("GET")
	router.PathPrefix("/static").Handler(http.StripPrefix("/static", staticFs))
	router.PathPrefix("/ui").Handler(http.StripPrefix("/ui", uiFs))
	router.PathPrefix("/api").Handler(http.StripPrefix("/api", api.HttpMux()))

	// DEPRECATED - to be removed once common clients are updated
	router.HandleFunc("/state.{extension}", wrap(api.stateHandler)).Methods("GET")
	router.HandleFunc("/watch", wrap(api.watchHandler)).Methods("GET")
	// ------------------------------------------------------------

	http.Handle("/", router)

	err := http.ListenAndServe("0.0.0.0:7777", nil)
	if err != nil {
		log.Fatalf("Can't start HTTP server: %s", err)
	}
}
<|endoftext|>


<commit_before>package maas

import (
	"bytes"
	. "launchpad.net/gocheck"
	"launchpad.net/gomaasapi"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/testing"
)

type EnvironSuite struct {
	ProviderSuite
}

var _ = Suite(new(EnvironSuite))

// getTestConfig creates a customized sample MAAS provider configuration.
func getTestConfig(name, server, oauth, secret string) *config.Config {
	ecfg, err := newConfig(map[string]interface{}{
		"name":         name,
		"maas-server":  server,
		"maas-oauth":   oauth,
		"admin-secret": secret,
	})
	if err != nil {
		panic(err)
	}
	return ecfg.Config
}

// makeEnviron creates a functional maasEnviron for a test.  Its configuration
// is a bit arbitrary and none of the test code's business.
func (suite *EnvironSuite) makeEnviron() *maasEnviron {
	config, err := config.New(map[string]interface{}{
		"name":            suite.environ.Name(),
		"type":            "maas",
		"admin-secret":    "local-secret",
		"authorized-keys": "foo",
		"ca-cert":         testing.CACert,
		"ca-private-key":  testing.CAKey,
		"maas-oauth":      "a:b:c",
		"maas-server":     suite.testMAASObject.URL().String(),
	})
	if err != nil {
		panic(err)
	}
	env, err := NewEnviron(config)
	if err != nil {
		panic(err)
	}
	return env
}

func (EnvironSuite) TestSetConfigUpdatesConfig(c *C) {
	cfg := getTestConfig("test env", "http://maas2.example.com", "a:b:c", "secret")
	env, err := NewEnviron(cfg)
	c.Check(err, IsNil)
	c.Check(env.name, Equals, "test env")

	anotherName := "another name"
	anotherServer := "http://maas.example.com"
	anotherOauth := "c:d:e"
	anotherSecret := "secret2"
	cfg2 := getTestConfig(anotherName, anotherServer, anotherOauth, anotherSecret)
	errSetConfig := env.SetConfig(cfg2)
	c.Check(errSetConfig, IsNil)
	c.Check(env.name, Equals, anotherName)
	authClient, _ := gomaasapi.NewAuthenticatedClient(anotherServer, anotherOauth)
	maas := gomaasapi.NewMAAS(*authClient)
	MAASServer := env.maasClientUnlocked
	c.Check(MAASServer, DeepEquals, maas)
}

func (EnvironSuite) TestNewEnvironSetsConfig(c *C) {
	name := "test env"
	cfg := getTestConfig(name, "http://maas.example.com", "a:b:c", "secret")

	env, err := NewEnviron(cfg)

	c.Check(err, IsNil)
	c.Check(env.name, Equals, name)
}

func (suite *EnvironSuite) TestInstancesReturnsInstances(c *C) {
	input := `{"system_id": "test"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	resourceURI, _ := node.GetField("resource_uri")
	instanceIds := []state.InstanceId{state.InstanceId(resourceURI)}

	instances, err := suite.environ.Instances(instanceIds)

	c.Check(err, IsNil)
	c.Check(len(instances), Equals, 1)
	c.Check(string(instances[0].Id()), Equals, resourceURI)
}

func (suite *EnvironSuite) TestInstancesReturnsNilIfEmptyParameter(c *C) {
	// Instances returns nil if the given parameter is empty.
	input := `{"system_id": "test"}`
	suite.testMAASObject.TestServer.NewNode(input)
	instances, err := suite.environ.Instances([]state.InstanceId{})

	c.Check(err, IsNil)
	c.Check(instances, IsNil)
}

func (suite *EnvironSuite) TestInstancesReturnsNilIfNilParameter(c *C) {
	// Instances returns nil if the given parameter is nil.
	input := `{"system_id": "test"}`
	suite.testMAASObject.TestServer.NewNode(input)
	instances, err := suite.environ.Instances(nil)

	c.Check(err, IsNil)
	c.Check(instances, IsNil)
}

func (suite *EnvironSuite) TestAllInstancesReturnsAllInstances(c *C) {
	input := `{"system_id": "test"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	resourceURI, _ := node.GetField("resource_uri")

	instances, err := suite.environ.AllInstances()

	c.Check(err, IsNil)
	c.Check(len(instances), Equals, 1)
	c.Check(string(instances[0].Id()), Equals, resourceURI)
}

func (suite *EnvironSuite) TestAllInstancesReturnsEmptySliceIfNoInstance(c *C) {
	instances, err := suite.environ.AllInstances()

	c.Check(err, IsNil)
	c.Check(len(instances), Equals, 0)
}

func (suite *EnvironSuite) TestInstancesReturnsErrorIfPartialInstances(c *C) {
	input1 := `{"system_id": "test"}`
	node1 := suite.testMAASObject.TestServer.NewNode(input1)
	resourceURI1, _ := node1.GetField("resource_uri")
	input2 := `{"system_id": "test2"}`
	suite.testMAASObject.TestServer.NewNode(input2)
	instanceId1 := state.InstanceId(resourceURI1)
	instanceId2 := state.InstanceId("unknown systemID")
	instanceIds := []state.InstanceId{instanceId1, instanceId2}

	instances, err := suite.environ.Instances(instanceIds)

	c.Check(err, Equals, environs.ErrPartialInstances)
	c.Check(len(instances), Equals, 1)
	c.Check(string(instances[0].Id()), Equals, resourceURI1)
}

func (suite *EnvironSuite) TestStartInstanceStartsInstance(c *C) {
	input := `{"system_id": "test"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	resourceURI, _ := node.GetField("resource_uri")

	instance, err := suite.environ.StartInstance(resourceURI, nil, nil, nil)

	c.Check(err, IsNil)
	c.Check(string(instance.Id()), Equals, resourceURI)
	operations := suite.testMAASObject.TestServer.NodeOperations()
	actions, found := operations["test"]
	c.Check(found, Equals, true)
	c.Check(actions, DeepEquals, []string{"start"})
}

func (suite *EnvironSuite) getInstance(systemId string) *maasInstance {
	input := `{"system_id": "` + systemId + `"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	return &maasInstance{&node, suite.environ}
}

func (suite *EnvironSuite) TestStopInstancesReturnsIfParameterEmpty(c *C) {
	suite.getInstance("test1")

	err := suite.environ.StopInstances([]environs.Instance{})
	c.Check(err, IsNil)
	operations := suite.testMAASObject.TestServer.NodeOperations()
	c.Check(operations, DeepEquals, map[string][]string{})
}

func (suite *EnvironSuite) TestStopInstancesStopsInstances(c *C) {
	instance1 := suite.getInstance("test1")
	instance2 := suite.getInstance("test2")
	suite.getInstance("test3")
	instances := []environs.Instance{instance1, instance2}

	err := suite.environ.StopInstances(instances)

	c.Check(err, IsNil)
	operations := suite.testMAASObject.TestServer.NodeOperations()
	expectedOperations := map[string][]string{"test1": {"stop"}, "test2": {"stop"}}
	c.Check(operations, DeepEquals, expectedOperations)
}

func (suite *EnvironSuite) TestQuiesceStateFileIsHappyWithoutStateFile(c *C) {
	err := suite.makeEnviron().quiesceStateFile()
	c.Check(err, IsNil)
}

func (suite *EnvironSuite) TestQuiesceStateFileFailsWithStateFile(c *C) {
	env := suite.makeEnviron()
	err := env.saveState(&bootstrapState{})
	c.Assert(err, IsNil)

	err = env.quiesceStateFile()

	c.Check(err, Not(IsNil))
}

func (suite *EnvironSuite) TestQuiesceStateFileFailsOnBrokenStateFile(c *C) {
	const content = "@#$(*&Y%!"
	reader := bytes.NewReader([]byte(content))
	env := suite.makeEnviron()
	err := env.Storage().Put(stateFile, reader, int64(len(content)))
	c.Assert(err, IsNil)

	err = env.quiesceStateFile()

	c.Check(err, Not(IsNil))
}

func (suite *EnvironSuite) TestBootstrap(c *C) {
	env := suite.makeEnviron()

	err := env.Bootstrap(true, []byte{}, []byte{})
	// TODO: Get this to succeed.
	unused(err)
	// c.Assert(err, IsNil)

	// TODO: Verify a simile of success.
}
<commit_msg>Test Storage() and PublicStorage().<commit_after>package maas

import (
	"bytes"
	. "launchpad.net/gocheck"
	"launchpad.net/gomaasapi"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/testing"
)

type EnvironSuite struct {
	ProviderSuite
}

var _ = Suite(new(EnvironSuite))

// getTestConfig creates a customized sample MAAS provider configuration.
func getTestConfig(name, server, oauth, secret string) *config.Config {
	ecfg, err := newConfig(map[string]interface{}{
		"name":         name,
		"maas-server":  server,
		"maas-oauth":   oauth,
		"admin-secret": secret,
	})
	if err != nil {
		panic(err)
	}
	return ecfg.Config
}

// makeEnviron creates a functional maasEnviron for a test.  Its configuration
// is a bit arbitrary and none of the test code's business.
func (suite *EnvironSuite) makeEnviron() *maasEnviron {
	config, err := config.New(map[string]interface{}{
		"name":            suite.environ.Name(),
		"type":            "maas",
		"admin-secret":    "local-secret",
		"authorized-keys": "foo",
		"ca-cert":         testing.CACert,
		"ca-private-key":  testing.CAKey,
		"maas-oauth":      "a:b:c",
		"maas-server":     suite.testMAASObject.URL().String(),
	})
	if err != nil {
		panic(err)
	}
	env, err := NewEnviron(config)
	if err != nil {
		panic(err)
	}
	return env
}

func (EnvironSuite) TestSetConfigUpdatesConfig(c *C) {
	cfg := getTestConfig("test env", "http://maas2.example.com", "a:b:c", "secret")
	env, err := NewEnviron(cfg)
	c.Check(err, IsNil)
	c.Check(env.name, Equals, "test env")

	anotherName := "another name"
	anotherServer := "http://maas.example.com"
	anotherOauth := "c:d:e"
	anotherSecret := "secret2"
	cfg2 := getTestConfig(anotherName, anotherServer, anotherOauth, anotherSecret)
	errSetConfig := env.SetConfig(cfg2)
	c.Check(errSetConfig, IsNil)
	c.Check(env.name, Equals, anotherName)
	authClient, _ := gomaasapi.NewAuthenticatedClient(anotherServer, anotherOauth)
	maas := gomaasapi.NewMAAS(*authClient)
	MAASServer := env.maasClientUnlocked
	c.Check(MAASServer, DeepEquals, maas)
}

func (EnvironSuite) TestNewEnvironSetsConfig(c *C) {
	name := "test env"
	cfg := getTestConfig(name, "http://maas.example.com", "a:b:c", "secret")

	env, err := NewEnviron(cfg)

	c.Check(err, IsNil)
	c.Check(env.name, Equals, name)
}

func (suite *EnvironSuite) TestInstancesReturnsInstances(c *C) {
	input := `{"system_id": "test"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	resourceURI, _ := node.GetField("resource_uri")
	instanceIds := []state.InstanceId{state.InstanceId(resourceURI)}

	instances, err := suite.environ.Instances(instanceIds)

	c.Check(err, IsNil)
	c.Check(len(instances), Equals, 1)
	c.Check(string(instances[0].Id()), Equals, resourceURI)
}

func (suite *EnvironSuite) TestInstancesReturnsNilIfEmptyParameter(c *C) {
	// Instances returns nil if the given parameter is empty.
	input := `{"system_id": "test"}`
	suite.testMAASObject.TestServer.NewNode(input)
	instances, err := suite.environ.Instances([]state.InstanceId{})

	c.Check(err, IsNil)
	c.Check(instances, IsNil)
}

func (suite *EnvironSuite) TestInstancesReturnsNilIfNilParameter(c *C) {
	// Instances returns nil if the given parameter is nil.
	input := `{"system_id": "test"}`
	suite.testMAASObject.TestServer.NewNode(input)
	instances, err := suite.environ.Instances(nil)

	c.Check(err, IsNil)
	c.Check(instances, IsNil)
}

func (suite *EnvironSuite) TestAllInstancesReturnsAllInstances(c *C) {
	input := `{"system_id": "test"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	resourceURI, _ := node.GetField("resource_uri")

	instances, err := suite.environ.AllInstances()

	c.Check(err, IsNil)
	c.Check(len(instances), Equals, 1)
	c.Check(string(instances[0].Id()), Equals, resourceURI)
}

func (suite *EnvironSuite) TestAllInstancesReturnsEmptySliceIfNoInstance(c *C) {
	instances, err := suite.environ.AllInstances()

	c.Check(err, IsNil)
	c.Check(len(instances), Equals, 0)
}

func (suite *EnvironSuite) TestInstancesReturnsErrorIfPartialInstances(c *C) {
	input1 := `{"system_id": "test"}`
	node1 := suite.testMAASObject.TestServer.NewNode(input1)
	resourceURI1, _ := node1.GetField("resource_uri")
	input2 := `{"system_id": "test2"}`
	suite.testMAASObject.TestServer.NewNode(input2)
	instanceId1 := state.InstanceId(resourceURI1)
	instanceId2 := state.InstanceId("unknown systemID")
	instanceIds := []state.InstanceId{instanceId1, instanceId2}

	instances, err := suite.environ.Instances(instanceIds)

	c.Check(err, Equals, environs.ErrPartialInstances)
	c.Check(len(instances), Equals, 1)
	c.Check(string(instances[0].Id()), Equals, resourceURI1)
}

func (suite *EnvironSuite) TestStorageReturnsStorage(c *C) {
	env := suite.makeEnviron()
	storage := env.Storage()
	c.Check(storage, NotNil)
	specificStorage := storage.(*maasStorage)
	c.Check(specificStorage.environUnlocked, Equals, env)
}

func (suite *EnvironSuite) TestPublicStorageIsNotImplemented(c *C) {
	env := suite.makeEnviron()
	c.Check(env.PublicStorage(), IsNil)
}

func (suite *EnvironSuite) TestStartInstanceStartsInstance(c *C) {
	input := `{"system_id": "test"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	resourceURI, _ := node.GetField("resource_uri")

	instance, err := suite.environ.StartInstance(resourceURI, nil, nil, nil)

	c.Check(err, IsNil)
	c.Check(string(instance.Id()), Equals, resourceURI)
	operations := suite.testMAASObject.TestServer.NodeOperations()
	actions, found := operations["test"]
	c.Check(found, Equals, true)
	c.Check(actions, DeepEquals, []string{"start"})
}

func (suite *EnvironSuite) getInstance(systemId string) *maasInstance {
	input := `{"system_id": "` + systemId + `"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	return &maasInstance{&node, suite.environ}
}

func (suite *EnvironSuite) TestStopInstancesReturnsIfParameterEmpty(c *C) {
	suite.getInstance("test1")

	err := suite.environ.StopInstances([]environs.Instance{})
	c.Check(err, IsNil)
	operations := suite.testMAASObject.TestServer.NodeOperations()
	c.Check(operations, DeepEquals, map[string][]string{})
}

func (suite *EnvironSuite) TestStopInstancesStopsInstances(c *C) {
	instance1 := suite.getInstance("test1")
	instance2 := suite.getInstance("test2")
	suite.getInstance("test3")
	instances := []environs.Instance{instance1, instance2}

	err := suite.environ.StopInstances(instances)

	c.Check(err, IsNil)
	operations := suite.testMAASObject.TestServer.NodeOperations()
	expectedOperations := map[string][]string{"test1": {"stop"}, "test2": {"stop"}}
	c.Check(operations, DeepEquals, expectedOperations)
}

func (suite *EnvironSuite) TestQuiesceStateFileIsHappyWithoutStateFile(c *C) {
	err := suite.makeEnviron().quiesceStateFile()
	c.Check(err, IsNil)
}

func (suite *EnvironSuite) TestQuiesceStateFileFailsWithStateFile(c *C) {
	env := suite.makeEnviron()
	err := env.saveState(&bootstrapState{})
	c.Assert(err, IsNil)

	err = env.quiesceStateFile()

	c.Check(err, Not(IsNil))
}

func (suite *EnvironSuite) TestQuiesceStateFileFailsOnBrokenStateFile(c *C) {
	const content = "@#$(*&Y%!"
	reader := bytes.NewReader([]byte(content))
	env := suite.makeEnviron()
	err := env.Storage().Put(stateFile, reader, int64(len(content)))
	c.Assert(err, IsNil)

	err = env.quiesceStateFile()

	c.Check(err, Not(IsNil))
}

func (suite *EnvironSuite) TestBootstrap(c *C) {
	env := suite.makeEnviron()

	err := env.Bootstrap(true, []byte{}, []byte{})
	// TODO: Get this to succeed.
	unused(err)
	// c.Assert(err, IsNil)

	// TODO: Verify a simile of success.
}
<|endoftext|>


<commit_before>package analyze

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"regexp"

	"github.com/deckarep/golang-set"
	"github.com/jzelinskie/geddit"
)

func AnalyzeComments(s *geddit.OAuthSession, comments []*geddit.Comment) error {
	r, err := regexp.Compile(`github\.com\/\w+\/\w+`)
	if err != nil {
		return err
	}
	for _, comment := range comments {
		if comment.Author == "github-stats-bot" {
			continue
		}
		if r.MatchString(comment.Body) {
			linkSet := mapset.NewSet()
			for _, link := range r.FindAllString(comment.Body, -1) {
				linkSet.Add(link)
			}
			var links []string
			for _, link := range linkSet.ToSlice() {
				links = append(links, link.(string))
			}
			if err = postReply(s, comment, links); err != nil {
				return err
			}
		}
	}
	return nil
}

func postReply(s *geddit.OAuthSession, comment *geddit.Comment, links []string) error {
	footer := "***\n^(This is Earth radio, and now here's human music ♫)\n\n^[Source](https://github.com/anaskhan96/github-stats-bot) ^| ^[PMme](https://np.reddit.com/message/compose?to=github-stats-bot)"
	var reply string
	for _, link := range links {
		var data map[string]interface{}
		if err := getStats(link, &data); err != nil {
			return err
		}
		if data["message"] == "Not Found" {
			return errors.New("Wrong GitHub API endpoint")
		}
		description := data["description"]
		stargazers := int(data["stargazers_count"].(float64))
		forks := int(data["forks_count"].(float64))
		issuesURL := "https://" + link + "/issues"
		pullsURL := "https://" + link + "/pulls"
		reply += fmt.Sprintf("\n[%s](https://%s)\n\n> *Description*: %v\n\n> *Stars*: %d\n\n> *Forks*: %d\n\n> [Issues](%s) | [Pull Requests](%s)\n\n",
			link[11:], link, description, stargazers, forks, issuesURL, pullsURL)
	}
	reply += footer
	if _, err := s.Reply(comment, reply); err != nil {
		return err
	}
	return nil
}

func getStats(link string, data *map[string]interface{}) error {
	res, err := http.Get("https://api.github.com/repos/" + link[11:])
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
		return err
	}
	return nil
}
<commit_msg>interface error fix<commit_after>package analyze

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"regexp"

	"github.com/deckarep/golang-set"
	"github.com/jzelinskie/geddit"
)

func AnalyzeComments(s *geddit.OAuthSession, comments []*geddit.Comment) error {
	r, err := regexp.Compile(`github\.com\/\w+\/\w+`)
	if err != nil {
		return err
	}
	for _, comment := range comments {
		if comment.Author == "github-stats-bot" {
			continue
		}
		if r.MatchString(comment.Body) {
			linkSet := mapset.NewSet()
			for _, link := range r.FindAllString(comment.Body, -1) {
				linkSet.Add(link)
			}
			var links []string
			for _, link := range linkSet.ToSlice() {
				links = append(links, link.(string))
			}
			if err = postReply(s, comment, links); err != nil {
				return err
			}
		}
	}
	return nil
}

func postReply(s *geddit.OAuthSession, comment *geddit.Comment, links []string) error {
	footer := "***\n^(This is Earth radio, and now here's human music ♫)\n\n^[Source](https://github.com/anaskhan96/github-stats-bot) ^| ^[PMme](https://np.reddit.com/message/compose?to=github-stats-bot)"
	var reply string
	for _, link := range links {
		var data map[string]interface{}
		if err := getStats(link, &data); err != nil {
			return err
		}
		if data["message"] == "Not Found" {
			return errors.New("Wrong GitHub API endpoint")
		}
		description := data["description"]
		stargazers := data["stargazers_count"]
		forks := data["forks_count"]
		issuesURL := "https://" + link + "/issues"
		pullsURL := "https://" + link + "/pulls"
		reply += fmt.Sprintf("\n[%s](https://%s)\n\n> *Description*: %v\n\n> *Stars*: %v\n\n> *Forks*: %v\n\n> [Issues](%s) | [Pull Requests](%s)\n\n",
			link[11:], link, description, stargazers, forks, issuesURL, pullsURL)
	}
	reply += footer
	if _, err := s.Reply(comment, reply); err != nil {
		return err
	}
	return nil
}

func getStats(link string, data *map[string]interface{}) error {
	res, err := http.Get("https://api.github.com/repos/" + link[11:])
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package weed_server

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/stats"
	"github.com/chrislusf/seaweedfs/weed/storage/needle"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	OS_UID = uint32(os.Getuid())
	OS_GID = uint32(os.Getgid())

	ErrReadOnly = errors.New("read only")
)

type FilerPostResult struct {
	Name  string `json:"name,omitempty"`
	Size  int64  `json:"size,omitempty"`
	Error string `json:"error,omitempty"`
}

func (fs *FilerServer) assignNewFileInfo(so *operation.StorageOption) (fileId, urlLocation string, auth security.EncodedJwt, err error) {

	stats.FilerRequestCounter.WithLabelValues("assign").Inc()
	start := time.Now()
	defer func() { stats.FilerRequestHistogram.WithLabelValues("assign").Observe(time.Since(start).Seconds()) }()

	ar, altRequest := so.ToAssignRequests(1)

	assignResult, ae := operation.Assign(fs.filer.GetMaster, fs.grpcDialOption, ar, altRequest)
	if ae != nil {
		glog.Errorf("failing to assign a file id: %v", ae)
		err = ae
		return
	}
	fileId = assignResult.Fid
	urlLocation = "http://" + assignResult.Url + "/" + assignResult.Fid
	if so.Fsync {
		urlLocation += "?fsync=true"
	}
	auth = assignResult.Auth
	return
}

func (fs *FilerServer) PostHandler(w http.ResponseWriter, r *http.Request, contentLength int64) {

	ctx := context.Background()

	query := r.URL.Query()
	so, err := fs.detectStorageOption0(r.RequestURI,
		query.Get("collection"),
		query.Get("replication"),
		query.Get("ttl"),
		query.Get("disk"),
		query.Get("fsync"),
		query.Get("dataCenter"),
		query.Get("rack"),
		query.Get("dataNode"),
	)
	if err != nil {
		if err == ErrReadOnly {
			w.WriteHeader(http.StatusInsufficientStorage)
		} else {
			glog.V(1).Infoln("post", r.RequestURI, ":", err.Error())
			w.WriteHeader(http.StatusInternalServerError)
		}
		return
	}

	if query.Has("from") {
		fs.move(ctx, w, r, so)
	} else {
		fs.autoChunk(ctx, w, r, contentLength, so)
	}

	util.CloseRequest(r)

}

func (fs *FilerServer) move(ctx context.Context, w http.ResponseWriter, r *http.Request, so *operation.StorageOption) {
	src := r.URL.Query().Get("from")
	dst := r.URL.Path

	glog.V(2).Infof("FilerServer.move %v to %v", src, dst)

	var err error
	if src, err = clearName(src); err != nil {
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}
	if dst, err = clearName(dst); err != nil {
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}
	src = strings.TrimRight(src, "/")
	if src == "" {
		err = fmt.Errorf("invalid source '/'")
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	srcPath := util.FullPath(src)
	dstPath := util.FullPath(dst)
	srcEntry, err := fs.filer.FindEntry(ctx, srcPath)
	if err != nil {
		err = fmt.Errorf("failed to get src entry '%s', err: %s", src, err)
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	oldDir, oldName := srcPath.DirAndName()
	newDir, newName := dstPath.DirAndName()
	newName = util.Nvl(newName, oldName)

	dstEntry, err := fs.filer.FindEntry(ctx, util.FullPath(strings.TrimRight(dst, "/")))
	if err != nil && err != filer_pb.ErrNotFound {
		err = fmt.Errorf("failed to get dst entry '%s', err: %s", dst, err)
		writeJsonError(w, r, http.StatusInternalServerError, err)
		return
	}
	if err == nil && !dstEntry.IsDirectory() && srcEntry.IsDirectory() {
		err = fmt.Errorf("move: cannot overwrite non-directory '%s' with directory '%s'", dst, src)
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	_, err = fs.AtomicRenameEntry(ctx, &filer_pb.AtomicRenameEntryRequest{
		OldDirectory: oldDir,
		OldName:      oldName,
		NewDirectory: newDir,
		NewName:      newName,
	})
	if err != nil {
		err = fmt.Errorf("failed to move entry from '%s' to '%s', err: %s", src, dst, err)
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

// curl -X DELETE http://localhost:8888/path/to
// curl -X DELETE http://localhost:8888/path/to?recursive=true
// curl -X DELETE http://localhost:8888/path/to?recursive=true&ignoreRecursiveError=true
// curl -X DELETE http://localhost:8888/path/to?recursive=true&skipChunkDeletion=true
func (fs *FilerServer) DeleteHandler(w http.ResponseWriter, r *http.Request) {

	isRecursive := r.FormValue("recursive") == "true"
	if !isRecursive && fs.option.recursiveDelete {
		if r.FormValue("recursive") != "false" {
			isRecursive = true
		}
	}
	ignoreRecursiveError := r.FormValue("ignoreRecursiveError") == "true"
	skipChunkDeletion := r.FormValue("skipChunkDeletion") == "true"

	objectPath := r.URL.Path
	if len(r.URL.Path) > 1 && strings.HasSuffix(objectPath, "/") {
		objectPath = objectPath[0 : len(objectPath)-1]
	}

	err := fs.filer.DeleteEntryMetaAndData(context.Background(), util.FullPath(objectPath), isRecursive, ignoreRecursiveError, !skipChunkDeletion, false, nil)
	if err != nil {
		glog.V(1).Infoln("deleting", objectPath, ":", err.Error())
		httpStatus := http.StatusInternalServerError
		if err == filer_pb.ErrNotFound {
			httpStatus = http.StatusNoContent
		}
		writeJsonError(w, r, httpStatus, err)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func (fs *FilerServer) detectStorageOption(requestURI, qCollection, qReplication string, ttlSeconds int32, diskType, dataCenter, rack, dataNode string) (*operation.StorageOption, error) {

	rule := fs.filer.FilerConf.MatchStorageRule(requestURI)

	if rule.ReadOnly {
		return nil, ErrReadOnly
	}

	// required by buckets folder
	bucketDefaultCollection, bucketDefaultReplication, fsync := "", "", false
	if strings.HasPrefix(requestURI, fs.filer.DirBucketsPath+"/") {
		bucketDefaultCollection = fs.filer.DetectBucket(util.FullPath(requestURI))
		bucketDefaultReplication, fsync = fs.filer.ReadBucketOption(bucketDefaultCollection)
	}

	if ttlSeconds == 0 {
		ttl, err := needle.ReadTTL(rule.GetTtl())
		if err != nil {
			glog.Errorf("fail to parse %s ttl setting %s: %v", rule.LocationPrefix, rule.Ttl, err)
		}
		ttlSeconds = int32(ttl.Minutes()) * 60
	}

	return &operation.StorageOption{
		Replication:       util.Nvl(qReplication, rule.Replication, bucketDefaultReplication, fs.option.DefaultReplication),
		Collection:        util.Nvl(qCollection, rule.Collection, bucketDefaultCollection, fs.option.Collection),
		DataCenter:        util.Nvl(dataCenter, rule.DataCenter, fs.option.DataCenter),
		Rack:              util.Nvl(rack, rule.Rack, fs.option.Rack),
		DataNode:          util.Nvl(dataNode, rule.DataNode, fs.option.DataNode),
		TtlSeconds:        ttlSeconds,
		DiskType:          util.Nvl(diskType, rule.DiskType),
		Fsync:             fsync || rule.Fsync,
		VolumeGrowthCount: rule.VolumeGrowthCount,
	}, nil
}

func (fs *FilerServer) detectStorageOption0(requestURI, qCollection, qReplication string, qTtl string, diskType string, fsync string, dataCenter, rack, dataNode string) (*operation.StorageOption, error) {

	ttl, err := needle.ReadTTL(qTtl)
	if err != nil {
		glog.Errorf("fail to parse ttl %s: %v", qTtl, err)
	}

	so, err := fs.detectStorageOption(requestURI, qCollection, qReplication, int32(ttl.Minutes())*60, diskType, dataCenter, rack, dataNode)
	if so != nil {
		so.Fsync = fsync == "true"
	}

	return so, err
}
<commit_msg>use "mv.from" for moving files<commit_after>package weed_server

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/operation"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/stats"
	"github.com/chrislusf/seaweedfs/weed/storage/needle"
	"github.com/chrislusf/seaweedfs/weed/util"
)

var (
	OS_UID = uint32(os.Getuid())
	OS_GID = uint32(os.Getgid())

	ErrReadOnly = errors.New("read only")
)

type FilerPostResult struct {
	Name  string `json:"name,omitempty"`
	Size  int64  `json:"size,omitempty"`
	Error string `json:"error,omitempty"`
}

func (fs *FilerServer) assignNewFileInfo(so *operation.StorageOption) (fileId, urlLocation string, auth security.EncodedJwt, err error) {

	stats.FilerRequestCounter.WithLabelValues("assign").Inc()
	start := time.Now()
	defer func() { stats.FilerRequestHistogram.WithLabelValues("assign").Observe(time.Since(start).Seconds()) }()

	ar, altRequest := so.ToAssignRequests(1)

	assignResult, ae := operation.Assign(fs.filer.GetMaster, fs.grpcDialOption, ar, altRequest)
	if ae != nil {
		glog.Errorf("failing to assign a file id: %v", ae)
		err = ae
		return
	}
	fileId = assignResult.Fid
	urlLocation = "http://" + assignResult.Url + "/" + assignResult.Fid
	if so.Fsync {
		urlLocation += "?fsync=true"
	}
	auth = assignResult.Auth
	return
}

func (fs *FilerServer) PostHandler(w http.ResponseWriter, r *http.Request, contentLength int64) {

	ctx := context.Background()

	query := r.URL.Query()
	so, err := fs.detectStorageOption0(r.RequestURI,
		query.Get("collection"),
		query.Get("replication"),
		query.Get("ttl"),
		query.Get("disk"),
		query.Get("fsync"),
		query.Get("dataCenter"),
		query.Get("rack"),
		query.Get("dataNode"),
	)
	if err != nil {
		if err == ErrReadOnly {
			w.WriteHeader(http.StatusInsufficientStorage)
		} else {
			glog.V(1).Infoln("post", r.RequestURI, ":", err.Error())
			w.WriteHeader(http.StatusInternalServerError)
		}
		return
	}

	if query.Has("mv.from") {
		fs.move(ctx, w, r, so)
	} else {
		fs.autoChunk(ctx, w, r, contentLength, so)
	}

	util.CloseRequest(r)

}

func (fs *FilerServer) move(ctx context.Context, w http.ResponseWriter, r *http.Request, so *operation.StorageOption) {
	src := r.URL.Query().Get("mv.from")
	dst := r.URL.Path

	glog.V(2).Infof("FilerServer.move %v to %v", src, dst)

	var err error
	if src, err = clearName(src); err != nil {
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}
	if dst, err = clearName(dst); err != nil {
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}
	src = strings.TrimRight(src, "/")
	if src == "" {
		err = fmt.Errorf("invalid source '/'")
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	srcPath := util.FullPath(src)
	dstPath := util.FullPath(dst)
	srcEntry, err := fs.filer.FindEntry(ctx, srcPath)
	if err != nil {
		err = fmt.Errorf("failed to get src entry '%s', err: %s", src, err)
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	oldDir, oldName := srcPath.DirAndName()
	newDir, newName := dstPath.DirAndName()
	newName = util.Nvl(newName, oldName)

	dstEntry, err := fs.filer.FindEntry(ctx, util.FullPath(strings.TrimRight(dst, "/")))
	if err != nil && err != filer_pb.ErrNotFound {
		err = fmt.Errorf("failed to get dst entry '%s', err: %s", dst, err)
		writeJsonError(w, r, http.StatusInternalServerError, err)
		return
	}
	if err == nil && !dstEntry.IsDirectory() && srcEntry.IsDirectory() {
		err = fmt.Errorf("move: cannot overwrite non-directory '%s' with directory '%s'", dst, src)
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	_, err = fs.AtomicRenameEntry(ctx, &filer_pb.AtomicRenameEntryRequest{
		OldDirectory: oldDir,
		OldName:      oldName,
		NewDirectory: newDir,
		NewName:      newName,
	})
	if err != nil {
		err = fmt.Errorf("failed to move entry from '%s' to '%s', err: %s", src, dst, err)
		writeJsonError(w, r, http.StatusBadRequest, err)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

// curl -X DELETE http://localhost:8888/path/to
// curl -X DELETE http://localhost:8888/path/to?recursive=true
// curl -X DELETE http://localhost:8888/path/to?recursive=true&ignoreRecursiveError=true
// curl -X DELETE http://localhost:8888/path/to?recursive=true&skipChunkDeletion=true
func (fs *FilerServer) DeleteHandler(w http.ResponseWriter, r *http.Request) {

	isRecursive := r.FormValue("recursive") == "true"
	if !isRecursive && fs.option.recursiveDelete {
		if r.FormValue("recursive") != "false" {
			isRecursive = true
		}
	}
	ignoreRecursiveError := r.FormValue("ignoreRecursiveError") == "true"
	skipChunkDeletion := r.FormValue("skipChunkDeletion") == "true"

	objectPath := r.URL.Path
	if len(r.URL.Path) > 1 && strings.HasSuffix(objectPath, "/") {
		objectPath = objectPath[0 : len(objectPath)-1]
	}

	err := fs.filer.DeleteEntryMetaAndData(context.Background(), util.FullPath(objectPath), isRecursive, ignoreRecursiveError, !skipChunkDeletion, false, nil)
	if err != nil {
		glog.V(1).Infoln("deleting", objectPath, ":", err.Error())
		httpStatus := http.StatusInternalServerError
		if err == filer_pb.ErrNotFound {
			httpStatus = http.StatusNoContent
		}
		writeJsonError(w, r, httpStatus, err)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func (fs *FilerServer) detectStorageOption(requestURI, qCollection, qReplication string, ttlSeconds int32, diskType, dataCenter, rack, dataNode string) (*operation.StorageOption, error) {

	rule := fs.filer.FilerConf.MatchStorageRule(requestURI)

	if rule.ReadOnly {
		return nil, ErrReadOnly
	}

	// required by buckets folder
	bucketDefaultCollection, bucketDefaultReplication, fsync := "", "", false
	if strings.HasPrefix(requestURI, fs.filer.DirBucketsPath+"/") {
		bucketDefaultCollection = fs.filer.DetectBucket(util.FullPath(requestURI))
		bucketDefaultReplication, fsync = fs.filer.ReadBucketOption(bucketDefaultCollection)
	}

	if ttlSeconds == 0 {
		ttl, err := needle.ReadTTL(rule.GetTtl())
		if err != nil {
			glog.Errorf("fail to parse %s ttl setting %s: %v", rule.LocationPrefix, rule.Ttl, err)
		}
		ttlSeconds = int32(ttl.Minutes()) * 60
	}

	return &operation.StorageOption{
		Replication:       util.Nvl(qReplication, rule.Replication, bucketDefaultReplication, fs.option.DefaultReplication),
		Collection:        util.Nvl(qCollection, rule.Collection, bucketDefaultCollection, fs.option.Collection),
		DataCenter:        util.Nvl(dataCenter, rule.DataCenter, fs.option.DataCenter),
		Rack:              util.Nvl(rack, rule.Rack, fs.option.Rack),
		DataNode:          util.Nvl(dataNode, rule.DataNode, fs.option.DataNode),
		TtlSeconds:        ttlSeconds,
		DiskType:          util.Nvl(diskType, rule.DiskType),
		Fsync:             fsync || rule.Fsync,
		VolumeGrowthCount: rule.VolumeGrowthCount,
	}, nil
}

func (fs *FilerServer) detectStorageOption0(requestURI, qCollection, qReplication string, qTtl string, diskType string, fsync string, dataCenter, rack, dataNode string) (*operation.StorageOption, error) {

	ttl, err := needle.ReadTTL(qTtl)
	if err != nil {
		glog.Errorf("fail to parse ttl %s: %v", qTtl, err)
	}

	so, err := fs.detectStorageOption(requestURI, qCollection, qReplication, int32(ttl.Minutes())*60, diskType, dataCenter, rack, dataNode)
	if so != nil {
		so.Fsync = fsync == "true"
	}

	return so, err
}
<|endoftext|>


<commit_before>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package rotate

import (
	"errors"
	"io/ioutil"
	"strconv"
	"strings"
)

const indexPlaceholder = "%i"

// ErrIndexNotExists 格式化字符串 %i 不存在
var ErrIndexNotExists = errors.New("必须存在 %i")

var dateRelpacer = strings.NewReplacer(
	"%y", "06",
	"%Y", "2006",
	"%m", "01",
	"%d", "02",
	"%h", "03",
	"%H", "15")

func parseFormat(format string) (prefix, suffix string, err error) {
	index := strings.Index(format, indexPlaceholder)
	if index < 0 {
		return "", "", ErrIndexNotExists
	}

	prefix = format[:index]
	suffix = format[index+len(indexPlaceholder):]

	return dateRelpacer.Replace(prefix), dateRelpacer.Replace(suffix), nil
}

// 获取指定目录下，去掉前后缀之后，最大的索引值。
func getIndex(dir, prefix, suffix string) (int, error) {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return 0, err
	}

	var index int
	for _, f := range fs {
		name := f.Name()

		if !strings.HasPrefix(name, prefix) || !strings.HasSuffix(name, suffix) {
			continue
		}

		istr := strings.TrimSuffix(strings.TrimPrefix(f.Name(), prefix), suffix)
		i, err := strconv.Atoi(istr)
		if err != nil {
			continue
		}

		if i > index {
			index = i
		}
	}

	return index, nil
}
<commit_msg>修正 windows 下测试错误<commit_after>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package rotate

import (
	"errors"
	"io/ioutil"
	"path/filepath"
	"strconv"
	"strings"
)

const indexPlaceholder = "%i"

// ErrIndexNotExists 格式化字符串 %i 不存在
var ErrIndexNotExists = errors.New("必须存在 %i")

var dateRelpacer = strings.NewReplacer(
	"%y", "06",
	"%Y", "2006",
	"%m", "01",
	"%d", "02",
	"%h", "03",
	"%H", "15")

func parseFormat(format string) (prefix, suffix string, err error) {
	index := strings.Index(format, indexPlaceholder)
	if index < 0 {
		return "", "", ErrIndexNotExists
	}

	prefix = format[:index]
	suffix = format[index+len(indexPlaceholder):]

	return dateRelpacer.Replace(prefix), dateRelpacer.Replace(suffix), nil
}

// 获取指定目录下，去掉前后缀之后，最大的索引值。
func getIndex(dir, prefix, suffix string) (int, error) {
	dir, err := filepath.Abs(dir)
	if err != nil {
		return 0, err
	}

	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return 0, err
	}

	var index int
	for _, f := range fs {
		name := f.Name()

		if !strings.HasPrefix(name, prefix) || !strings.HasSuffix(name, suffix) {
			continue
		}

		istr := strings.TrimSuffix(strings.TrimPrefix(f.Name(), prefix), suffix)
		i, err := strconv.Atoi(istr)
		if err != nil {
			continue
		}

		if i > index {
			index = i
		}
	}

	return index, nil
}
<|endoftext|>


<commit_before>package slackboard

const (
	Version = "0.2.0"
)
<commit_msg>bumped version to 0.2.1.<commit_after>package slackboard

const (
	Version = "0.2.1"
)
<|endoftext|>


<commit_before>package service

import (
	"encoding/json"
	"net/url"
	"path"

	"github.com/coreos/go-etcd/etcd"
	"github.com/op/go-logging"
)

const (
	servicePrefix  = "service"
	frontEndPrefix = "frontend"
)

type etcdBackend struct {
	client    *etcd.Client
	waitIndex uint64
	Logger    *logging.Logger
	prefix    string
}

func NewEtcdBackend(logger *logging.Logger, uri *url.URL) Backend {
	urls := make([]string, 0)
	if uri.Host != "" {
		urls = append(urls, "http://"+uri.Host)
	}
	return &etcdBackend{
		client: etcd.NewClient(urls),
		prefix: uri.Path,
		Logger: logger,
	}
}

// Watch for changes on a path and return where there is a change.
func (eb *etcdBackend) Watch() error {
	resp, err := eb.client.Watch(eb.prefix, eb.waitIndex, true, nil, nil)
	if err != nil {
		return maskAny(err)
	} else {
		eb.waitIndex = resp.EtcdIndex + 1
		return nil
	}
}

// Load all registered services
func (eb *etcdBackend) Services() ([]ServiceRegistration, error) {
	etcdPath := path.Join(eb.prefix, servicePrefix)
	sort := false
	recursive := true
	resp, err := eb.client.Get(etcdPath, sort, recursive)
	if err != nil {
		return nil, maskAny(err)
	}
	list := []ServiceRegistration{}
	if resp.Node == nil {
		return list, nil
	}
	for _, serviceNode := range resp.Node.Nodes {
		sr := ServiceRegistration{Name: path.Base(serviceNode.Key)}
		for _, backendNode := range serviceNode.Nodes {
			sr.Backends = append(sr.Backends, backendNode.Value)
		}
		list = append(list, sr)
	}

	return list, nil
}

type frontendRecord struct {
	Selectors     []frontendSelectorRecord `json:"selectors"`
	Service       string                   `json:"service,omitempty"`
	HttpCheckPath string                   `json:"http-check-path,omitempty"`
}

type frontendSelectorRecord struct {
	Domain     string `json:"domain,omitempty"`
	SslCert    string `json:ssl-cert,ompitempty"`
	PathPrefix string `json:"path-prefix,omitempty"`
}

// Load all registered front-ends
func (eb *etcdBackend) FrontEnds() ([]FrontEndRegistration, error) {
	etcdPath := path.Join(eb.prefix, frontEndPrefix)
	sort := false
	recursive := false
	resp, err := eb.client.Get(etcdPath, sort, recursive)
	if err != nil {
		return nil, maskAny(err)
	}
	list := []FrontEndRegistration{}
	if resp.Node == nil {
		return list, nil
	}
	for _, frontEndNode := range resp.Node.Nodes {
		rawJson := frontEndNode.Value
		record := &frontendRecord{}
		if err := json.Unmarshal([]byte(rawJson), record); err != nil {
			eb.Logger.Error("Cannot unmarshal registration of %s", frontEndNode.Key)
			continue
		}

		reg := FrontEndRegistration{
			Name:          path.Base(frontEndNode.Key),
			Service:       record.Service,
			HttpCheckPath: record.HttpCheckPath,
		}
		for _, sel := range record.Selectors {
			reg.Selectors = append(reg.Selectors, FrontEndSelector{
				Domain:     sel.Domain,
				SslCert:    sel.SslCert,
				PathPrefix: sel.PathPrefix,
			})
		}
		list = append(list, reg)
	}

	return list, nil
}
<commit_msg>Fixed ssl-cert json tag<commit_after>package service

import (
	"encoding/json"
	"net/url"
	"path"

	"github.com/coreos/go-etcd/etcd"
	"github.com/op/go-logging"
)

const (
	servicePrefix  = "service"
	frontEndPrefix = "frontend"
)

type etcdBackend struct {
	client    *etcd.Client
	waitIndex uint64
	Logger    *logging.Logger
	prefix    string
}

func NewEtcdBackend(logger *logging.Logger, uri *url.URL) Backend {
	urls := make([]string, 0)
	if uri.Host != "" {
		urls = append(urls, "http://"+uri.Host)
	}
	return &etcdBackend{
		client: etcd.NewClient(urls),
		prefix: uri.Path,
		Logger: logger,
	}
}

// Watch for changes on a path and return where there is a change.
func (eb *etcdBackend) Watch() error {
	resp, err := eb.client.Watch(eb.prefix, eb.waitIndex, true, nil, nil)
	if err != nil {
		return maskAny(err)
	} else {
		eb.waitIndex = resp.EtcdIndex + 1
		return nil
	}
}

// Load all registered services
func (eb *etcdBackend) Services() ([]ServiceRegistration, error) {
	etcdPath := path.Join(eb.prefix, servicePrefix)
	sort := false
	recursive := true
	resp, err := eb.client.Get(etcdPath, sort, recursive)
	if err != nil {
		return nil, maskAny(err)
	}
	list := []ServiceRegistration{}
	if resp.Node == nil {
		return list, nil
	}
	for _, serviceNode := range resp.Node.Nodes {
		sr := ServiceRegistration{Name: path.Base(serviceNode.Key)}
		for _, backendNode := range serviceNode.Nodes {
			sr.Backends = append(sr.Backends, backendNode.Value)
		}
		list = append(list, sr)
	}

	return list, nil
}

type frontendRecord struct {
	Selectors     []frontendSelectorRecord `json:"selectors"`
	Service       string                   `json:"service,omitempty"`
	HttpCheckPath string                   `json:"http-check-path,omitempty"`
}

type frontendSelectorRecord struct {
	Domain     string `json:"domain,omitempty"`
	SslCert    string `json:ssl-cert,omitempty"`
	PathPrefix string `json:"path-prefix,omitempty"`
}

// Load all registered front-ends
func (eb *etcdBackend) FrontEnds() ([]FrontEndRegistration, error) {
	etcdPath := path.Join(eb.prefix, frontEndPrefix)
	sort := false
	recursive := false
	resp, err := eb.client.Get(etcdPath, sort, recursive)
	if err != nil {
		return nil, maskAny(err)
	}
	list := []FrontEndRegistration{}
	if resp.Node == nil {
		return list, nil
	}
	for _, frontEndNode := range resp.Node.Nodes {
		rawJson := frontEndNode.Value
		record := &frontendRecord{}
		if err := json.Unmarshal([]byte(rawJson), record); err != nil {
			eb.Logger.Error("Cannot unmarshal registration of %s", frontEndNode.Key)
			continue
		}

		reg := FrontEndRegistration{
			Name:          path.Base(frontEndNode.Key),
			Service:       record.Service,
			HttpCheckPath: record.HttpCheckPath,
		}
		for _, sel := range record.Selectors {
			reg.Selectors = append(reg.Selectors, FrontEndSelector{
				Domain:     sel.Domain,
				SslCert:    sel.SslCert,
				PathPrefix: sel.PathPrefix,
			})
		}
		list = append(list, reg)
	}

	return list, nil
}
<|endoftext|>


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

package gobuild

import (
	"exec";
	"fmt";
	"go/ast";
	"go/parser";
	"os";
	"path";
	"sort";
	"strconv";
	"strings";
)

var (
	theChar string;
	goarch string;
	goos string;
	bin = make(map[string] string);
)

var theChars = map[string] string {
	"amd64": "6",
	"386": "8",
	"arm": "5"
}

const ObjDir = "_obj"

func fatal(args ...) {
	fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprint(args));
	os.Exit(1);
}

func init() {
	var err os.Error;
	goarch, err = os.Getenv("GOARCH");
	goos, err = os.Getenv("GOOS");

	var ok bool;
	theChar, ok = theChars[goarch];
	if !ok {
		fatal("unknown $GOARCH: ", goarch);
	}

	var binaries = []string{
		theChar + "g",
		theChar + "c",
		theChar + "a",
		"6ar",	// sic
	};

	for i, v := range binaries {
		var s string;
		if s, err = exec.LookPath(v); err != nil {
			fatal("cannot find binary ", v);
		}
		bin[v] = s;
	}
}

func PushString(v *[]string, p string) {
	n := len(v);
	if n >= cap(v) {
		m := 2*n + 10;
		a := make([]string, n, m);
		for i := range *v {
			a[i] = v[i];
		}
		*v = a;
	}
	*v = v[0:n+1];
	v[n] = p;
}

func run(argv []string, display bool) (ok bool) {
	argv0 := bin[argv[0]];
	output := exec.DevNull;
	if display {
		output = exec.PassThrough;
	}
	p, err1 := exec.Run(argv0, argv, os.Environ(), exec.DevNull, output, output);
	if err1 != nil {
		return false;
	}
	w, err2 := p.Wait(0);
	if err2 != nil {
		return false;
	}
	return w.Exited() && w.ExitStatus() == 0;
}

func Build(cmd []string, file string, display bool) (ok bool) {
	if display {
		fmt.Fprint(os.Stderr, "$ ");
		for i, s := range cmd {
			fmt.Fprint(os.Stderr, s[i], " ");
		}
		fmt.Fprint(os.Stderr, file, "\n");
	}

	var argv []string;
	for i, c := range cmd {
		PushString(&argv, c);
	}
	PushString(&argv, file);
	return run(argv, display);
}

func Archive(pkg string, files []string) {
	argv := []string{ "6ar", "grc", pkg };
	for i, file := range files {
		PushString(&argv, file);
	}
	if !run(argv, true) {
		fatal("archive failed");
	}
}

func Compiler(file string) []string {
	switch {
	case strings.HasSuffix(file, ".go"):
		return []string{ theChar + "g", "-I", ObjDir };
	case strings.HasSuffix(file, ".c"):
		return []string{ theChar + "c", "-FVw" };
	case strings.HasSuffix(file, ".s"):
		return []string{ theChar + "a" };
	}
	fatal("don't know how to compile ", file);
	return nil;
}

func Object(file, suffix string) string {
	ext := path.Ext(file);
	return file[0:len(file)-len(ext)] + "." + suffix;
}

// Dollarstring returns s with literal goarch/goos values
// replaced by $lGOARCHr where l and r are the specified delimeters.
func dollarString(s, l, r string) string {
	out := "";
	j := 0;	// index of last byte in s copied to out.
	for i := 0; i < len(s); {
		switch {
		case i+len(goarch) <= len(s) && s[i:i+len(goarch)] == goarch:
			out += s[j:i];
			out += "$" + l + "GOARCH" + r;
			i += len(goarch);
			j = i;
		case i+len(goos) <= len(s) && s[i:i+len(goos)] == goos:
			out += s[j:i];
			out += "$" + l + "GOOS" + r;
			i += len(goos);
			j = i;
		default:
			i++;
		}
	}
	out += s[j:len(s)];
	return out;
}

// dollarString wrappers.
// Print ShellString(s) or MakeString(s) depending on
// the context in which the result will be interpreted.
type ShellString string;
func (s ShellString) String() string {
	return dollarString(string(s), "{", "}");
}

type MakeString string;
func (s MakeString) String() string {
	return dollarString(string(s), "(", ")");
}

// TODO(rsc): parse.Parse should return an os.Error.
var ParseError = os.NewError("parse errors");

// TODO(rsc): Should this be in the AST library?
func LitString(p []*ast.StringLit) (string, os.Error) {
	s := "";
	for i, lit := range p {
		t, err := strconv.Unquote(string(lit.Value));
		if err != nil {
			return "", err;
		}
		s += t;
	}
	return s, nil;
}

func PackageImports(file string) (pkg string, imports []string, err1 os.Error) {
	f, err := os.Open(file, os.O_RDONLY, 0);
	if err != nil {
		return "", nil, err
	}

	prog, ok := parser.Parse(f, nil, parser.ImportsOnly);
	if !ok {
		return "", nil, ParseError;
	}

	// Normally one must consult the types of decl and spec,
	// but we told the parser to return imports only,
	// so assume it did.
	var imp []string;
	for _, decl := range prog.Decls {
		for _, spec := range decl.(*ast.GenDecl).Specs {
			str, err := LitString(spec.(*ast.ImportSpec).Path);
			if err != nil {
				return "", nil, ParseError;	// ParseError is better than os.EINVAL
			}
			PushString(&imp, str);
		}
	}

	// TODO(rsc): should be prog.Package.Value
	return prog.Name.Value, imp, nil;
}

func SourceFiles(dir string) ([]string, os.Error) {
	f, err := os.Open(dir, os.O_RDONLY, 0);
	if err != nil {
		return nil, err;
	}
	names, err1 := f.Readdirnames(-1);
	f.Close();
	out := make([]string, 0, len(names));
	for i, name := range names {
		if strings.HasSuffix(name, ".go")
		|| strings.HasSuffix(name, ".c")
		|| strings.HasSuffix(name, ".s") {
			n := len(out);
			out = out[0:n+1];
			out[n] = name;
		}
	}
	sort.SortStrings(out);
	return out, nil;
}

// TODO(rsc): Implement these for real as
// os.MkdirAll and os.RemoveAll and then
// make these wrappers that call fatal on error.

func MkdirAll(name string) {
	p, err := exec.Run("/bin/mkdir", []string{"mkdir", "-p", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
	if err != nil {
		fatal("run /bin/mkdir: %v", err);
	}
	w, err1 := p.Wait(0);
	if err1 != nil {
		fatal("wait /bin/mkdir: %v", err);
	}
	if !w.Exited() || w.ExitStatus() != 0 {
		fatal("/bin/mkdir: %v", w);
	}
}

func RemoveAll(name string) {
	p, err := exec.Run("/bin/rm", []string{"rm", "-rf", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
	if err != nil {
		fatal("run /bin/rm: %v", err);
	}
	w, err1 := p.Wait(0);
	if err1 != nil {
		fatal("wait /bin/rm: %v", err);
	}
	if !w.Exited() || w.ExitStatus() != 0 {
		fatal("/bin/rm: %v", w);
	}

}

<commit_msg>gobuild: command printing bug fix<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gobuild

import (
	"exec";
	"fmt";
	"go/ast";
	"go/parser";
	"os";
	"path";
	"sort";
	"strconv";
	"strings";
)

var (
	theChar string;
	goarch string;
	goos string;
	bin = make(map[string] string);
)

var theChars = map[string] string {
	"amd64": "6",
	"386": "8",
	"arm": "5"
}

const ObjDir = "_obj"

func fatal(args ...) {
	fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprint(args));
	os.Exit(1);
}

func init() {
	var err os.Error;
	goarch, err = os.Getenv("GOARCH");
	goos, err = os.Getenv("GOOS");

	var ok bool;
	theChar, ok = theChars[goarch];
	if !ok {
		fatal("unknown $GOARCH: ", goarch);
	}

	var binaries = []string{
		theChar + "g",
		theChar + "c",
		theChar + "a",
		"6ar",	// sic
	};

	for i, v := range binaries {
		var s string;
		if s, err = exec.LookPath(v); err != nil {
			fatal("cannot find binary ", v);
		}
		bin[v] = s;
	}
}

func PushString(v *[]string, p string) {
	n := len(v);
	if n >= cap(v) {
		m := 2*n + 10;
		a := make([]string, n, m);
		for i := range *v {
			a[i] = v[i];
		}
		*v = a;
	}
	*v = v[0:n+1];
	v[n] = p;
}

func run(argv []string, display bool) (ok bool) {
	argv0 := bin[argv[0]];
	output := exec.DevNull;
	if display {
		output = exec.PassThrough;
	}
	p, err1 := exec.Run(argv0, argv, os.Environ(), exec.DevNull, output, output);
	if err1 != nil {
		return false;
	}
	w, err2 := p.Wait(0);
	if err2 != nil {
		return false;
	}
	return w.Exited() && w.ExitStatus() == 0;
}

func Build(cmd []string, file string, display bool) (ok bool) {
	if display {
		fmt.Fprint(os.Stderr, "$ ");
		for i, s := range cmd {
			fmt.Fprint(os.Stderr, s, " ");
		}
		fmt.Fprint(os.Stderr, file, "\n");
	}

	var argv []string;
	for i, c := range cmd {
		PushString(&argv, c);
	}
	PushString(&argv, file);
	return run(argv, display);
}

func Archive(pkg string, files []string) {
	argv := []string{ "6ar", "grc", pkg };
	for i, file := range files {
		PushString(&argv, file);
	}
	if !run(argv, true) {
		fatal("archive failed");
	}
}

func Compiler(file string) []string {
	switch {
	case strings.HasSuffix(file, ".go"):
		return []string{ theChar + "g", "-I", ObjDir };
	case strings.HasSuffix(file, ".c"):
		return []string{ theChar + "c", "-FVw" };
	case strings.HasSuffix(file, ".s"):
		return []string{ theChar + "a" };
	}
	fatal("don't know how to compile ", file);
	return nil;
}

func Object(file, suffix string) string {
	ext := path.Ext(file);
	return file[0:len(file)-len(ext)] + "." + suffix;
}

// Dollarstring returns s with literal goarch/goos values
// replaced by $lGOARCHr where l and r are the specified delimeters.
func dollarString(s, l, r string) string {
	out := "";
	j := 0;	// index of last byte in s copied to out.
	for i := 0; i < len(s); {
		switch {
		case i+len(goarch) <= len(s) && s[i:i+len(goarch)] == goarch:
			out += s[j:i];
			out += "$" + l + "GOARCH" + r;
			i += len(goarch);
			j = i;
		case i+len(goos) <= len(s) && s[i:i+len(goos)] == goos:
			out += s[j:i];
			out += "$" + l + "GOOS" + r;
			i += len(goos);
			j = i;
		default:
			i++;
		}
	}
	out += s[j:len(s)];
	return out;
}

// dollarString wrappers.
// Print ShellString(s) or MakeString(s) depending on
// the context in which the result will be interpreted.
type ShellString string;
func (s ShellString) String() string {
	return dollarString(string(s), "{", "}");
}

type MakeString string;
func (s MakeString) String() string {
	return dollarString(string(s), "(", ")");
}

// TODO(rsc): parse.Parse should return an os.Error.
var ParseError = os.NewError("parse errors");

// TODO(rsc): Should this be in the AST library?
func LitString(p []*ast.StringLit) (string, os.Error) {
	s := "";
	for i, lit := range p {
		t, err := strconv.Unquote(string(lit.Value));
		if err != nil {
			return "", err;
		}
		s += t;
	}
	return s, nil;
}

func PackageImports(file string) (pkg string, imports []string, err1 os.Error) {
	f, err := os.Open(file, os.O_RDONLY, 0);
	if err != nil {
		return "", nil, err
	}

	prog, ok := parser.Parse(f, nil, parser.ImportsOnly);
	if !ok {
		return "", nil, ParseError;
	}

	// Normally one must consult the types of decl and spec,
	// but we told the parser to return imports only,
	// so assume it did.
	var imp []string;
	for _, decl := range prog.Decls {
		for _, spec := range decl.(*ast.GenDecl).Specs {
			str, err := LitString(spec.(*ast.ImportSpec).Path);
			if err != nil {
				return "", nil, ParseError;	// ParseError is better than os.EINVAL
			}
			PushString(&imp, str);
		}
	}

	// TODO(rsc): should be prog.Package.Value
	return prog.Name.Value, imp, nil;
}

func SourceFiles(dir string) ([]string, os.Error) {
	f, err := os.Open(dir, os.O_RDONLY, 0);
	if err != nil {
		return nil, err;
	}
	names, err1 := f.Readdirnames(-1);
	f.Close();
	out := make([]string, 0, len(names));
	for i, name := range names {
		if strings.HasSuffix(name, ".go")
		|| strings.HasSuffix(name, ".c")
		|| strings.HasSuffix(name, ".s") {
			n := len(out);
			out = out[0:n+1];
			out[n] = name;
		}
	}
	sort.SortStrings(out);
	return out, nil;
}

// TODO(rsc): Implement these for real as
// os.MkdirAll and os.RemoveAll and then
// make these wrappers that call fatal on error.

func MkdirAll(name string) {
	p, err := exec.Run("/bin/mkdir", []string{"mkdir", "-p", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
	if err != nil {
		fatal("run /bin/mkdir: %v", err);
	}
	w, err1 := p.Wait(0);
	if err1 != nil {
		fatal("wait /bin/mkdir: %v", err);
	}
	if !w.Exited() || w.ExitStatus() != 0 {
		fatal("/bin/mkdir: %v", w);
	}
}

func RemoveAll(name string) {
	p, err := exec.Run("/bin/rm", []string{"rm", "-rf", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
	if err != nil {
		fatal("run /bin/rm: %v", err);
	}
	w, err1 := p.Wait(0);
	if err1 != nil {
		fatal("wait /bin/rm: %v", err);
	}
	if !w.Exited() || w.ExitStatus() != 0 {
		fatal("/bin/rm: %v", w);
	}

}

<|endoftext|>


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

package io

type multiReader struct {
	readers []Reader
}

func (mr *multiReader) Read(p []byte) (n int, err error) {
	for len(mr.readers) > 0 {
		// Optimization to flatten nested multiReaders (Issue 13558)
		if len(mr.readers) == 1 {
			if r, ok := mr.readers[0].(*multiReader); ok {
				mr.readers = r.readers
				continue
			}
		}
		n, err = mr.readers[0].Read(p)
		if err == EOF {
			mr.readers = mr.readers[1:]
		}
		if n > 0 || err != EOF {
			if err == EOF && len(mr.readers) > 0 {
				// Don't return EOF yet. More readers remain.
				err = nil
			}
			return
		}
	}
	return 0, EOF
}

// MultiReader returns a Reader that's the logical concatenation of
// the provided input readers. They're read sequentially. Once all
// inputs have returned EOF, Read will return EOF.  If any of the readers
// return a non-nil, non-EOF error, Read will return that error.
func MultiReader(readers ...Reader) Reader {
	r := make([]Reader, len(readers))
	copy(r, readers)
	return &multiReader{r}
}

type multiWriter struct {
	writers []Writer
}

func (t *multiWriter) Write(p []byte) (n int, err error) {
	for _, w := range t.writers {
		n, err = w.Write(p)
		if err != nil {
			return
		}
		if n != len(p) {
			err = ErrShortWrite
			return
		}
	}
	return len(p), nil
}

var _ stringWriter = (*multiWriter)(nil)

func (t *multiWriter) WriteString(s string) (n int, err error) {
	var p []byte // lazily initialized if/when needed
	for _, w := range t.writers {
		if sw, ok := w.(stringWriter); ok {
			n, err = sw.WriteString(s)
		} else {
			if p == nil {
				p = []byte(s)
			}
			n, err = w.Write(p)
		}
		if err != nil {
			return
		}
		if n != len(s) {
			err = ErrShortWrite
			return
		}
	}
	return len(s), nil
}

// MultiWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command.
func MultiWriter(writers ...Writer) Writer {
	w := make([]Writer, len(writers))
	copy(w, writers)
	return &multiWriter{w}
}
<commit_msg>io: make MultiReader nil exhausted Readers for earlier GC<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io

type multiReader struct {
	readers []Reader
}

func (mr *multiReader) Read(p []byte) (n int, err error) {
	for len(mr.readers) > 0 {
		// Optimization to flatten nested multiReaders (Issue 13558)
		if len(mr.readers) == 1 {
			if r, ok := mr.readers[0].(*multiReader); ok {
				mr.readers = r.readers
				continue
			}
		}
		n, err = mr.readers[0].Read(p)
		if err == EOF {
			mr.readers[0] = nil // permit earlier GC
			mr.readers = mr.readers[1:]
		}
		if n > 0 || err != EOF {
			if err == EOF && len(mr.readers) > 0 {
				// Don't return EOF yet. More readers remain.
				err = nil
			}
			return
		}
	}
	return 0, EOF
}

// MultiReader returns a Reader that's the logical concatenation of
// the provided input readers. They're read sequentially. Once all
// inputs have returned EOF, Read will return EOF.  If any of the readers
// return a non-nil, non-EOF error, Read will return that error.
func MultiReader(readers ...Reader) Reader {
	r := make([]Reader, len(readers))
	copy(r, readers)
	return &multiReader{r}
}

type multiWriter struct {
	writers []Writer
}

func (t *multiWriter) Write(p []byte) (n int, err error) {
	for _, w := range t.writers {
		n, err = w.Write(p)
		if err != nil {
			return
		}
		if n != len(p) {
			err = ErrShortWrite
			return
		}
	}
	return len(p), nil
}

var _ stringWriter = (*multiWriter)(nil)

func (t *multiWriter) WriteString(s string) (n int, err error) {
	var p []byte // lazily initialized if/when needed
	for _, w := range t.writers {
		if sw, ok := w.(stringWriter); ok {
			n, err = sw.WriteString(s)
		} else {
			if p == nil {
				p = []byte(s)
			}
			n, err = w.Write(p)
		}
		if err != nil {
			return
		}
		if n != len(s) {
			err = ErrShortWrite
			return
		}
	}
	return len(s), nil
}

// MultiWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command.
func MultiWriter(writers ...Writer) Writer {
	w := make([]Writer, len(writers))
	copy(w, writers)
	return &multiWriter{w}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"net"
	"strconv"
)

func startServer(listenPort int, backends *Backends) {
	port := strconv.Itoa(listenPort)
	fmt.Println("Starting server on port ", port)

	addr, _ := net.ResolveTCPAddr("tcp", ":"+port)

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		fmt.Println("Could not listen on port because:", err.Error())
		return
	}

	for {
		con, err := listener.Accept()
		if err != nil {
			fmt.Println("Error occured accepting a connection", err.Error())
		}

		go handleConnection(con, backends.NextAddress())
	}

}

func handleConnection(cli_conn net.Conn, srv_addr string) {
	srv_conn, err := net.Dial("tcp", srv_addr)
	if err != nil {
		fmt.Println("Could not connect to server (%s), connection dropping", srv_addr)
		return
	}

	go io.Copy(cli_conn, srv_conn)
	io.Copy(srv_conn, cli_conn)
}
<commit_msg>Println -> Printf<commit_after>package main

import (
	"fmt"
	"io"
	"net"
	"strconv"
)

func startServer(listenPort int, backends *Backends) {
	port := strconv.Itoa(listenPort)
	fmt.Println("Starting server on port ", port)

	addr, _ := net.ResolveTCPAddr("tcp", ":"+port)

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		fmt.Println("Could not listen on port because:", err.Error())
		return
	}

	for {
		con, err := listener.Accept()
		if err != nil {
			fmt.Println("Error occured accepting a connection", err.Error())
		}

		go handleConnection(con, backends.NextAddress())
	}

}

func handleConnection(cli_conn net.Conn, srv_addr string) {
	srv_conn, err := net.Dial("tcp", srv_addr)
	if err != nil {
		fmt.Printf("Could not connect to server (%s), connection dropping\n", srv_addr)
		return
	}

	go io.Copy(cli_conn, srv_conn)
	io.Copy(srv_conn, cli_conn)
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "log"
    "net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, 世界")
}

func main() {
    var h Hello
    err := http.ListenAndServe("0.0.0.0:4000", h)
    if err != nil {
        log.Fatal(err)
    }
}
<commit_msg>add startup message<commit_after>package main

import (
    "fmt"
    "log"
    "net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, 世界")
}

func main() {
    var h Hello
    fmt.Println("application started")
    err := http.ListenAndServe("0.0.0.0:4000", h)
    if err != nil {
        log.Fatal(err)
    }
}
<|endoftext|>


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

package main

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

var dir = flag.String("d", "/tmp", "path in which to create test directory")
var n = flag.Int("n", 1000000, "number of files to create")

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	d, err := ioutil.TempDir(*dir, "bigdirbench-")
	check(err)
	fmt.Printf("working in %s\n", d)
	wd, err := os.Getwd()
	check(err)
	check(os.Chdir(d))

	jump := 1
	for i := 0; i < *n; {
		var name string
		for j := 0; j < jump; j++ {
			name = fmt.Sprintf("%032d", i)
			f, err := os.Create(name)
			check(err)
			f.Close()
			i++
		}
		t := time.Now()
		_, err := os.Stat(name)
		check(err)
		dt := time.Since(t)
		t = time.Now()
		f, err := os.Open(".")
		check(err)
		_, err = f.Readdirnames(0)
		check(err)
		f.Close()
		dt2 := time.Since(t)
		fmt.Printf("%d %.6f %.6f\n", i, dt.Seconds(), dt2.Seconds())
		if jump*1000 <= i {
			jump *= 10
		}
	}

	check(os.Chdir(wd))
	check(os.RemoveAll(d))
}
<commit_msg>bigdirbench: fewer probes<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

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

var dir = flag.String("d", "/tmp", "path in which to create test directory")
var n = flag.Int("n", 1000000, "number of files to create")

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	d, err := ioutil.TempDir(*dir, "bigdirbench-")
	check(err)
	fmt.Printf("working in %s\n", d)
	wd, err := os.Getwd()
	check(err)
	check(os.Chdir(d))

	for i := 0; i < *n; {
		end := i + i/10
		pow := 10
		for pow*100 < end {
			pow *= 10
		}
		end = end / pow * pow
		if end > *n {
			end = *n + 1
		}
		if end <= i {
			end = i + 1
		}
		var name string
		for ; i < end; i++ {
			name = fmt.Sprintf("%032d", i)
			f, err := os.Create(name)
			check(err)
			f.Close()
			i++
		}
		t := time.Now()
		_, err := os.Stat(name)
		check(err)
		dt := time.Since(t)
		t = time.Now()
		f, err := os.Open(".")
		check(err)
		_, err = f.Readdirnames(0)
		check(err)
		f.Close()
		dt2 := time.Since(t)
		fmt.Printf("%d %.6f %.6f\n", i, dt.Seconds(), dt2.Seconds())
	}

	check(os.Chdir(wd))
	check(os.RemoveAll(d))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net"
	"os"
	"time"

	"encoding/json"
	"io/ioutil"

	"github.com/aleasoluciones/goaleasoluciones/scheduledtask"
	"github.com/aleasoluciones/gosnmpquerier"
)

const (
	sysName = "1.3.6.1.2.1.1.5.0"
)

type Device struct {
	Id        string
	DevType   string
	Ip        string
	Community string
}

func devicesFromInventory(inventoryPath string) ([]Device, error) {
	content, err := ioutil.ReadFile(inventoryPath)
	if err != nil {
		return []Device{}, err
	}
	var inventory interface{}
	err = json.Unmarshal(content, &inventory)
	if err != nil {
		return []Device{}, err
	}

	devices := []Device{}

	for _, device := range inventory.([]interface{}) {
		deviceMap := device.(map[string]interface{})
		status := deviceMap["status"].(string)
		if status == "Activo" {
			device := Device{
				DevType: deviceMap["dev_type"].(string),
				Id:      deviceMap["id"].(string),
				Ip:      deviceMap["ip"].(string),
			}
			community, ok := deviceMap["snmp_rw"]
			if ok {
				device.Community = community.(string)
			}
			devices = append(devices, device)
		}
	}
	return devices, nil
}

type Checker struct {
	Devices     []Device
	SnmpQuerier gosnmpquerier.SyncQuerier
}

func NewChecker(devices []Device) Checker {
	return Checker{Devices: devices, SnmpQuerier: gosnmpquerier.NewSyncQuerier(1, 1, 4*time.Second)}
}

func (c *Checker) Start() {
	for _, device := range c.Devices {
		if device.DevType == "bos" {
			c.checkTcpPortLoop(device, 6922)
		}
		if device.Community != "" {
			c.checkSnmpLoop(device)
		}
	}
}

func (c *Checker) checkSnmpLoop(device Device) {
	scheduledtask.NewScheduledTask(func() {
		result, err := c.SnmpQuerier.Get(device.Ip, device.Community, []string{sysName}, 1*time.Second, 1)
		if err == nil {
			log.Println("Check snmp ok", device, result)
		} else {
			log.Println("Check snmp error", device, err)
		}
	}, 20*time.Second, 0)
}

func (c *Checker) checkTcpPortLoop(device Device, port int) {
	scheduledtask.NewScheduledTask(func() {
		if ok, err := c.checkTcpPort(device, port); ok {
			log.Println("Check tcp ok", device)
		} else {
			log.Println("Check tcp error", device, err)
		}
	}, 20*time.Second, 0)
}

func (c *Checker) checkTcpPort(device Device, port int) (bool, error) {
	var err error
	var conn net.Conn

	for attempt := 0; attempt < 3; attempt++ {
		conn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", device.Ip, port))
		if err == nil {
			conn.Close()
			return true, nil
		}
		time.Sleep(1 * time.Second)
	}
	return false, err
}

func main() {
	devices, err := devicesFromInventory(os.Getenv("INVENTORY_FILE"))
	if err != nil {
		log.Panic(err)
	}
	checker := NewChecker(devices)
	checker.Start()

	for {
		time.Sleep(2 * time.Second)
	}
}
<commit_msg>Dial with timeout<commit_after>package main

import (
	"fmt"
	"log"
	"net"
	"os"
	"time"

	"encoding/json"
	"io/ioutil"

	"github.com/aleasoluciones/goaleasoluciones/scheduledtask"
	"github.com/aleasoluciones/gosnmpquerier"
)

const (
	sysName = "1.3.6.1.2.1.1.5.0"
)

type Device struct {
	Id        string
	DevType   string
	Ip        string
	Community string
}

func devicesFromInventory(inventoryPath string) ([]Device, error) {
	content, err := ioutil.ReadFile(inventoryPath)
	if err != nil {
		return []Device{}, err
	}
	var inventory interface{}
	err = json.Unmarshal(content, &inventory)
	if err != nil {
		return []Device{}, err
	}

	devices := []Device{}

	for _, device := range inventory.([]interface{}) {
		deviceMap := device.(map[string]interface{})
		status := deviceMap["status"].(string)
		if status == "Activo" {
			device := Device{
				DevType: deviceMap["dev_type"].(string),
				Id:      deviceMap["id"].(string),
				Ip:      deviceMap["ip"].(string),
			}
			community, ok := deviceMap["snmp_rw"]
			if ok {
				device.Community = community.(string)
			}
			devices = append(devices, device)
		}
	}
	return devices, nil
}

type Checker struct {
	Devices     []Device
	SnmpQuerier gosnmpquerier.SyncQuerier
}

func NewChecker(devices []Device) Checker {
	return Checker{Devices: devices, SnmpQuerier: gosnmpquerier.NewSyncQuerier(1, 1, 4*time.Second)}
}

func (c *Checker) Start() {
	for _, device := range c.Devices {
		if device.DevType == "bos" {
			c.checkTcpPortLoop(device, 6922)
		}
		if device.Community != "" {
			c.checkSnmpLoop(device)
		}
	}
}

func (c *Checker) checkSnmpLoop(device Device) {
	scheduledtask.NewScheduledTask(func() {
		result, err := c.SnmpQuerier.Get(device.Ip, device.Community, []string{sysName}, 1*time.Second, 1)
		if err == nil {
			log.Println("Check snmp ok", device, result)
		} else {
			log.Println("Check snmp error", device, err)
		}
	}, 20*time.Second, 0)
}

func (c *Checker) checkTcpPortLoop(device Device, port int) {
	scheduledtask.NewScheduledTask(func() {
		if ok, err := c.checkTcpPort(device, port); ok {
			log.Println("Check tcp ok", device)
		} else {
			log.Println("Check tcp error", device, err)
		}
	}, 20*time.Second, 0)
}

func (c *Checker) checkTcpPort(device Device, port int) (bool, error) {
	var err error
	var conn net.Conn

	for attempt := 0; attempt < 3; attempt++ {
		conn, err = net.DialTimeout("tcp", fmt.Sprintf("%s:%d", device.Ip, port), 2*time.Second)
		if err == nil {
			conn.Close()
			return true, nil
		}
		time.Sleep(1 * time.Second)
	}
	return false, err
}

func main() {
	devices, err := devicesFromInventory(os.Getenv("INVENTORY_FILE"))
	if err != nil {
		log.Panic(err)
	}
	checker := NewChecker(devices)
	checker.Start()

	for {
		time.Sleep(2 * time.Second)
	}
}
<|endoftext|>