<commit_before>package configurator

import (
	"sync"
	"time"

	"github.com/mholt/caddy"
	"github.com/nathan-osman/caddy-docker/container"
	"github.com/sirupsen/logrus"

	// TODO: is this still needed?
	_ "github.com/mholt/caddy/caddyhttp"
)

// Configurator generates Caddy configurations from running containers and
// runs the server.
type Configurator struct {
	mutex  sync.Mutex
	inst   *caddy.Instance
	log    *logrus.Entry
	stopCh chan bool
}

// run receives container events and processes them.
func (c *Configurator) run(events <-chan *container.Container) {
	defer close(c.stopCh)
	defer c.log.Info("configurator stopped")
	c.log.Info("starting configurator")
	var (
		t <-chan time.Time
		m = make(map[string]*container.Container)
	)
	for {
		select {
		case e, ok := <-events:
			if !ok {
				return
			}
			if e.Running {
				m[e.ID] = e
			} else {
				delete(m, e.ID)
			}
			t = time.After(2 * time.Second)
		case <-t:
			if err := c.generate(m); err != nil {
				c.log.Error(err)
			}
			t = nil
		}
	}
}

// New creates a new configurator from the specified configuration.
func New(cfg *Config) *Configurator {
	c := &Configurator{
		log:    logrus.WithField("context", "configurator"),
		stopCh: make(chan bool),
	}
	go c.run(cfg.Events)
	return c
}

// Close shuts down the configurator.
func (c *Configurator) Close() {
	<-c.stopCh
	func() {
		c.mutex.Lock()
		defer c.mutex.Unlock()
		if c.inst != nil {
			c.log.Info("stopping server")
			c.inst.Stop()
		}
	}()
}
<commit_msg>Yes, it is needed.<commit_after>package configurator

import (
	"sync"
	"time"

	"github.com/mholt/caddy"
	"github.com/nathan-osman/caddy-docker/container"
	"github.com/sirupsen/logrus"

	_ "github.com/mholt/caddy/caddyhttp"
)

// Configurator generates Caddy configurations from running containers and
// runs the server.
type Configurator struct {
	mutex  sync.Mutex
	inst   *caddy.Instance
	log    *logrus.Entry
	stopCh chan bool
}

// run receives container events and processes them.
func (c *Configurator) run(events <-chan *container.Container) {
	defer close(c.stopCh)
	defer c.log.Info("configurator stopped")
	c.log.Info("starting configurator")
	var (
		t <-chan time.Time
		m = make(map[string]*container.Container)
	)
	for {
		select {
		case e, ok := <-events:
			if !ok {
				return
			}
			if e.Running {
				m[e.ID] = e
			} else {
				delete(m, e.ID)
			}
			t = time.After(2 * time.Second)
		case <-t:
			if err := c.generate(m); err != nil {
				c.log.Error(err)
			}
			t = nil
		}
	}
}

// New creates a new configurator from the specified configuration.
func New(cfg *Config) *Configurator {
	c := &Configurator{
		log:    logrus.WithField("context", "configurator"),
		stopCh: make(chan bool),
	}
	go c.run(cfg.Events)
	return c
}

// Close shuts down the configurator.
func (c *Configurator) Close() {
	<-c.stopCh
	func() {
		c.mutex.Lock()
		defer c.mutex.Unlock()
		if c.inst != nil {
			c.log.Info("stopping server")
			c.inst.Stop()
		}
	}()
}
<|endoftext|>


<commit_before>package bild

import (
	"image"
	"image/color"
	"math"
)

// Invert returns a negated version of the image
func Invert(src image.Image) *image.RGBA {
	fn := func(c color.RGBA) color.RGBA {
		return color.RGBA{255 - c.R, 255 - c.G, 255 - c.B, c.A}
	}

	img := apply(src, fn)

	return img
}

// Brightness returns a copy of the image with the adjusted brightness
func Brightness(src image.Image, percentChange float64) *image.RGBA {
	fn := func(c color.RGBA) color.RGBA {

		changeR := 1 + percentChange/100.0
		changeG := 1 + percentChange/100.0
		changeB := 1 + percentChange/100.0

		return color.RGBA{
			uint8(clamp(math.Ceil(float64(c.R)*changeR), 0, 255)),
			uint8(clamp(math.Ceil(float64(c.G)*changeG), 0, 255)),
			uint8(clamp(math.Ceil(float64(c.B)*changeB), 0, 255)),
			c.A}
	}

	img := apply(src, fn)

	return img
}
<commit_msg>using new helper clamp<commit_after>package bild

import (
	"image"
	"image/color"
	"math"
)

// Invert returns a negated version of the image
func Invert(src image.Image) *image.RGBA {
	fn := func(c color.RGBA) color.RGBA {
		return color.RGBA{255 - c.R, 255 - c.G, 255 - c.B, c.A}
	}

	img := apply(src, fn)

	return img
}

// Brightness returns a copy of the image with the adjusted brightness
func Brightness(src image.Image, percentChange float64) *image.RGBA {
	fn := func(c color.RGBA) color.RGBA {

		changeR := 1 + percentChange/100.0
		changeG := 1 + percentChange/100.0
		changeB := 1 + percentChange/100.0

		return color.RGBA{
			uint8(clampFloat64(math.Ceil(float64(c.R)*changeR), 0, 255)),
			uint8(clampFloat64(math.Ceil(float64(c.G)*changeG), 0, 255)),
			uint8(clampFloat64(math.Ceil(float64(c.B)*changeB), 0, 255)),
			c.A}
	}

	img := apply(src, fn)

	return img
}
<|endoftext|>


<commit_before>package mysql

import (
	"sync"

	"github.com/funkygao/dbus/engine"
	"github.com/funkygao/dbus/pkg/model"
	"github.com/funkygao/dbus/pkg/myslave"
	conf "github.com/funkygao/jsconf"
	log "github.com/funkygao/log4go"
)

// MysqlbinlogInput is an input plugin that pretends to be a mysql instance's
// slave and consumes mysql binlog events.
type MysqlbinlogInput struct {
	maxEventLength int
	stopChan       chan struct{}
	stopped        chan struct{}
	cf             *conf.Conf

	mu     sync.RWMutex
	slaves []*myslave.MySlave
}

func (this *MysqlbinlogInput) shouldRunInCluster() bool {
	if dsn := this.cf.String("dsn", ""); len(dsn) == 0 {
		return true
	}

	return false
}

func (this *MysqlbinlogInput) Init(config *conf.Conf) {
	this.maxEventLength = config.Int("max_event_length", (1<<20)-100)
	this.cf = config
	this.stopChan = make(chan struct{})
	this.slaves = make([]*myslave.MySlave, 0)
}

func (this *MysqlbinlogInput) Stop(r engine.InputRunner) {
	log.Debug("[%s] stopping...", r.Name())

	close(this.stopChan)
	<-this.stopped
}

func (this *MysqlbinlogInput) OnAck(pack *engine.Packet) error {
	// FIXME
	return this.slaves[0].MarkAsProcessed(pack.Payload.(*model.RowsEvent))
}

func (this *MysqlbinlogInput) Run(r engine.InputRunner, h engine.PluginHelper) error {
	if this.shouldRunInCluster() {
		return this.runClustered(r, h)
	}

	return this.runStandalone(this.cf.String("dsn", ""), r, h)
}
<commit_msg>race condition: in cluster mode, when ACK, the slave might have be gone<commit_after>package mysql

import (
	"sync"

	"github.com/funkygao/dbus/engine"
	"github.com/funkygao/dbus/pkg/model"
	"github.com/funkygao/dbus/pkg/myslave"
	conf "github.com/funkygao/jsconf"
	log "github.com/funkygao/log4go"
)

// MysqlbinlogInput is an input plugin that pretends to be a mysql instance's
// slave and consumes mysql binlog events.
type MysqlbinlogInput struct {
	maxEventLength int
	stopChan       chan struct{}
	stopped        chan struct{}
	cf             *conf.Conf

	mu     sync.RWMutex
	slaves []*myslave.MySlave
}

func (this *MysqlbinlogInput) shouldRunInCluster() bool {
	if dsn := this.cf.String("dsn", ""); len(dsn) == 0 {
		return true
	}

	return false
}

func (this *MysqlbinlogInput) Init(config *conf.Conf) {
	this.maxEventLength = config.Int("max_event_length", (1<<20)-100)
	this.cf = config
	this.stopChan = make(chan struct{})
	this.slaves = make([]*myslave.MySlave, 0)
}

func (this *MysqlbinlogInput) Stop(r engine.InputRunner) {
	log.Debug("[%s] stopping...", r.Name())

	close(this.stopChan)
	<-this.stopped
}

func (this *MysqlbinlogInput) OnAck(pack *engine.Packet) error {
	// FIXME
	// race condition: in cluster mode, when ACK, the slave might have be gone
	return this.slaves[0].MarkAsProcessed(pack.Payload.(*model.RowsEvent))
}

func (this *MysqlbinlogInput) Run(r engine.InputRunner, h engine.PluginHelper) error {
	if this.shouldRunInCluster() {
		return this.runClustered(r, h)
	}

	return this.runStandalone(this.cf.String("dsn", ""), r, h)
}
<|endoftext|>


<commit_before>package clearbit_test

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/clearbit/clearbit-go/clearbit"
)

func handleError(err error, resp *http.Response) {
	fmt.Printf("%#v\n%s\n", err, resp.Status)
}

func ExampleNewClient_manuallyConfiguringEverything_output() {
	var clearbitApiKey = os.Getenv("CLEARBIT_KEY")
	client := clearbit.NewClient(
		clearbit.WithHTTPClient(&http.Client{}),
		clearbit.WithAPIKey(clearbitApiKey),
		clearbit.WithTimeout(20*time.Second),
	)

	_, resp, _ := client.Discovery.Search(clearbit.DiscoverySearchParams{
		Query: "name:clearbit",
	})

	fmt.Println(resp.Status)

	// Output: 200 OK
}

func ExampleRevealService_Find_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Reveal.Find(clearbit.RevealFindParams{
		IP: "104.193.168.24",
	})

	if err == nil {
		fmt.Println(results.Company.Name, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Clearbt 200 OK
}

func ExampleAutocompleteService_Suggest_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Autocomplete.Suggest(clearbit.AutocompleteSuggestParams{
		Query: "clearbit",
	})

	if err == nil {
		fmt.Println(results[0].Domain, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: clearbit.com 200 OK
}

func ExampleProspectorService_Search_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Prospector.Search(clearbit.ProspectorSearchParams{
		Domain: "clearbit.com",
	})

	if err == nil {
		fmt.Println(results[0].Email, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: alex@clearbit.com 200 OK
}

func ExampleProspectorService_SearchWithRoles_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Prospector.Search(clearbit.ProspectorSearchParams{
		Domain: "clearbit.com",
		Roles:  []string{"sales", "engineering"},
	})

	if err == nil {
		fmt.Println(len(results), resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: 5 200 OK
}

func ExampleCompanyService_Find_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Company.Find(clearbit.CompanyFindParams{
		Domain: "clearbit.com",
	})

	if err == nil {
		fmt.Println(results.Name, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Clearbit 200 OK
}

func ExamplePersonService_Find_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Person.Find(clearbit.PersonFindParams{
		Email: "alex@clearbit.com",
	})

	if err == nil {
		fmt.Println(results.Name.FullName, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Alex MacCaw 200 OK
}

func ExamplePersonService_FindCombined_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Person.FindCombined(clearbit.PersonFindParams{
		Email: "alex@clearbit.com",
	})

	if err == nil {
		fmt.Println(results.Person.Name.FullName, results.Company.Name, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Alex MacCaw Clearbit 200 OK
}

func ExampleDiscoveryService_Search_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Discovery.Search(clearbit.DiscoverySearchParams{
		Query: "name:clearbit",
	})

	if err == nil {
		fmt.Println(results.Results[0].Domain, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: clearbit.com 200 OK
}
<commit_msg>Rename prospector search with roles example<commit_after>package clearbit_test

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/clearbit/clearbit-go/clearbit"
)

func handleError(err error, resp *http.Response) {
	fmt.Printf("%#v\n%s\n", err, resp.Status)
}

func ExampleNewClient_manuallyConfiguringEverything_output() {
	var clearbitApiKey = os.Getenv("CLEARBIT_KEY")
	client := clearbit.NewClient(
		clearbit.WithHTTPClient(&http.Client{}),
		clearbit.WithAPIKey(clearbitApiKey),
		clearbit.WithTimeout(20*time.Second),
	)

	_, resp, _ := client.Discovery.Search(clearbit.DiscoverySearchParams{
		Query: "name:clearbit",
	})

	fmt.Println(resp.Status)

	// Output: 200 OK
}

func ExampleRevealService_Find_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Reveal.Find(clearbit.RevealFindParams{
		IP: "104.193.168.24",
	})

	if err == nil {
		fmt.Println(results.Company.Name, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Clearbit 200 OK
}

func ExampleAutocompleteService_Suggest_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Autocomplete.Suggest(clearbit.AutocompleteSuggestParams{
		Query: "clearbit",
	})

	if err == nil {
		fmt.Println(results[0].Domain, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: clearbit.com 200 OK
}

func ExampleProspectorService_Search_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Prospector.Search(clearbit.ProspectorSearchParams{
		Domain: "clearbit.com",
	})

	if err == nil {
		fmt.Println(results[0].Email, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: alex@clearbit.com 200 OK
}

func ExampleProspectorService_Search_withRoles_Output() {
	client := clearbit.NewClient()
	results, resp, err := client.Prospector.Search(clearbit.ProspectorSearchParams{
		Domain: "clearbit.com",
		Roles:  []string{"sales", "engineering"},
	})

	if err == nil {
		fmt.Println(len(results), resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: 5 200 OK
}

func ExampleCompanyService_Find_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Company.Find(clearbit.CompanyFindParams{
		Domain: "clearbit.com",
	})

	if err == nil {
		fmt.Println(results.Name, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Clearbit 200 OK
}

func ExamplePersonService_Find_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Person.Find(clearbit.PersonFindParams{
		Email: "alex@clearbit.com",
	})

	if err == nil {
		fmt.Println(results.Name.FullName, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Alex MacCaw 200 OK
}

func ExamplePersonService_FindCombined_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Person.FindCombined(clearbit.PersonFindParams{
		Email: "alex@clearbit.com",
	})

	if err == nil {
		fmt.Println(results.Person.Name.FullName, results.Company.Name, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: Alex MacCaw Clearbit 200 OK
}

func ExampleDiscoveryService_Search_output() {
	client := clearbit.NewClient()
	results, resp, err := client.Discovery.Search(clearbit.DiscoverySearchParams{
		Query: "name:clearbit",
	})

	if err == nil {
		fmt.Println(results.Results[0].Domain, resp.Status)
	} else {
		handleError(err, resp)
	}

	// Output: clearbit.com 200 OK
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"github.com/kurrik/oauth1a"
	"github.com/kurrik/twittergo"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

const MINWAIT = time.Duration(10) * time.Second

func LoadCredentials() (client *twittergo.Client, err error) {
	credentials, err := ioutil.ReadFile("CREDENTIALS")
	if err != nil {
		return
	}
	lines := strings.Split(string(credentials), "\n")
	config := &oauth1a.ClientConfig{
		ConsumerKey:    lines[0],
		ConsumerSecret: lines[1],
	}
	user := oauth1a.NewAuthorizedConfig(lines[2], lines[3])
	client = twittergo.NewClient(config, user)
	return
}

type Args struct {
	ScreenName string
	Count      string
}

func parseArgs() *Args {
	a := &Args{}
	flag.StringVar(&a.ScreenName, "screen_name", "episod", "Screen name to look up")
	flag.StringVar(&a.Count, "count", "100", "Number of results / page")
	flag.Parse()
	return a
}

func handleRateLimit(err error) error {
	if rle, ok := err.(twittergo.RateLimitError); ok {
		dur := rle.Reset.Sub(time.Now()) + time.Second
		if dur < MINWAIT {
			// Don't wait less than minwait.
			dur = MINWAIT
		}
		msg := "Rate limited. Reset at %v. Waiting for %v\n"
		fmt.Printf(msg, rle.Reset, dur)
		time.Sleep(dur)
		return nil
	}
	return err
}

func printRateLimit(resp *twittergo.APIResponse) {
	if resp.HasRateLimit() {
		fmt.Printf("Rate limit:           %v\n", resp.RateLimit())
		fmt.Printf("Rate limit remaining: %v\n", resp.RateLimitRemaining())
		fmt.Printf("Rate limit reset:     %v\n", resp.RateLimitReset())
	} else {
		fmt.Printf("Could not parse rate limit from response.\n")
	}
}

func printList(list *twittergo.List) {
	user := list.User()
	fmt.Printf("%v\n", list.Name())
	fmt.Printf("Owner: %v (@%v)\n", user.Name(), user.ScreenName())
	fmt.Printf("Members: %v\n", list.MemberCount())
	fmt.Printf("Subscribers: %v\n\n", list.SubscriberCount())
}

func fetchAndPrintList(client *twittergo.Client, path string, query url.Values) (err error) {
	var (
		req     *http.Request
		resp    *twittergo.APIResponse
		results twittergo.Lists
	)
	for {
		url := fmt.Sprintf("%v?%v", path, query.Encode())
		req, err = http.NewRequest("GET", url, nil)
		req.Header.Set("Accept-Encoding", "gzip, deflate")
		if err != nil {
			err = fmt.Errorf("Could not parse request: %v\n", err)
			return
		}
		resp, err = client.SendRequest(req)
		if err != nil {
			err = fmt.Errorf("Could not send request: %v\n", err)
			return
		}
		results = twittergo.Lists{}
		if err = resp.Parse(&results); err != nil {
			if err = handleRateLimit(err); err != nil {
				err = fmt.Errorf("Problem parsing response: %v\n", err)
				return
			} else {
				continue
			}
		}
		fmt.Printf("\n")
		for i, list := range results {
			fmt.Printf("%v.) ", i+1)
			printList(&list)
		}
		printRateLimit(resp)
		return
	}
	return
}

func fetchAndPrintCursoredList(client *twittergo.Client, path string, query url.Values) (err error) {
	var (
		req     *http.Request
		resp    *twittergo.APIResponse
		results twittergo.CursoredLists
		i       int64
	)
	i = 1
	query.Set("cursor", "-1")
	for {
		url := fmt.Sprintf("%v?%v", path, query.Encode())
		req, err = http.NewRequest("GET", url, nil)
		req.Header.Set("Accept-Encoding", "gzip, deflate")
		if err != nil {
			err = fmt.Errorf("Could not parse request: %v\n", err)
			break
		}
		resp, err = client.SendRequest(req)
		if err != nil {
			err = fmt.Errorf("Could not send request: %v\n", err)
			break
		}
		results = twittergo.CursoredLists{}
		if err = resp.Parse(&results); err != nil {
			if err = handleRateLimit(err); err != nil {
				err = fmt.Errorf("Problem parsing response: %v\n", err)
				break
			} else {
				continue
			}
		}
		fmt.Printf("\n")
		for _, list := range results.Lists() {
			fmt.Printf("%v.) ", i)
			printList(&list)
			i += 1
		}
		printRateLimit(resp)
		if results.NextCursorStr() == "0" {
			break
		}
		query.Set("cursor", results.NextCursorStr())
	}
	return
}

func main() {
	var (
		err    error
		args   *Args
		client *twittergo.Client
	)
	args = parseArgs()
	if client, err = LoadCredentials(); err != nil {
		fmt.Printf("Could not parse CREDENTIALS file: %v\n", err)
		os.Exit(1)
	}
	query := url.Values{}
	query.Set("screen_name", args.ScreenName)

	fmt.Printf("Printing up to 100 lists %v owns or is subscribed to:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintList(client, "/1.1/lists/list.json", query); err != nil {
		fmt.Println("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

	// Add count for future requests
	query.Set("count", args.Count)

	fmt.Printf("Printing the lists %v is a member of:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintCursoredList(client, "/1.1/lists/memberships.json", query); err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

	fmt.Printf("Printing the lists %v is subscribed to:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintCursoredList(client, "/1.1/lists/subscriptions.json", query); err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

	fmt.Printf("Printing the lists %v is owner of:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintCursoredList(client, "/1.1/lists/ownerships.json", query); err != nil {
		fmt.Printf("Error: %v\n", err)
	}
}
<commit_msg>Sort lists imports<commit_after>// Copyright 2013 Arne Roomann-Kurrik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/kurrik/oauth1a"
	"github.com/kurrik/twittergo"
)

const MINWAIT = time.Duration(10) * time.Second

func LoadCredentials() (client *twittergo.Client, err error) {
	credentials, err := ioutil.ReadFile("CREDENTIALS")
	if err != nil {
		return
	}
	lines := strings.Split(string(credentials), "\n")
	config := &oauth1a.ClientConfig{
		ConsumerKey:    lines[0],
		ConsumerSecret: lines[1],
	}
	user := oauth1a.NewAuthorizedConfig(lines[2], lines[3])
	client = twittergo.NewClient(config, user)
	return
}

type Args struct {
	ScreenName string
	Count      string
}

func parseArgs() *Args {
	a := &Args{}
	flag.StringVar(&a.ScreenName, "screen_name", "episod", "Screen name to look up")
	flag.StringVar(&a.Count, "count", "100", "Number of results / page")
	flag.Parse()
	return a
}

func handleRateLimit(err error) error {
	if rle, ok := err.(twittergo.RateLimitError); ok {
		dur := rle.Reset.Sub(time.Now()) + time.Second
		if dur < MINWAIT {
			// Don't wait less than minwait.
			dur = MINWAIT
		}
		msg := "Rate limited. Reset at %v. Waiting for %v\n"
		fmt.Printf(msg, rle.Reset, dur)
		time.Sleep(dur)
		return nil
	}
	return err
}

func printRateLimit(resp *twittergo.APIResponse) {
	if resp.HasRateLimit() {
		fmt.Printf("Rate limit:           %v\n", resp.RateLimit())
		fmt.Printf("Rate limit remaining: %v\n", resp.RateLimitRemaining())
		fmt.Printf("Rate limit reset:     %v\n", resp.RateLimitReset())
	} else {
		fmt.Printf("Could not parse rate limit from response.\n")
	}
}

func printList(list *twittergo.List) {
	user := list.User()
	fmt.Printf("%v\n", list.Name())
	fmt.Printf("Owner: %v (@%v)\n", user.Name(), user.ScreenName())
	fmt.Printf("Members: %v\n", list.MemberCount())
	fmt.Printf("Subscribers: %v\n\n", list.SubscriberCount())
}

func fetchAndPrintList(client *twittergo.Client, path string, query url.Values) (err error) {
	var (
		req     *http.Request
		resp    *twittergo.APIResponse
		results twittergo.Lists
	)
	for {
		url := fmt.Sprintf("%v?%v", path, query.Encode())
		req, err = http.NewRequest("GET", url, nil)
		req.Header.Set("Accept-Encoding", "gzip, deflate")
		if err != nil {
			err = fmt.Errorf("Could not parse request: %v\n", err)
			return
		}
		resp, err = client.SendRequest(req)
		if err != nil {
			err = fmt.Errorf("Could not send request: %v\n", err)
			return
		}
		results = twittergo.Lists{}
		if err = resp.Parse(&results); err != nil {
			if err = handleRateLimit(err); err != nil {
				err = fmt.Errorf("Problem parsing response: %v\n", err)
				return
			} else {
				continue
			}
		}
		fmt.Printf("\n")
		for i, list := range results {
			fmt.Printf("%v.) ", i+1)
			printList(&list)
		}
		printRateLimit(resp)
		return
	}
	return
}

func fetchAndPrintCursoredList(client *twittergo.Client, path string, query url.Values) (err error) {
	var (
		req     *http.Request
		resp    *twittergo.APIResponse
		results twittergo.CursoredLists
		i       int64
	)
	i = 1
	query.Set("cursor", "-1")
	for {
		url := fmt.Sprintf("%v?%v", path, query.Encode())
		req, err = http.NewRequest("GET", url, nil)
		req.Header.Set("Accept-Encoding", "gzip, deflate")
		if err != nil {
			err = fmt.Errorf("Could not parse request: %v\n", err)
			break
		}
		resp, err = client.SendRequest(req)
		if err != nil {
			err = fmt.Errorf("Could not send request: %v\n", err)
			break
		}
		results = twittergo.CursoredLists{}
		if err = resp.Parse(&results); err != nil {
			if err = handleRateLimit(err); err != nil {
				err = fmt.Errorf("Problem parsing response: %v\n", err)
				break
			} else {
				continue
			}
		}
		fmt.Printf("\n")
		for _, list := range results.Lists() {
			fmt.Printf("%v.) ", i)
			printList(&list)
			i += 1
		}
		printRateLimit(resp)
		if results.NextCursorStr() == "0" {
			break
		}
		query.Set("cursor", results.NextCursorStr())
	}
	return
}

func main() {
	var (
		err    error
		args   *Args
		client *twittergo.Client
	)
	args = parseArgs()
	if client, err = LoadCredentials(); err != nil {
		fmt.Printf("Could not parse CREDENTIALS file: %v\n", err)
		os.Exit(1)
	}
	query := url.Values{}
	query.Set("screen_name", args.ScreenName)

	fmt.Printf("Printing up to 100 lists %v owns or is subscribed to:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintList(client, "/1.1/lists/list.json", query); err != nil {
		fmt.Println("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

	// Add count for future requests
	query.Set("count", args.Count)

	fmt.Printf("Printing the lists %v is a member of:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintCursoredList(client, "/1.1/lists/memberships.json", query); err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

	fmt.Printf("Printing the lists %v is subscribed to:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintCursoredList(client, "/1.1/lists/subscriptions.json", query); err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

	fmt.Printf("Printing the lists %v is owner of:\n", args.ScreenName)
	fmt.Printf("=========================================================\n")
	if err = fetchAndPrintCursoredList(client, "/1.1/lists/ownerships.json", query); err != nil {
		fmt.Printf("Error: %v\n", err)
	}
}
<|endoftext|>


<commit_before>package captain // import "github.com/harbur/captain/captain"

func getRevision() string {
	return oneliner("git", "rev-parse", "--short", "HEAD")
}

func getBranch() string {
	return oneliner("git", "rev-parse", "--abbrev-ref", "HEAD")
}

func isDirty() bool {
	var res = oneliner("git", "status", "--porcelain")
	return len(res) > 0
}

func isGit() bool {
	var res = getRevision()
	return len(res) > 0
}
<commit_msg>Fixes #5 Add mapping of '/' char to '.' char whne translating from git tags to docker tags<commit_after>package captain // import "github.com/harbur/captain/captain"

import (
    "strings"
)

func getRevision() string {
	return oneliner("git", "rev-parse", "--short", "HEAD")
}

func getBranch() string {
	branch := oneliner("git", "rev-parse", "--abbrev-ref", "HEAD")
	branch = strings.Replace(branch, "/", ".", -1)
	return branch
}

func isDirty() bool {
	var res = oneliner("git", "status", "--porcelain")
	return len(res) > 0
}

func isGit() bool {
	var res = getRevision()
	return len(res) > 0
}
<|endoftext|>


<commit_before>package logrus

import (
	"io/ioutil"
	"os/exec"
	"testing"
	"time"
)

func TestRegister(t *testing.T) {
	current := len(handlers)
	RegisterExitHandler(func() {})
	if len(handlers) != current+1 {
		t.Fatalf("can't add handler")
	}
}

func TestHandler(t *testing.T) {
	gofile := "/tmp/testprog.go"
	if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil {
		t.Fatalf("can't create go file")
	}

	outfile := "/tmp/testprog.out"
	arg := time.Now().UTC().String()
	err := exec.Command("go", "run", gofile, outfile, arg).Run()
	if err == nil {
		t.Fatalf("completed normally, should have failed")
	}

	data, err := ioutil.ReadFile(outfile)
	if err != nil {
		t.Fatalf("can't read output file %s", outfile)
	}

	if string(data) != arg {
		t.Fatalf("bad data")
	}
}

var testprog = []byte(`
// Test program for atexit, gets output file and data as arguments and writes
// data to output file in atexit handler.
package main

import (
	"github.com/sirupsen/logrus"
	"flag"
	"fmt"
	"io/ioutil"
)

var outfile = ""
var data = ""

func handler() {
	ioutil.WriteFile(outfile, []byte(data), 0666)
}

func badHandler() {
	n := 0
	fmt.Println(1/n)
}

func main() {
	flag.Parse()
	outfile = flag.Arg(0)
	data = flag.Arg(1)

	logrus.RegisterExitHandler(handler)
	logrus.RegisterExitHandler(badHandler)
	logrus.Fatal("Bye bye")
}
`)
<commit_msg>improve test failure messages for alt_exit_test<commit_after>package logrus

import (
	"io/ioutil"
	"os/exec"
	"testing"
	"time"
)

func TestRegister(t *testing.T) {
	current := len(handlers)
	RegisterExitHandler(func() {})
	if len(handlers) != current+1 {
		t.Fatalf("expected %d handlers, got %d", current+1, len(handlers))
	}
}

func TestHandler(t *testing.T) {
	gofile := "/tmp/testprog.go"
	if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil {
		t.Fatalf("can't create go file. %q", err)
	}

	outfile := "/tmp/testprog.out"
	arg := time.Now().UTC().String()
	err := exec.Command("go", "run", gofile, outfile, arg).Run()
	if err == nil {
		t.Fatalf("completed normally, should have failed")
	}

	data, err := ioutil.ReadFile(outfile)
	if err != nil {
		t.Fatalf("can't read output file %s. %q", outfile, err)
	}

	if string(data) != arg {
		t.Fatalf("bad data. Expected %q, got %q", data, arg)
	}
}

var testprog = []byte(`
// Test program for atexit, gets output file and data as arguments and writes
// data to output file in atexit handler.
package main

import (
	"github.com/sirupsen/logrus"
	"flag"
	"fmt"
	"io/ioutil"
)

var outfile = ""
var data = ""

func handler() {
	ioutil.WriteFile(outfile, []byte(data), 0666)
}

func badHandler() {
	n := 0
	fmt.Println(1/n)
}

func main() {
	flag.Parse()
	outfile = flag.Arg(0)
	data = flag.Arg(1)

	logrus.RegisterExitHandler(handler)
	logrus.RegisterExitHandler(badHandler)
	logrus.Fatal("Bye bye")
}
`)
<|endoftext|>


<commit_before>package amqp

import (
	"errors"
	"fmt"
	"runtime/debug"
	"sync"
	"time"

	"github.com/eventials/goevents/messaging"

	log "github.com/sirupsen/logrus"
	amqplib "github.com/streadway/amqp"
)

// ErrNotAcked indicated that published messages was not acked by RabbitMQ
var ErrNotAcked = errors.New("message was not acked")
var ErrTimedout = errors.New("message was timed out")

type message struct {
	action string
	msg    amqplib.Publishing
}

// producer holds a amqp connection and channel to publish messages to.
type producer struct {
	m               sync.RWMutex
	wg              sync.WaitGroup
	conn            *connection
	channel         *amqplib.Channel
	notifyConfirm   chan amqplib.Confirmation
	notifyChanClose chan *amqplib.Error
	config          ProducerConfig

	internalQueue chan message

	exchangeName string

	closed       bool
	channelReady bool
	closes       []chan bool
}

// ProducerConfig to be used when creating a new producer.
type ProducerConfig struct {
	PublishInterval time.Duration
	ConfirmTimeout  time.Duration
}

// NewProducer returns a new AMQP Producer.
// Uses a default ProducerConfig with 2 second of publish interval.
func NewProducer(c messaging.Connection, exchange string) (*producer, error) {
	return NewProducerConfig(c, exchange, ProducerConfig{
		PublishInterval: 2 * time.Second,
		ConfirmTimeout:  10 * time.Second,
	})
}

// NewProducerConfig returns a new AMQP Producer.
func NewProducerConfig(c messaging.Connection, exchange string, config ProducerConfig) (*producer, error) {
	producer := &producer{
		conn:          c.(*connection),
		config:        config,
		internalQueue: make(chan message),
		exchangeName:  exchange,
	}

	err := producer.setupTopology()

	if err != nil {
		return nil, err
	}

	go producer.drainInternalQueue()
	go producer.handleReestablishedConnnection()

	return producer, err
}

// Publish publishes an action.
func (p *producer) Publish(action string, data []byte) {
	// ignore messages published to a closed producer
	if p.isClosed() {
		return
	}

	messageID, _ := NewUUIDv4()

	p.publishAmqMessage(action, amqplib.Publishing{
		MessageId:    messageID,
		DeliveryMode: amqplib.Persistent,
		Timestamp:    time.Now().UTC(),
		Body:         data,
	})
}

func (p *producer) publishAmqMessage(queue string, msg amqplib.Publishing) {
	p.wg.Add(1)

	log.WithFields(log.Fields{
		"action":     queue,
		"message_id": msg.MessageId,
		"type":       "goevents",
		"sub_type":   "producer",
		"exchange":   p.exchangeName,
		"length":     len(p.internalQueue),
	}).Debug("Publishing message to internal queue.")

	p.internalQueue <- message{
		action: queue,
		msg:    msg,
	}
}

// NotifyClose returns a channel to be notified then this producer closes.
func (p *producer) NotifyClose() <-chan bool {
	receiver := make(chan bool, 1)

	p.m.Lock()
	p.closes = append(p.closes, receiver)
	p.m.Unlock()

	return receiver
}

func (p *producer) setClosed() {
	p.m.Lock()
	defer p.m.Unlock()

	p.closed = true
}

func (p *producer) notifyProducerClosed() {
	p.m.RLock()
	defer p.m.RUnlock()

	for _, c := range p.closes {
		c <- true
	}
}

// Close the producer's internal queue.
func (p *producer) Close() {
	p.setClosed()

	p.wg.Wait()

	close(p.internalQueue)

	p.channel.Close()

	p.notifyProducerClosed()
}

// changeChannel takes a new channel to the queue,
// and updates the channel listeners to reflect this.
func (p *producer) changeChannel(channel *amqplib.Channel) {
	p.channel = channel

	p.notifyChanClose = make(chan *amqplib.Error)
	p.channel.NotifyClose(p.notifyChanClose)

	p.notifyConfirm = make(chan amqplib.Confirmation)
	p.channel.NotifyPublish(p.notifyConfirm)

	p.channelReady = true
}

func (p *producer) setupTopology() error {
	log.WithFields(log.Fields{
		"type":     "goevents",
		"sub_type": "producer",
	}).Debug("Setting up topology...")

	p.m.Lock()
	defer p.m.Unlock()

	channel, err := p.conn.openChannel()

	if err != nil {
		return err
	}

	if p.exchangeName != "" {
		if err != nil {
			return err
		}

		err = channel.ExchangeDeclare(
			p.exchangeName, // name
			"topic",        // type
			true,           // durable
			false,          // auto-delete
			false,          // internal
			false,          // no-wait
			nil,            // arguments
		)

		if err != nil {
			return err
		}
	}

	err = channel.Confirm(false)

	if err != nil {
		err = fmt.Errorf("Channel could not be put into confirm mode: %s", err)
		return err
	}

	p.changeChannel(channel)

	log.WithFields(log.Fields{
		"type":     "goevents",
		"sub_type": "producer",
	}).Debug("Topology ready.")

	return nil
}

func (p *producer) setChannelReady(ready bool) {
	p.m.Lock()
	defer p.m.Unlock()

	p.channelReady = ready
}

func (p *producer) isChannelReady() bool {
	p.m.RLock()
	defer p.m.RUnlock()

	return p.channelReady
}

func (p *producer) isConnected() bool {
	if !p.conn.IsConnected() {
		return false
	}

	return p.isChannelReady()
}

func (p *producer) waitConnectionLost() bool {
	if !p.isConnected() {
		return true
	}

	defer p.setChannelReady(false)

	select {
	case <-p.conn.NotifyConnectionClose():
		log.Warn("Producer connection closed")
		return true
	case <-p.notifyChanClose:
		log.Warn("Producer channel closed")
		return false
	}
}

func (p *producer) handleReestablishedConnnection() {
	rs := p.conn.NotifyReestablish()

	for !p.isClosed() {
		// true if connection is lot
		// false if channel connection is lost
		connectionLost := p.waitConnectionLost()

		if connectionLost {
			// Wait reconnect
			<-rs
		}

		err := p.setupTopology()
		if err != nil {
			log.WithFields(log.Fields{
				"type":     "goevents",
				"sub_type": "producer",
				"error":    err,
			}).Error("Error setting up topology after reconnection.")
		}
	}
}

func (p *producer) publishMessage(msg amqplib.Publishing, queue string) (err error) {
	if !p.isConnected() {
		err = errors.New("connection/channel is not open")
		return
	}

	logMessage := log.WithFields(log.Fields{
		"action":     queue,
		"message_id": msg.MessageId,
		"type":       "goevents",
		"sub_type":   "producer",
		"exchange":   p.exchangeName,
	})

	logMessage.WithFields(log.Fields{
		"body": msg.Body,
	}).Debug("Publishing message to the exchange.")

	defer func() {
		if r := recover(); r != nil {
			debug.PrintStack()

			switch x := r.(type) {
			case string:
				err = errors.New(x)
			case error:
				err = x
			default:
				err = errors.New("Unknown panic")
			}
		}
	}()

	err = p.channel.Publish(
		p.exchangeName, // Exchange
		queue,          // Routing key
		false,          // Mandatory
		false,          // Immediate
		msg)

	if err != nil {
		return
	}

	logMessage.Debug("Waiting message to be acked or timed out.")

	select {
	case confirm := <-p.notifyConfirm:
		if confirm.Ack {
			return
		}

		err = ErrNotAcked
		return
	case <-time.After(p.config.ConfirmTimeout):
		err = ErrTimedout
		return
	}

	return
}

func (p *producer) isClosed() bool {
	p.m.RLock()
	defer p.m.RUnlock()

	return p.closed
}

func (p *producer) drainInternalQueue() {
	for m := range p.internalQueue {
		retry := true

		for retry {
			// block until confirmation
			err := p.publishMessage(m.msg, m.action)

			if err != nil {
				log.WithFields(log.Fields{
					"action":     m.action,
					"body":       m.msg.Body,
					"message_id": m.msg.MessageId,
					"error":      err,
					"type":       "goevents",
					"sub_type":   "producer",
				}).Error("Error publishing message to the exchange. Retrying...")

				if err == ErrTimedout {
					log.Warn("Closing producer channel due timeout wating msg confirmation")

					// force close to run setupTopology
					p.setChannelReady(false)
					p.channel.Close()
				}

				time.Sleep(p.config.PublishInterval)
			} else {
				p.wg.Done()
				retry = false
			}
		}
	}
}
<commit_msg>Increased confirms channel length<commit_after>package amqp

import (
	"errors"
	"fmt"
	"runtime/debug"
	"sync"
	"time"

	"github.com/eventials/goevents/messaging"

	log "github.com/sirupsen/logrus"
	amqplib "github.com/streadway/amqp"
)

// ErrNotAcked indicated that published messages was not acked by RabbitMQ
var ErrNotAcked = errors.New("message was not acked")
var ErrTimedout = errors.New("message was timed out")

type message struct {
	action string
	msg    amqplib.Publishing
}

// producer holds a amqp connection and channel to publish messages to.
type producer struct {
	m               sync.RWMutex
	wg              sync.WaitGroup
	conn            *connection
	channel         *amqplib.Channel
	notifyConfirm   chan amqplib.Confirmation
	notifyChanClose chan *amqplib.Error
	config          ProducerConfig

	internalQueue chan message

	exchangeName string

	closed       bool
	channelReady bool
	closes       []chan bool
}

// ProducerConfig to be used when creating a new producer.
type ProducerConfig struct {
	PublishInterval time.Duration
	ConfirmTimeout  time.Duration
}

// NewProducer returns a new AMQP Producer.
// Uses a default ProducerConfig with 2 second of publish interval.
func NewProducer(c messaging.Connection, exchange string) (*producer, error) {
	return NewProducerConfig(c, exchange, ProducerConfig{
		PublishInterval: 2 * time.Second,
		ConfirmTimeout:  10 * time.Second,
	})
}

// NewProducerConfig returns a new AMQP Producer.
func NewProducerConfig(c messaging.Connection, exchange string, config ProducerConfig) (*producer, error) {
	producer := &producer{
		conn:          c.(*connection),
		config:        config,
		internalQueue: make(chan message),
		exchangeName:  exchange,
	}

	err := producer.setupTopology()

	if err != nil {
		return nil, err
	}

	go producer.drainInternalQueue()
	go producer.handleReestablishedConnnection()

	return producer, err
}

// Publish publishes an action.
func (p *producer) Publish(action string, data []byte) {
	// ignore messages published to a closed producer
	if p.isClosed() {
		return
	}

	messageID, _ := NewUUIDv4()

	p.publishAmqMessage(action, amqplib.Publishing{
		MessageId:    messageID,
		DeliveryMode: amqplib.Persistent,
		Timestamp:    time.Now().UTC(),
		Body:         data,
	})
}

func (p *producer) publishAmqMessage(queue string, msg amqplib.Publishing) {
	p.wg.Add(1)

	log.WithFields(log.Fields{
		"action":     queue,
		"message_id": msg.MessageId,
		"type":       "goevents",
		"sub_type":   "producer",
		"exchange":   p.exchangeName,
		"length":     len(p.internalQueue),
	}).Debug("Publishing message to internal queue.")

	p.internalQueue <- message{
		action: queue,
		msg:    msg,
	}
}

// NotifyClose returns a channel to be notified then this producer closes.
func (p *producer) NotifyClose() <-chan bool {
	receiver := make(chan bool, 1)

	p.m.Lock()
	p.closes = append(p.closes, receiver)
	p.m.Unlock()

	return receiver
}

func (p *producer) setClosed() {
	p.m.Lock()
	defer p.m.Unlock()

	p.closed = true
}

func (p *producer) notifyProducerClosed() {
	p.m.RLock()
	defer p.m.RUnlock()

	for _, c := range p.closes {
		c <- true
	}
}

// Close the producer's internal queue.
func (p *producer) Close() {
	p.setClosed()

	p.wg.Wait()

	close(p.internalQueue)

	p.channel.Close()

	p.notifyProducerClosed()
}

// changeChannel takes a new channel to the queue,
// and updates the channel listeners to reflect this.
func (p *producer) changeChannel(channel *amqplib.Channel) {
	p.channel = channel

	p.notifyChanClose = make(chan *amqplib.Error)
	p.channel.NotifyClose(p.notifyChanClose)

	p.notifyConfirm = make(chan amqplib.Confirmation, 1)
	p.channel.NotifyPublish(p.notifyConfirm)

	p.channelReady = true
}

func (p *producer) setupTopology() error {
	log.WithFields(log.Fields{
		"type":     "goevents",
		"sub_type": "producer",
	}).Debug("Setting up topology...")

	p.m.Lock()
	defer p.m.Unlock()

	channel, err := p.conn.openChannel()

	if err != nil {
		return err
	}

	if p.exchangeName != "" {
		if err != nil {
			return err
		}

		err = channel.ExchangeDeclare(
			p.exchangeName, // name
			"topic",        // type
			true,           // durable
			false,          // auto-delete
			false,          // internal
			false,          // no-wait
			nil,            // arguments
		)

		if err != nil {
			return err
		}
	}

	err = channel.Confirm(false)

	if err != nil {
		err = fmt.Errorf("Channel could not be put into confirm mode: %s", err)
		return err
	}

	p.changeChannel(channel)

	log.WithFields(log.Fields{
		"type":     "goevents",
		"sub_type": "producer",
	}).Debug("Topology ready.")

	return nil
}

func (p *producer) setChannelReady(ready bool) {
	p.m.Lock()
	defer p.m.Unlock()

	p.channelReady = ready
}

func (p *producer) isChannelReady() bool {
	p.m.RLock()
	defer p.m.RUnlock()

	return p.channelReady
}

func (p *producer) isConnected() bool {
	if !p.conn.IsConnected() {
		return false
	}

	return p.isChannelReady()
}

func (p *producer) waitConnectionLost() bool {
	if !p.isConnected() {
		return true
	}

	defer p.setChannelReady(false)

	select {
	case <-p.conn.NotifyConnectionClose():
		log.Warn("Producer connection closed")
		return true
	case <-p.notifyChanClose:
		log.Warn("Producer channel closed")
		return false
	}
}

func (p *producer) handleReestablishedConnnection() {
	rs := p.conn.NotifyReestablish()

	for !p.isClosed() {
		// true if connection is lot
		// false if channel connection is lost
		connectionLost := p.waitConnectionLost()

		if connectionLost {
			// Wait reconnect
			<-rs
		}

		err := p.setupTopology()
		if err != nil {
			log.WithFields(log.Fields{
				"type":     "goevents",
				"sub_type": "producer",
				"error":    err,
			}).Error("Error setting up topology after reconnection.")
		}
	}
}

func (p *producer) publishMessage(msg amqplib.Publishing, queue string) (err error) {
	if !p.isConnected() {
		err = errors.New("connection/channel is not open")
		return
	}

	logMessage := log.WithFields(log.Fields{
		"action":     queue,
		"message_id": msg.MessageId,
		"type":       "goevents",
		"sub_type":   "producer",
		"exchange":   p.exchangeName,
	})

	logMessage.WithFields(log.Fields{
		"body": msg.Body,
	}).Debug("Publishing message to the exchange.")

	defer func() {
		if r := recover(); r != nil {
			debug.PrintStack()

			switch x := r.(type) {
			case string:
				err = errors.New(x)
			case error:
				err = x
			default:
				err = errors.New("Unknown panic")
			}
		}
	}()

	err = p.channel.Publish(
		p.exchangeName, // Exchange
		queue,          // Routing key
		false,          // Mandatory
		false,          // Immediate
		msg)

	if err != nil {
		return
	}

	logMessage.Debug("Waiting message to be acked or timed out.")

	select {
	case confirm := <-p.notifyConfirm:
		if confirm.Ack {
			return
		}

		err = ErrNotAcked
		return
	case <-time.After(p.config.ConfirmTimeout):
		err = ErrTimedout
		return
	}

	return
}

func (p *producer) isClosed() bool {
	p.m.RLock()
	defer p.m.RUnlock()

	return p.closed
}

func (p *producer) drainInternalQueue() {
	for m := range p.internalQueue {
		retry := true

		for retry {
			// block until confirmation
			err := p.publishMessage(m.msg, m.action)

			if err != nil {
				log.WithFields(log.Fields{
					"action":     m.action,
					"body":       m.msg.Body,
					"message_id": m.msg.MessageId,
					"error":      err,
					"type":       "goevents",
					"sub_type":   "producer",
				}).Error("Error publishing message to the exchange. Retrying...")

				if err == ErrTimedout {
					log.Warn("Closing producer channel due timeout wating msg confirmation")

					// force close to run setupTopology
					p.setChannelReady(false)
					p.channel.Close()
				}

				time.Sleep(p.config.PublishInterval)
			} else {
				p.wg.Done()
				retry = false
			}
		}
	}
}
<|endoftext|>


<commit_before>package worker

import (
	"encoding/json"
	"strings"
	"testing"
	"time"

	gocontext "context"

	"github.com/bitly/go-simplejson"
	"github.com/streadway/amqp"
	"github.com/stretchr/testify/assert"
	"github.com/travis-ci/worker/backend"
)

type fakeAMQPAcknowledger struct {
	lastAckTag    uint64
	lastAckMult   bool
	lastNackTag   uint64
	lastNackMult  bool
	lastNackReq   bool
	lastRejectTag uint64
	lastRejectReq bool
}

func (a *fakeAMQPAcknowledger) Ack(tag uint64, mult bool) error {
	a.lastAckTag = tag
	a.lastAckMult = mult
	return nil
}

func (a *fakeAMQPAcknowledger) Nack(tag uint64, mult bool, req bool) error {
	a.lastNackTag = tag
	a.lastNackMult = mult
	a.lastNackReq = req
	return nil
}

func (a *fakeAMQPAcknowledger) Reject(tag uint64, req bool) error {
	a.lastRejectTag = tag
	a.lastRejectReq = req
	return nil
}

func newTestAMQPJob(t *testing.T) *amqpJob {
	amqpConn, logChan := setupAMQPConn(t)

	payload := &JobPayload{
		Type: "job:test",
		Job: JobJobPayload{
			ID:       uint64(123),
			Number:   "1",
			QueuedAt: new(time.Time),
		},
		Build: BuildPayload{
			ID:     uint64(456),
			Number: "1",
		},
		UUID:   "870f986d-a88f-4801-86cc-3d2dbc6c80da",
		Config: map[string]interface{}{},
		Timeouts: TimeoutsPayload{
			HardLimit:  uint64(9000),
			LogSilence: uint64(8001),
		},
	}
	startAttributes := &backend.StartAttributes{
		Language: "go",
		Dist:     "trusty",
	}

	body, err := json.Marshal(payload)
	if err != nil {
		t.Error(err)
	}

	delivery := amqp.Delivery{
		Body:         body,
		Acknowledger: &fakeAMQPAcknowledger{},
	}

	rawPayload, err := simplejson.NewJson(body)
	if err != nil {
		t.Error(err)
	}

	stateUpdatePool := newStateUpdatePool(amqpConn, 1)
	defer stateUpdatePool.Close()

	return &amqpJob{
		conn:            amqpConn,
		logWriterChan:   logChan,
		stateUpdatePool: stateUpdatePool,
		delivery:        delivery,
		payload:         payload,
		rawPayload:      rawPayload,
		startAttributes: startAttributes,
		received:        time.Now().Add(-3 * time.Minute),
		started:         time.Now().Add(-2 * time.Minute),
		finished:        time.Now().Add(-3 * time.Second),
	}
}

func TestAMQPJob(t *testing.T) {
	job := newTestAMQPJob(t)

	if job.Payload() == nil {
		t.Fatalf("payload not set")
	}

	if job.RawPayload() == nil {
		t.Fatalf("raw payload not set")
	}

	if job.StartAttributes() == nil {
		t.Fatalf("start attributes not set")
	}

	if job.GoString() == "" {
		t.Fatalf("go string is empty")
	}
}

func TestAMQPJob_GoString(t *testing.T) {
	job := newTestAMQPJob(t)

	str := job.GoString()

	if !strings.HasPrefix(str, "&amqpJob{") && !strings.HasSuffix(str, "}") {
		t.Fatalf("go string has unexpected format: %q", str)
	}
}

func TestAMQPJob_Error(t *testing.T) {
	job := newTestAMQPJob(t)

	err := job.Error(gocontext.TODO(), "wat")
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_Requeue(t *testing.T) {
	job := newTestAMQPJob(t)
	ctx := gocontext.TODO()

	err := job.Requeue(ctx)
	if err != nil {
		t.Error(err)
	}

	acker := job.delivery.Acknowledger.(*fakeAMQPAcknowledger)
	if acker.lastAckMult {
		t.Fatalf("last ack multiple was true")
	}
}

func TestAMQPJob_Received(t *testing.T) {
	job := newTestAMQPJob(t)

	err := job.Received(gocontext.TODO())
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_Started(t *testing.T) {
	job := newTestAMQPJob(t)

	err := job.Started(gocontext.TODO())
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_Finish(t *testing.T) {
	job := newTestAMQPJob(t)
	ctx := gocontext.TODO()

	err := job.Finish(ctx, FinishStatePassed)
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_createStateUpdateBody(t *testing.T) {
	job := newTestAMQPJob(t)
	body := job.createStateUpdateBody(gocontext.TODO(), "foo")

	assert.Equal(t, "foo", body["state"])

	for _, key := range []string{
		"finished_at",
		"id",
		"meta",
		"queued_at",
		"received_at",
		"started_at",
	} {
		assert.Contains(t, body, key)
	}

	assert.Equal(t, body["meta"].(map[string]interface{})["instance_id"], nil)

	job.received = time.Time{}
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "received_at")

	job.Payload().Job.QueuedAt = nil
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "queued_at")

	job.started = time.Time{}
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "started_at")

	job.finished = time.Time{}
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "finished_at")
}
<commit_msg>do not close stateUpdatePool<commit_after>package worker

import (
	"encoding/json"
	"strings"
	"testing"
	"time"

	gocontext "context"

	"github.com/bitly/go-simplejson"
	"github.com/streadway/amqp"
	"github.com/stretchr/testify/assert"
	"github.com/travis-ci/worker/backend"
)

type fakeAMQPAcknowledger struct {
	lastAckTag    uint64
	lastAckMult   bool
	lastNackTag   uint64
	lastNackMult  bool
	lastNackReq   bool
	lastRejectTag uint64
	lastRejectReq bool
}

func (a *fakeAMQPAcknowledger) Ack(tag uint64, mult bool) error {
	a.lastAckTag = tag
	a.lastAckMult = mult
	return nil
}

func (a *fakeAMQPAcknowledger) Nack(tag uint64, mult bool, req bool) error {
	a.lastNackTag = tag
	a.lastNackMult = mult
	a.lastNackReq = req
	return nil
}

func (a *fakeAMQPAcknowledger) Reject(tag uint64, req bool) error {
	a.lastRejectTag = tag
	a.lastRejectReq = req
	return nil
}

func newTestAMQPJob(t *testing.T) *amqpJob {
	amqpConn, logChan := setupAMQPConn(t)

	payload := &JobPayload{
		Type: "job:test",
		Job: JobJobPayload{
			ID:       uint64(123),
			Number:   "1",
			QueuedAt: new(time.Time),
		},
		Build: BuildPayload{
			ID:     uint64(456),
			Number: "1",
		},
		UUID:   "870f986d-a88f-4801-86cc-3d2dbc6c80da",
		Config: map[string]interface{}{},
		Timeouts: TimeoutsPayload{
			HardLimit:  uint64(9000),
			LogSilence: uint64(8001),
		},
	}
	startAttributes := &backend.StartAttributes{
		Language: "go",
		Dist:     "trusty",
	}

	body, err := json.Marshal(payload)
	if err != nil {
		t.Error(err)
	}

	delivery := amqp.Delivery{
		Body:         body,
		Acknowledger: &fakeAMQPAcknowledger{},
	}

	rawPayload, err := simplejson.NewJson(body)
	if err != nil {
		t.Error(err)
	}

	stateUpdatePool := newStateUpdatePool(amqpConn, 1)

	return &amqpJob{
		conn:            amqpConn,
		logWriterChan:   logChan,
		stateUpdatePool: stateUpdatePool,
		delivery:        delivery,
		payload:         payload,
		rawPayload:      rawPayload,
		startAttributes: startAttributes,
		received:        time.Now().Add(-3 * time.Minute),
		started:         time.Now().Add(-2 * time.Minute),
		finished:        time.Now().Add(-3 * time.Second),
	}
}

func TestAMQPJob(t *testing.T) {
	job := newTestAMQPJob(t)

	if job.Payload() == nil {
		t.Fatalf("payload not set")
	}

	if job.RawPayload() == nil {
		t.Fatalf("raw payload not set")
	}

	if job.StartAttributes() == nil {
		t.Fatalf("start attributes not set")
	}

	if job.GoString() == "" {
		t.Fatalf("go string is empty")
	}
}

func TestAMQPJob_GoString(t *testing.T) {
	job := newTestAMQPJob(t)

	str := job.GoString()

	if !strings.HasPrefix(str, "&amqpJob{") && !strings.HasSuffix(str, "}") {
		t.Fatalf("go string has unexpected format: %q", str)
	}
}

func TestAMQPJob_Error(t *testing.T) {
	job := newTestAMQPJob(t)

	err := job.Error(gocontext.TODO(), "wat")
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_Requeue(t *testing.T) {
	job := newTestAMQPJob(t)
	ctx := gocontext.TODO()

	err := job.Requeue(ctx)
	if err != nil {
		t.Error(err)
	}

	acker := job.delivery.Acknowledger.(*fakeAMQPAcknowledger)
	if acker.lastAckMult {
		t.Fatalf("last ack multiple was true")
	}
}

func TestAMQPJob_Received(t *testing.T) {
	job := newTestAMQPJob(t)

	err := job.Received(gocontext.TODO())
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_Started(t *testing.T) {
	job := newTestAMQPJob(t)

	err := job.Started(gocontext.TODO())
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_Finish(t *testing.T) {
	job := newTestAMQPJob(t)
	ctx := gocontext.TODO()

	err := job.Finish(ctx, FinishStatePassed)
	if err != nil {
		t.Error(err)
	}
}

func TestAMQPJob_createStateUpdateBody(t *testing.T) {
	job := newTestAMQPJob(t)
	body := job.createStateUpdateBody(gocontext.TODO(), "foo")

	assert.Equal(t, "foo", body["state"])

	for _, key := range []string{
		"finished_at",
		"id",
		"meta",
		"queued_at",
		"received_at",
		"started_at",
	} {
		assert.Contains(t, body, key)
	}

	assert.Equal(t, body["meta"].(map[string]interface{})["instance_id"], nil)

	job.received = time.Time{}
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "received_at")

	job.Payload().Job.QueuedAt = nil
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "queued_at")

	job.started = time.Time{}
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "started_at")

	job.finished = time.Time{}
	assert.NotContains(t, job.createStateUpdateBody(gocontext.TODO(), "foo"), "finished_at")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

func init() {
	fmt.Println("REGISTERING HANDLER: HOST")
	h := NewHandler()
	h.CommandName = "host"
	h.CommandPattern = "(host)(( )(.*))"
	h.HandlerFunc = func(cmd *Command) string {
		if cmd.Args == "" {
			return "Server host: " + server.host
		} else {
			arg := cmd.Args
			server.host = arg
			return "Set server host: " + arg
		}
	}
	HandlerRegistry[h.CommandName] = h
}
<commit_msg>Removed debug println.<commit_after>package main

import ()

func init() {
	h := NewHandler()
	h.CommandName = "host"
	h.CommandPattern = "(host)(( )(.*))"
	h.HandlerFunc = func(cmd *Command) string {
		if cmd.Args == "" {
			return "Server host: " + server.host
		} else {
			arg := cmd.Args
			server.host = arg
			return "Set server host: " + arg
		}
	}
	HandlerRegistry[h.CommandName] = h
}
<|endoftext|>


<commit_before>package echo

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"net/http"
	"reflect"
	"runtime"
	"sync"

	"github.com/labstack/gommon/log"
	"github.com/webx-top/echo/engine"
	"github.com/webx-top/echo/logger"
)

type (
	Echo struct {
		prefix           string
		middleware       []Middleware
		head             Handler
		maxParam         *int
		notFoundHandler  HandlerFunc
		httpErrorHandler HTTPErrorHandler
		binder           Binder
		renderer         Renderer
		pool             sync.Pool
		debug            bool
		router           *Router
		logger           logger.Logger
	}

	Route struct {
		Method  string
		Path    string
		Handler string
	}

	HTTPError struct {
		code    int
		message string
	}

	Middleware interface {
		Handle(Handler) Handler
	}

	MiddlewareFunc func(Handler) Handler

	Handler interface {
		Handle(Context) error
	}

	HandlerFunc func(Context) error

	// HTTPErrorHandler is a centralized HTTP error handler.
	HTTPErrorHandler func(error, Context)

	// Validator is the interface that wraps the Validate method.
	Validator interface {
		Validate() error
	}

	// Renderer is the interface that wraps the Render method.
	Renderer interface {
		Render(w io.Writer, name string, data interface{}, funcMap map[string]interface{}) error
	}
)

const (
	// CONNECT HTTP method
	CONNECT = "CONNECT"
	// DELETE HTTP method
	DELETE = "DELETE"
	// GET HTTP method
	GET = "GET"
	// HEAD HTTP method
	HEAD = "HEAD"
	// OPTIONS HTTP method
	OPTIONS = "OPTIONS"
	// PATCH HTTP method
	PATCH = "PATCH"
	// POST HTTP method
	POST = "POST"
	// PUT HTTP method
	PUT = "PUT"
	// TRACE HTTP method
	TRACE = "TRACE"

	//-------------
	// Media types
	//-------------

	ApplicationJSON                  = "application/json"
	ApplicationJSONCharsetUTF8       = ApplicationJSON + "; " + CharsetUTF8
	ApplicationJavaScript            = "application/javascript"
	ApplicationJavaScriptCharsetUTF8 = ApplicationJavaScript + "; " + CharsetUTF8
	ApplicationXML                   = "application/xml"
	ApplicationXMLCharsetUTF8        = ApplicationXML + "; " + CharsetUTF8
	ApplicationForm                  = "application/x-www-form-urlencoded"
	ApplicationProtobuf              = "application/protobuf"
	ApplicationMsgpack               = "application/msgpack"
	TextHTML                         = "text/html"
	TextHTMLCharsetUTF8              = TextHTML + "; " + CharsetUTF8
	TextPlain                        = "text/plain"
	TextPlainCharsetUTF8             = TextPlain + "; " + CharsetUTF8
	MultipartForm                    = "multipart/form-data"
	OctetStream                      = "application/octet-stream"

	//---------
	// Charset
	//---------

	CharsetUTF8 = "charset=utf-8"

	//---------
	// Headers
	//---------

	AcceptEncoding     = "Accept-Encoding"
	Authorization      = "Authorization"
	ContentDisposition = "Content-Disposition"
	ContentEncoding    = "Content-Encoding"
	ContentLength      = "Content-Length"
	ContentType        = "Content-Type"
	Location           = "Location"
	Upgrade            = "Upgrade"
	Vary               = "Vary"
	WWWAuthenticate    = "WWW-Authenticate"
	XForwardedFor      = "X-Forwarded-For"
	XRealIP            = "X-Real-IP"
	//-----------
	// Protocols
	//-----------

	WebSocket = "websocket"
)

var (
	methods = []string{
		CONNECT,
		DELETE,
		GET,
		HEAD,
		OPTIONS,
		PATCH,
		POST,
		PUT,
		TRACE,
	}

	//--------
	// Errors
	//--------

	ErrUnsupportedMediaType  = NewHTTPError(http.StatusUnsupportedMediaType)
	ErrNotFound              = NewHTTPError(http.StatusNotFound)
	ErrRendererNotRegistered = errors.New("renderer not registered")
	ErrInvalidRedirectCode   = errors.New("invalid redirect status code")

	//----------------
	// Error handlers
	//----------------

	notFoundHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusNotFound)
	})

	methodNotAllowedHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusMethodNotAllowed)
	})
)

// New creates an instance of Echo.
func New() (e *Echo) {
	return NewWithContext(func(e *Echo) interface{} {
		return NewContext(nil, nil, e)
	})
}

func NewWithContext(fn func(*Echo) interface{}) (e *Echo) {
	e = &Echo{maxParam: new(int)}
	e.pool.New = func() interface{} {
		return fn(e)
	}
	e.router = NewRouter(e)

	//----------
	// Defaults
	//----------
	e.SetHTTPErrorHandler(e.DefaultHTTPErrorHandler)
	e.SetBinder(&binder{Echo: e})

	// Logger
	e.logger = log.New("echo")

	return
}

func (f MiddlewareFunc) Handle(h Handler) Handler {
	return f(h)
}

func (f HandlerFunc) Handle(c Context) error {
	return f(c)
}

// Router returns router.
func (e *Echo) Router() *Router {
	return e.router
}

// SetLogger sets the logger instance.
func (e *Echo) SetLogger(l logger.Logger) {
	e.logger = l
}

// Logger returns the logger instance.
func (e *Echo) Logger() logger.Logger {
	return e.logger
}

// DefaultHTTPErrorHandler invokes the default HTTP error handler.
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
	code := http.StatusInternalServerError
	msg := http.StatusText(code)
	if he, ok := err.(*HTTPError); ok {
		code = he.code
		msg = he.message
	}
	if e.debug {
		msg = err.Error()
	}
	if !c.Response().Committed() {
		c.String(code, msg)
	}
	e.logger.Error(err)
}

// SetHTTPErrorHandler registers a custom Echo.HTTPErrorHandler.
func (e *Echo) SetHTTPErrorHandler(h HTTPErrorHandler) {
	e.httpErrorHandler = h
}

// SetBinder registers a custom binder. It's invoked by Context.Bind().
func (e *Echo) SetBinder(b Binder) {
	e.binder = b
}

// SetRenderer registers an HTML template renderer. It's invoked by Context.Render().
func (e *Echo) SetRenderer(r Renderer) {
	e.renderer = r
}

// SetDebug enable/disable debug mode.
func (e *Echo) SetDebug(on bool) {
	e.debug = on
}

// Debug returns debug mode (enabled or disabled).
func (e *Echo) Debug() bool {
	return e.debug
}

// Use adds handler to the middleware chain.
func (e *Echo) Use(middleware ...Middleware) {
	e.middleware = append(e.middleware, middleware...)
}

// Use adds handler to the middleware chain.
func (e *Echo) PreUse(middleware ...Middleware) {
	e.middleware = append(middleware, e.middleware...)
}

// Connect adds a CONNECT route > handler to the router.
func (e *Echo) Connect(path string, h Handler, m ...Middleware) {
	e.add(CONNECT, path, h, m...)
}

// Delete adds a DELETE route > handler to the router.
func (e *Echo) Delete(path string, h Handler, m ...Middleware) {
	e.add(DELETE, path, h, m...)
}

// Get adds a GET route > handler to the router.
func (e *Echo) Get(path string, h Handler, m ...Middleware) {
	e.add(GET, path, h, m...)
}

// Head adds a HEAD route > handler to the router.
func (e *Echo) Head(path string, h Handler, m ...Middleware) {
	e.add(HEAD, path, h, m...)
}

// Options adds an OPTIONS route > handler to the router.
func (e *Echo) Options(path string, h Handler, m ...Middleware) {
	e.add(OPTIONS, path, h, m...)
}

// Patch adds a PATCH route > handler to the router.
func (e *Echo) Patch(path string, h Handler, m ...Middleware) {
	e.add(PATCH, path, h, m...)
}

// Post adds a POST route > handler to the router.
func (e *Echo) Post(path string, h Handler, m ...Middleware) {
	e.add(POST, path, h, m...)
}

// Put adds a PUT route > handler to the router.
func (e *Echo) Put(path string, h Handler, m ...Middleware) {
	e.add(PUT, path, h, m...)
}

// Trace adds a TRACE route > handler to the router.
func (e *Echo) Trace(path string, h Handler, m ...Middleware) {
	e.add(TRACE, path, h, m...)
}

// Any adds a route > handler to the router for all HTTP methods.
func (e *Echo) Any(path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

// Match adds a route > handler to the router for multiple HTTP methods provided.
func (e *Echo) Match(methods []string, path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

func (e *Echo) add(method, path string, handler Handler, middleware ...Middleware) {
	name := handlerName(handler)
	for _, m := range middleware {
		handler = m.Handle(handler)
	}
	e.router.Add(method, path, HandlerFunc(func(c Context) error {
		return handler.Handle(c)
	}), e)
	r := Route{
		Method:  method,
		Path:    path,
		Handler: name,
	}
	e.router.routes = append(e.router.routes, r)
}

// Group creates a new sub-router with prefix.
func (e *Echo) Group(prefix string, m ...Middleware) (g *Group) {
	g = &Group{prefix: prefix, echo: e}
	g.Use(m...)
	return
}

// URI generates a URI from handler.
func (e *Echo) URI(handler Handler, params ...interface{}) string {
	uri := new(bytes.Buffer)
	ln := len(params)
	n := 0
	name := handlerName(handler)
	for _, r := range e.router.routes {
		if r.Handler == name {
			for i, l := 0, len(r.Path); i < l; i++ {
				if r.Path[i] == ':' && n < ln {
					for ; i < l && r.Path[i] != '/'; i++ {
					}
					uri.WriteString(fmt.Sprintf("%v", params[n]))
					n++
				}
				if i < l {
					uri.WriteByte(r.Path[i])
				}
			}
			break
		}
	}
	return uri.String()
}

// URL is an alias for `URI` function.
func (e *Echo) URL(h Handler, params ...interface{}) string {
	return e.URI(h, params...)
}

// Routes returns the registered routes.
func (e *Echo) Routes() []Route {
	return e.router.routes
}

func (e *Echo) doMiddleware() {
	if e.head != nil {
		return
	}
	e.head = e.router.Handle(nil)
	// Chain middleware
	for i := len(e.middleware) - 1; i >= 0; i-- {
		e.head = e.middleware[i].Handle(e.head)
	}
}

func (e *Echo) ServeHTTP(req engine.Request, res engine.Response) {
	c := e.pool.Get().(Context)
	c.Reset(req, res)

	e.doMiddleware()

	if err := e.head.Handle(c); err != nil {
		e.httpErrorHandler(err, c)
	}

	e.pool.Put(c)
}

// Run starts the HTTP engine.
func (e *Echo) Run(eng engine.Engine) {
	eng.SetHandler(e.ServeHTTP)
	eng.SetLogger(e.logger)
	eng.Start()
}

func NewHTTPError(code int, msg ...string) *HTTPError {
	he := &HTTPError{code: code, message: http.StatusText(code)}
	if len(msg) > 0 {
		m := msg[0]
		he.message = m
	}
	return he
}

// SetCode sets code.
func (e *HTTPError) SetCode(code int) {
	e.code = code
}

// Code returns code.
func (e *HTTPError) Code() int {
	return e.code
}

// Error returns message.
func (e *HTTPError) Error() string {
	return e.message
}

func handlerName(h interface{}) string {
	v := reflect.ValueOf(h)
	t := v.Type()
	if t.Kind() == reflect.Func {
		return runtime.FuncForPC(v.Pointer()).Name()
	}
	return t.String()
}

func Methods() []string {
	return methods
}
<commit_msg>update<commit_after>package echo

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"net/http"
	"reflect"
	"runtime"
	"sync"

	"github.com/labstack/gommon/log"
	"github.com/webx-top/echo/engine"
	"github.com/webx-top/echo/logger"
)

type (
	Echo struct {
		prefix           string
		middleware       []Middleware
		head             Handler
		maxParam         *int
		notFoundHandler  HandlerFunc
		httpErrorHandler HTTPErrorHandler
		binder           Binder
		renderer         Renderer
		pool             sync.Pool
		debug            bool
		router           *Router
		logger           logger.Logger
	}

	Route struct {
		Method  string
		Path    string
		Handler string
	}

	HTTPError struct {
		code    int
		message string
	}

	Middleware interface {
		Handle(Handler) Handler
	}

	MiddlewareFunc func(Handler) Handler

	Handler interface {
		Handle(Context) error
	}

	HandlerFunc func(Context) error

	// HTTPErrorHandler is a centralized HTTP error handler.
	HTTPErrorHandler func(error, Context)

	// Validator is the interface that wraps the Validate method.
	Validator interface {
		Validate() error
	}

	// Renderer is the interface that wraps the Render method.
	Renderer interface {
		Render(w io.Writer, name string, data interface{}, funcMap map[string]interface{}) error
	}
)

const (
	// CONNECT HTTP method
	CONNECT = "CONNECT"
	// DELETE HTTP method
	DELETE = "DELETE"
	// GET HTTP method
	GET = "GET"
	// HEAD HTTP method
	HEAD = "HEAD"
	// OPTIONS HTTP method
	OPTIONS = "OPTIONS"
	// PATCH HTTP method
	PATCH = "PATCH"
	// POST HTTP method
	POST = "POST"
	// PUT HTTP method
	PUT = "PUT"
	// TRACE HTTP method
	TRACE = "TRACE"

	//-------------
	// Media types
	//-------------

	ApplicationJSON                  = "application/json"
	ApplicationJSONCharsetUTF8       = ApplicationJSON + "; " + CharsetUTF8
	ApplicationJavaScript            = "application/javascript"
	ApplicationJavaScriptCharsetUTF8 = ApplicationJavaScript + "; " + CharsetUTF8
	ApplicationXML                   = "application/xml"
	ApplicationXMLCharsetUTF8        = ApplicationXML + "; " + CharsetUTF8
	ApplicationForm                  = "application/x-www-form-urlencoded"
	ApplicationProtobuf              = "application/protobuf"
	ApplicationMsgpack               = "application/msgpack"
	TextHTML                         = "text/html"
	TextHTMLCharsetUTF8              = TextHTML + "; " + CharsetUTF8
	TextPlain                        = "text/plain"
	TextPlainCharsetUTF8             = TextPlain + "; " + CharsetUTF8
	MultipartForm                    = "multipart/form-data"
	OctetStream                      = "application/octet-stream"

	//---------
	// Charset
	//---------

	CharsetUTF8 = "charset=utf-8"

	//---------
	// Headers
	//---------

	AcceptEncoding     = "Accept-Encoding"
	Authorization      = "Authorization"
	ContentDisposition = "Content-Disposition"
	ContentEncoding    = "Content-Encoding"
	ContentLength      = "Content-Length"
	ContentType        = "Content-Type"
	Location           = "Location"
	Upgrade            = "Upgrade"
	Vary               = "Vary"
	WWWAuthenticate    = "WWW-Authenticate"
	XForwardedFor      = "X-Forwarded-For"
	XRealIP            = "X-Real-IP"

	//-----------
	// Protocols
	//-----------

	WebSocket = "websocket"
)

var (
	methods = []string{
		CONNECT,
		DELETE,
		GET,
		HEAD,
		OPTIONS,
		PATCH,
		POST,
		PUT,
		TRACE,
	}

	//--------
	// Errors
	//--------

	ErrUnsupportedMediaType  = NewHTTPError(http.StatusUnsupportedMediaType)
	ErrNotFound              = NewHTTPError(http.StatusNotFound)
	ErrRendererNotRegistered = errors.New("renderer not registered")
	ErrInvalidRedirectCode   = errors.New("invalid redirect status code")

	//----------------
	// Error handlers
	//----------------

	notFoundHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusNotFound)
	})

	methodNotAllowedHandler = HandlerFunc(func(c Context) error {
		return NewHTTPError(http.StatusMethodNotAllowed)
	})
)

// New creates an instance of Echo.
func New() (e *Echo) {
	return NewWithContext(func(e *Echo) interface{} {
		return NewContext(nil, nil, e)
	})
}

func NewWithContext(fn func(*Echo) interface{}) (e *Echo) {
	e = &Echo{maxParam: new(int)}
	e.pool.New = func() interface{} {
		return fn(e)
	}
	e.router = NewRouter(e)

	//----------
	// Defaults
	//----------

	e.SetHTTPErrorHandler(e.DefaultHTTPErrorHandler)
	e.SetBinder(&binder{Echo: e})

	// Logger
	e.logger = log.New("echo")

	return
}

func (f MiddlewareFunc) Handle(h Handler) Handler {
	return f(h)
}

func (f HandlerFunc) Handle(c Context) error {
	return f(c)
}

// Router returns router.
func (e *Echo) Router() *Router {
	return e.router
}

// SetLogger sets the logger instance.
func (e *Echo) SetLogger(l logger.Logger) {
	e.logger = l
}

// Logger returns the logger instance.
func (e *Echo) Logger() logger.Logger {
	return e.logger
}

// DefaultHTTPErrorHandler invokes the default HTTP error handler.
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
	code := http.StatusInternalServerError
	msg := http.StatusText(code)
	if he, ok := err.(*HTTPError); ok {
		code = he.code
		msg = he.message
	}
	if e.debug {
		msg = err.Error()
	}
	if !c.Response().Committed() {
		c.String(code, msg)
	}
	e.logger.Error(err)
}

// SetHTTPErrorHandler registers a custom Echo.HTTPErrorHandler.
func (e *Echo) SetHTTPErrorHandler(h HTTPErrorHandler) {
	e.httpErrorHandler = h
}

// SetBinder registers a custom binder. It's invoked by Context.Bind().
func (e *Echo) SetBinder(b Binder) {
	e.binder = b
}

// SetRenderer registers an HTML template renderer. It's invoked by Context.Render().
func (e *Echo) SetRenderer(r Renderer) {
	e.renderer = r
}

// SetDebug enable/disable debug mode.
func (e *Echo) SetDebug(on bool) {
	e.debug = on
}

// Debug returns debug mode (enabled or disabled).
func (e *Echo) Debug() bool {
	return e.debug
}

// Use adds handler to the middleware chain.
func (e *Echo) Use(middleware ...Middleware) {
	e.middleware = append(e.middleware, middleware...)
}

// Use adds handler to the middleware chain.
func (e *Echo) PreUse(middleware ...Middleware) {
	e.middleware = append(middleware, e.middleware...)
}

// Connect adds a CONNECT route > handler to the router.
func (e *Echo) Connect(path string, h Handler, m ...Middleware) {
	e.add(CONNECT, path, h, m...)
}

// Delete adds a DELETE route > handler to the router.
func (e *Echo) Delete(path string, h Handler, m ...Middleware) {
	e.add(DELETE, path, h, m...)
}

// Get adds a GET route > handler to the router.
func (e *Echo) Get(path string, h Handler, m ...Middleware) {
	e.add(GET, path, h, m...)
}

// Head adds a HEAD route > handler to the router.
func (e *Echo) Head(path string, h Handler, m ...Middleware) {
	e.add(HEAD, path, h, m...)
}

// Options adds an OPTIONS route > handler to the router.
func (e *Echo) Options(path string, h Handler, m ...Middleware) {
	e.add(OPTIONS, path, h, m...)
}

// Patch adds a PATCH route > handler to the router.
func (e *Echo) Patch(path string, h Handler, m ...Middleware) {
	e.add(PATCH, path, h, m...)
}

// Post adds a POST route > handler to the router.
func (e *Echo) Post(path string, h Handler, m ...Middleware) {
	e.add(POST, path, h, m...)
}

// Put adds a PUT route > handler to the router.
func (e *Echo) Put(path string, h Handler, m ...Middleware) {
	e.add(PUT, path, h, m...)
}

// Trace adds a TRACE route > handler to the router.
func (e *Echo) Trace(path string, h Handler, m ...Middleware) {
	e.add(TRACE, path, h, m...)
}

// Any adds a route > handler to the router for all HTTP methods.
func (e *Echo) Any(path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

// Match adds a route > handler to the router for multiple HTTP methods provided.
func (e *Echo) Match(methods []string, path string, handler Handler, middleware ...Middleware) {
	for _, m := range methods {
		e.add(m, path, handler, middleware...)
	}
}

func (e *Echo) add(method, path string, handler Handler, middleware ...Middleware) {
	name := handlerName(handler)
	for _, m := range middleware {
		handler = m.Handle(handler)
	}
	e.router.Add(method, path, HandlerFunc(func(c Context) error {
		return handler.Handle(c)
	}), e)
	r := Route{
		Method:  method,
		Path:    path,
		Handler: name,
	}
	e.router.routes = append(e.router.routes, r)
}

// Group creates a new sub-router with prefix.
func (e *Echo) Group(prefix string, m ...Middleware) (g *Group) {
	g = &Group{prefix: prefix, echo: e}
	g.Use(m...)
	return
}

// URI generates a URI from handler.
func (e *Echo) URI(handler Handler, params ...interface{}) string {
	uri := new(bytes.Buffer)
	ln := len(params)
	n := 0
	name := handlerName(handler)
	for _, r := range e.router.routes {
		if r.Handler == name {
			for i, l := 0, len(r.Path); i < l; i++ {
				if r.Path[i] == ':' && n < ln {
					for ; i < l && r.Path[i] != '/'; i++ {
					}
					uri.WriteString(fmt.Sprintf("%v", params[n]))
					n++
				}
				if i < l {
					uri.WriteByte(r.Path[i])
				}
			}
			break
		}
	}
	return uri.String()
}

// URL is an alias for `URI` function.
func (e *Echo) URL(h Handler, params ...interface{}) string {
	return e.URI(h, params...)
}

// Routes returns the registered routes.
func (e *Echo) Routes() []Route {
	return e.router.routes
}

func (e *Echo) doMiddleware() {
	if e.head != nil {
		return
	}
	e.head = e.router.Handle(nil)
	// Chain middleware
	for i := len(e.middleware) - 1; i >= 0; i-- {
		e.head = e.middleware[i].Handle(e.head)
	}
}

func (e *Echo) ServeHTTP(req engine.Request, res engine.Response) {
	c := e.pool.Get().(Context)
	c.Reset(req, res)

	e.doMiddleware()

	if err := e.head.Handle(c); err != nil {
		e.httpErrorHandler(err, c)
	}

	e.pool.Put(c)
}

// Run starts the HTTP engine.
func (e *Echo) Run(eng engine.Engine) {
	eng.SetHandler(e.ServeHTTP)
	eng.SetLogger(e.logger)
	eng.Start()
}

func NewHTTPError(code int, msg ...string) *HTTPError {
	he := &HTTPError{code: code, message: http.StatusText(code)}
	if len(msg) > 0 {
		m := msg[0]
		he.message = m
	}
	return he
}

// SetCode sets code.
func (e *HTTPError) SetCode(code int) {
	e.code = code
}

// Code returns code.
func (e *HTTPError) Code() int {
	return e.code
}

// Error returns message.
func (e *HTTPError) Error() string {
	return e.message
}

func handlerName(h interface{}) string {
	v := reflect.ValueOf(h)
	t := v.Type()
	if t.Kind() == reflect.Func {
		return runtime.FuncForPC(v.Pointer()).Name()
	}
	return t.String()
}

func Methods() []string {
	return methods
}
<|endoftext|>


<commit_before>package ebs

import (
	"encoding/json"
	"errors"
	"fmt"
	"os/exec"
	"syscall"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/boltdb/bolt"
	"github.com/libopenstorage/openstorage/api"
	"github.com/libopenstorage/openstorage/volume"
)

const (
	Name          = "aws"
	AwsBucketName = "OpenStorageAWSBucket"
)

var (
	devMinor int32
)

// This data is persisted in a DB.
type awsVolume struct {
	spec       api.VolumeSpec
	formatted  bool
	attached   bool
	mounted    bool
	device     string
	mountpath  string
	instanceID string
}

// Implements the open storage volume interface.
type awsProvider struct {
	db  *bolt.DB
	ec2 *ec2.EC2
}

func Init(params volume.DriverParams) (volume.VolumeDriver, error) {
	// Initialize the EC2 interface.
	creds := credentials.NewEnvCredentials()
	inst := &awsProvider{ec2: ec2.New(&aws.Config{
		Region:      "us-west-1",
		Credentials: creds,
	}),
	}

	// Create a DB if one does not exist.  This is where we persist the
	// Amazon instance ID, sdevice and volume ID mappings.
	db, err := bolt.Open("openstorage.aws.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		return nil, err
	}

	err = db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucket([]byte(AwsBucketName))
		if err != nil {
			return fmt.Errorf("create bucket: %s", err)
		}
		return nil
	})

	inst.db = db

	return inst, err
}

// AWS provisioned IOPS range is 100 - 20000.
func mapIops(cos api.VolumeCos) int64 {
	if cos < 3 {
		return 1000
	} else if cos < 7 {
		return 10000
	} else {
		return 20000
	}
}

func (self *awsProvider) get(volumeID string) (*awsVolume, error) {
	v := &awsVolume{}

	err := self.db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(AwsBucketName))
		b := bucket.Get([]byte(volumeID))

		if b == nil {
			return errors.New("no such volume ID")
		} else {
			err := json.Unmarshal(b, v)
			return err
		}
	})

	return v, err
}

func (self *awsProvider) put(volumeID string, v *awsVolume) error {
	b, _ := json.Marshal(v)

	err := self.db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(AwsBucketName))
		err := bucket.Put([]byte(volumeID), b)
		return err
	})

	return err
}

func (self *awsProvider) String() string {
	return Name
}

func (self *awsProvider) Create(l api.VolumeLocator, opt *api.CreateOptions, spec *api.VolumeSpec) (api.VolumeID, error) {
	availabilityZone := "us-west-1a"
	sz := int64(spec.Size / (1024 * 1024 * 1024))
	iops := mapIops(spec.Cos)
	req := &ec2.CreateVolumeInput{
		AvailabilityZone: &availabilityZone,
		Size:             &sz,
		IOPS:             &iops}
	v, err := self.ec2.CreateVolume(req)
	if err != nil {
		return api.VolumeID(""), err
	}

	err = self.put(*v.VolumeID, &awsVolume{spec: *spec})

	return api.VolumeID(*v.VolumeID), err
}

func (self *awsProvider) Attach(volumeID api.VolumeID) (string, error) {
	v, err := self.get(string(volumeID))
	if err != nil {
		return "", err
	}

	devMinor++
	device := fmt.Sprintf("/dev/ec2%v", int(devMinor))
	vol := string(volumeID)
	inst := string("")
	req := &ec2.AttachVolumeInput{
		Device:     &device,
		InstanceID: &inst,
		VolumeID:   &vol,
	}

	resp, err := self.ec2.AttachVolume(req)
	if err != nil {
		return "", err
	}

	v.instanceID = inst
	v.attached = true
	err = self.put(string(volumeID), v)

	return *resp.Device, err
}

func (self *awsProvider) Mount(volumeID api.VolumeID, mountpath string) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	err = syscall.Mount(v.device, mountpath, string(v.spec.Format), 0, "")
	if err != nil {
		return err
	}

	v.mountpath = mountpath
	v.mounted = true
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Detach(volumeID api.VolumeID) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	vol := string(volumeID)
	inst := v.instanceID
	force := true
	req := &ec2.DetachVolumeInput{
		InstanceID: &inst,
		VolumeID:   &vol,
		Force:      &force,
	}

	_, err = self.ec2.DetachVolume(req)
	if err != nil {
		return err
	}

	v.instanceID = inst
	v.attached = false
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Unmount(volumeID api.VolumeID, mountpath string) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	err = syscall.Unmount(v.mountpath, 0)
	if err != nil {
		return err
	}

	v.mountpath = ""
	v.mounted = false
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Delete(volumeID api.VolumeID) error {
	return nil
}

func (self *awsProvider) Format(volumeID api.VolumeID) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	if !v.attached {
		return errors.New("volume must be attached")
	}

	if v.mounted {
		return errors.New("volume already mounted")
	}

	if v.formatted {
		return errors.New("volume already formatted")
	}

	cmd := "/sbin/mkfs." + string(v.spec.Format)
	_, err = exec.Command(cmd, v.device).Output()
	if err != nil {
		return err
	}
	// XXX TODO validate output

	v.formatted = true
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Inspect(volumeIDs []api.VolumeID) (volume []api.Volume, err error) {
	return nil, nil
}

func (self *awsProvider) Enumerate(locator api.VolumeLocator, labels api.Labels) (volumes []api.Volume, err error) {
	return nil, errors.New("Unsupported")
}

func (self *awsProvider) Snapshot(volumeID api.VolumeID, labels api.Labels) (snap api.SnapID, err error) {
	return "", errors.New("Unsupported")
}

func (self *awsProvider) SnapDelete(snapID api.SnapID) (err error) {
	return errors.New("Unsupported")
}

func (self *awsProvider) SnapInspect(snapID api.SnapID) (snap api.VolumeSnap, err error) {
	return api.VolumeSnap{}, errors.New("Unsupported")
}

func (self *awsProvider) SnapEnumerate(locator api.VolumeLocator, labels api.Labels) (snaps *[]api.SnapID, err error) {
	return nil, errors.New("Unsupported")
}

func (self *awsProvider) Stats(volumeID api.VolumeID) (stats api.VolumeStats, err error) {
	return api.VolumeStats{}, errors.New("Unsupported")
}

func (self *awsProvider) Alerts(volumeID api.VolumeID) (stats api.VolumeAlerts, err error) {
	return api.VolumeAlerts{}, errors.New("Unsupported")
}

func (self *awsProvider) Shutdown() {
	fmt.Printf("%s Shutting down", Name)
}

func init() {
	// Register ourselves as an openstorage volume driver.
	volume.Register(Name, Init)
}
<commit_msg>use kvdb instead of a local storage<commit_after>package ebs

import (
	"errors"
	"fmt"
	"os/exec"
	"syscall"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/libopenstorage/kvdb"
	"github.com/libopenstorage/openstorage/api"
	"github.com/libopenstorage/openstorage/volume"
)

const (
	Name     = "aws"
	AwsDBKey = "OpenStorageAWSKey"
)

var (
	devMinor int32
)

// This data is persisted in a DB.
type awsVolume struct {
	spec       api.VolumeSpec
	formatted  bool
	attached   bool
	mounted    bool
	device     string
	mountpath  string
	instanceID string
}

// Implements the open storage volume interface.
type awsProvider struct {
	db  kvdb.Kvdb
	ec2 *ec2.EC2
}

func Init(params volume.DriverParams) (volume.VolumeDriver, error) {
	// Initialize the EC2 interface.
	creds := credentials.NewEnvCredentials()
	inst := &awsProvider{ec2: ec2.New(&aws.Config{
		Region:      "us-west-1",
		Credentials: creds,
	}),
	}

	inst.db = kvdb.Instance()

	return inst, nil
}

// AWS provisioned IOPS range is 100 - 20000.
func mapIops(cos api.VolumeCos) int64 {
	if cos < 3 {
		return 1000
	} else if cos < 7 {
		return 10000
	} else {
		return 20000
	}
}

func (self *awsProvider) get(volumeID string) (*awsVolume, error) {
	v := &awsVolume{}
	key := AwsDBKey + "/" + volumeID
	_, err := self.db.GetVal(key, v)
	return v, err
}

func (self *awsProvider) put(volumeID string, v *awsVolume) error {
	key := AwsDBKey + "/" + volumeID
	_, err := self.db.Put(key, v, 0)
	return err
}

func (self *awsProvider) String() string {
	return Name
}

func (self *awsProvider) Create(l api.VolumeLocator, opt *api.CreateOptions, spec *api.VolumeSpec) (api.VolumeID, error) {
	availabilityZone := "us-west-1a"
	sz := int64(spec.Size / (1024 * 1024 * 1024))
	iops := mapIops(spec.Cos)
	req := &ec2.CreateVolumeInput{
		AvailabilityZone: &availabilityZone,
		Size:             &sz,
		IOPS:             &iops}
	v, err := self.ec2.CreateVolume(req)
	if err != nil {
		return api.VolumeID(""), err
	}

	err = self.put(*v.VolumeID, &awsVolume{spec: *spec})

	return api.VolumeID(*v.VolumeID), err
}

func (self *awsProvider) Attach(volumeID api.VolumeID) (string, error) {
	v, err := self.get(string(volumeID))
	if err != nil {
		return "", err
	}

	devMinor++
	device := fmt.Sprintf("/dev/ec2%v", int(devMinor))
	vol := string(volumeID)
	inst := string("")
	req := &ec2.AttachVolumeInput{
		Device:     &device,
		InstanceID: &inst,
		VolumeID:   &vol,
	}

	resp, err := self.ec2.AttachVolume(req)
	if err != nil {
		return "", err
	}

	v.instanceID = inst
	v.attached = true
	err = self.put(string(volumeID), v)

	return *resp.Device, err
}

func (self *awsProvider) Mount(volumeID api.VolumeID, mountpath string) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	err = syscall.Mount(v.device, mountpath, string(v.spec.Format), 0, "")
	if err != nil {
		return err
	}

	v.mountpath = mountpath
	v.mounted = true
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Detach(volumeID api.VolumeID) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	vol := string(volumeID)
	inst := v.instanceID
	force := true
	req := &ec2.DetachVolumeInput{
		InstanceID: &inst,
		VolumeID:   &vol,
		Force:      &force,
	}

	_, err = self.ec2.DetachVolume(req)
	if err != nil {
		return err
	}

	v.instanceID = inst
	v.attached = false
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Unmount(volumeID api.VolumeID, mountpath string) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	err = syscall.Unmount(v.mountpath, 0)
	if err != nil {
		return err
	}

	v.mountpath = ""
	v.mounted = false
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Delete(volumeID api.VolumeID) error {
	return nil
}

func (self *awsProvider) Format(volumeID api.VolumeID) error {
	v, err := self.get(string(volumeID))
	if err != nil {
		return err
	}

	if !v.attached {
		return errors.New("volume must be attached")
	}

	if v.mounted {
		return errors.New("volume already mounted")
	}

	if v.formatted {
		return errors.New("volume already formatted")
	}

	cmd := "/sbin/mkfs." + string(v.spec.Format)
	_, err = exec.Command(cmd, v.device).Output()
	if err != nil {
		return err
	}
	// XXX TODO validate output

	v.formatted = true
	err = self.put(string(volumeID), v)

	return err
}

func (self *awsProvider) Inspect(volumeIDs []api.VolumeID) (volume []api.Volume, err error) {
	return nil, nil
}

func (self *awsProvider) Enumerate(locator api.VolumeLocator, labels api.Labels) (volumes []api.Volume, err error) {
	return nil, errors.New("Unsupported")
}

func (self *awsProvider) Snapshot(volumeID api.VolumeID, labels api.Labels) (snap api.SnapID, err error) {
	return "", errors.New("Unsupported")
}

func (self *awsProvider) SnapDelete(snapID api.SnapID) (err error) {
	return errors.New("Unsupported")
}

func (self *awsProvider) SnapInspect(snapID api.SnapID) (snap api.VolumeSnap, err error) {
	return api.VolumeSnap{}, errors.New("Unsupported")
}

func (self *awsProvider) SnapEnumerate(locator api.VolumeLocator, labels api.Labels) (snaps *[]api.SnapID, err error) {
	return nil, errors.New("Unsupported")
}

func (self *awsProvider) Stats(volumeID api.VolumeID) (stats api.VolumeStats, err error) {
	return api.VolumeStats{}, errors.New("Unsupported")
}

func (self *awsProvider) Alerts(volumeID api.VolumeID) (stats api.VolumeAlerts, err error) {
	return api.VolumeAlerts{}, errors.New("Unsupported")
}

func (self *awsProvider) Shutdown() {
	fmt.Printf("%s Shutting down", Name)
}

func init() {
	// Register ourselves as an openstorage volume driver.
	volume.Register(Name, Init)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/zettio/weave"
	"code.google.com/p/gopacket/layers"
	"crypto/sha256"
	"flag"
	"fmt"
	"io"
	"github.com/davecheney/profile"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
)

func ensureInterface(ifaceName string, wait bool) (iface *net.Interface, err error) {
	iface, err = findInterface(ifaceName)
	if err == nil || !wait {
		return
	}
	log.Println("Waiting for interface", ifaceName, "to come up")
	for err != nil {
		time.Sleep(1 * time.Second)
		iface, err = findInterface(ifaceName)
	}
	log.Println("Interface", ifaceName, "is up")
	return
}

func findInterface(ifaceName string) (iface *net.Interface, err error) {
	iface, err = net.InterfaceByName(ifaceName)
	if err != nil {
		return iface, fmt.Errorf("Unable to find interface %s", ifaceName)
	}
	if 0 == (net.FlagUp & iface.Flags) {
		return iface, fmt.Errorf("Interface %s is not up", ifaceName)
	}
	return
}

func main() {

	log.SetPrefix(weave.Protocol + " ")
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	procs := runtime.NumCPU()
	// packet sniffing can block an OS thread, so we need one thread
	// for that plus at least one more.
	if procs < 2 {
		procs = 2
	}
	runtime.GOMAXPROCS(procs)

	var (
		ifaceName  string
		routerName string
		password   string
		wait       bool
		debug      bool
		prof       string
		peers      []string
		connLimit  int
		bufSz      int
	)

	flag.StringVar(&ifaceName, "iface", "", "name of interface to read from")
	flag.StringVar(&routerName, "name", "", "name of router (defaults to MAC)")
	flag.StringVar(&password, "password", "", "network password")
	flag.BoolVar(&wait, "wait", false, "wait for interface to be created and come up")
	flag.BoolVar(&debug, "debug", false, "enable debug logging")
	flag.StringVar(&prof, "profile", "", "enable profiling and write profiles to given path")
	flag.IntVar(&connLimit, "connlimit", 10, "connection limit (defaults to 10, set to 0 for unlimited)")
	flag.IntVar(&bufSz, "bufsz", 8, "capture buffer size in MB (defaults to 8MB)")
	flag.Parse()
	peers = flag.Args()

	if ifaceName == "" {
		fmt.Println("Missing required parameter 'iface'")
		os.Exit(1)
	}
	iface, err := ensureInterface(ifaceName, wait)
	if err != nil {
		log.Fatal(err)
	}

	if connLimit < 0 {
		connLimit = 0
	}

	if routerName == "" {
		routerName = iface.HardwareAddr.String()
	}

	ourName, err := weave.PeerNameFromUserInput(routerName)
	if err != nil {
		log.Fatal(err)
	}

	var logFrame func(string, []byte, *layers.Ethernet)
	if debug {
		logFrame = func(prefix string, frame []byte, eth *layers.Ethernet) {
			h := fmt.Sprintf("%x", sha256.Sum256(frame))
			if eth == nil {
				log.Println(prefix, len(frame), "bytes (", h, ")")
			} else {
				log.Println(prefix, len(frame), "bytes (", h, "):", eth.SrcMAC, "->", eth.DstMAC)
			}
		}
	} else {
		logFrame = func(prefix string, frame []byte, eth *layers.Ethernet) {}
	}

	if prof != "" {
		p := *profile.CPUProfile
		p.ProfilePath = prof
		defer profile.Start(&p).Stop()
	}

	router := weave.NewRouter(iface, ourName, []byte(password), connLimit, bufSz*1024*1024, logFrame)
	router.Start()
	for _, peer := range peers {
		targetPeer := peer
		go func() {
			if err := router.Ourself.CreateConnection(targetPeer, weave.UnknownPeerName); err != nil {
				log.Println(err)
			}
		}()
	}
	go handleHttp(router)
	handleSignals(router)
}

func handleHttp(router *weave.Router) {
	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		io.WriteString(w, router.Status())
	})
	address := fmt.Sprintf(":%d", weave.StatusPort)
	err := http.ListenAndServe(address, nil)
	if err != nil {
		log.Fatal("Unable to create http listener: ", err)
	}
}

func handleSignals(router *weave.Router) {
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGQUIT, syscall.SIGUSR1)
	buf := make([]byte, 1<<20)
	for {
		sig := <-sigs
		switch sig {
		case syscall.SIGQUIT:
			runtime.Stack(buf, true)
			log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf)
		case syscall.SIGUSR1:
			log.Printf("=== received SIGUSR1 ===\n*** status...\n%s\n*** end\n", router.Status())
		}
	}
}
<commit_msg>gm fmt<commit_after>package main

import (
	"code.google.com/p/gopacket/layers"
	"crypto/sha256"
	"flag"
	"fmt"
	"github.com/davecheney/profile"
	"github.com/zettio/weave"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"
)

func ensureInterface(ifaceName string, wait bool) (iface *net.Interface, err error) {
	iface, err = findInterface(ifaceName)
	if err == nil || !wait {
		return
	}
	log.Println("Waiting for interface", ifaceName, "to come up")
	for err != nil {
		time.Sleep(1 * time.Second)
		iface, err = findInterface(ifaceName)
	}
	log.Println("Interface", ifaceName, "is up")
	return
}

func findInterface(ifaceName string) (iface *net.Interface, err error) {
	iface, err = net.InterfaceByName(ifaceName)
	if err != nil {
		return iface, fmt.Errorf("Unable to find interface %s", ifaceName)
	}
	if 0 == (net.FlagUp & iface.Flags) {
		return iface, fmt.Errorf("Interface %s is not up", ifaceName)
	}
	return
}

func main() {

	log.SetPrefix(weave.Protocol + " ")
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	procs := runtime.NumCPU()
	// packet sniffing can block an OS thread, so we need one thread
	// for that plus at least one more.
	if procs < 2 {
		procs = 2
	}
	runtime.GOMAXPROCS(procs)

	var (
		ifaceName  string
		routerName string
		password   string
		wait       bool
		debug      bool
		prof       string
		peers      []string
		connLimit  int
		bufSz      int
	)

	flag.StringVar(&ifaceName, "iface", "", "name of interface to read from")
	flag.StringVar(&routerName, "name", "", "name of router (defaults to MAC)")
	flag.StringVar(&password, "password", "", "network password")
	flag.BoolVar(&wait, "wait", false, "wait for interface to be created and come up")
	flag.BoolVar(&debug, "debug", false, "enable debug logging")
	flag.StringVar(&prof, "profile", "", "enable profiling and write profiles to given path")
	flag.IntVar(&connLimit, "connlimit", 10, "connection limit (defaults to 10, set to 0 for unlimited)")
	flag.IntVar(&bufSz, "bufsz", 8, "capture buffer size in MB (defaults to 8MB)")
	flag.Parse()
	peers = flag.Args()

	if ifaceName == "" {
		fmt.Println("Missing required parameter 'iface'")
		os.Exit(1)
	}
	iface, err := ensureInterface(ifaceName, wait)
	if err != nil {
		log.Fatal(err)
	}

	if connLimit < 0 {
		connLimit = 0
	}

	if routerName == "" {
		routerName = iface.HardwareAddr.String()
	}

	ourName, err := weave.PeerNameFromUserInput(routerName)
	if err != nil {
		log.Fatal(err)
	}

	var logFrame func(string, []byte, *layers.Ethernet)
	if debug {
		logFrame = func(prefix string, frame []byte, eth *layers.Ethernet) {
			h := fmt.Sprintf("%x", sha256.Sum256(frame))
			if eth == nil {
				log.Println(prefix, len(frame), "bytes (", h, ")")
			} else {
				log.Println(prefix, len(frame), "bytes (", h, "):", eth.SrcMAC, "->", eth.DstMAC)
			}
		}
	} else {
		logFrame = func(prefix string, frame []byte, eth *layers.Ethernet) {}
	}

	if prof != "" {
		p := *profile.CPUProfile
		p.ProfilePath = prof
		defer profile.Start(&p).Stop()
	}

	router := weave.NewRouter(iface, ourName, []byte(password), connLimit, bufSz*1024*1024, logFrame)
	router.Start()
	for _, peer := range peers {
		targetPeer := peer
		go func() {
			if err := router.Ourself.CreateConnection(targetPeer, weave.UnknownPeerName); err != nil {
				log.Println(err)
			}
		}()
	}
	go handleHttp(router)
	handleSignals(router)
}

func handleHttp(router *weave.Router) {
	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		io.WriteString(w, router.Status())
	})
	address := fmt.Sprintf(":%d", weave.StatusPort)
	err := http.ListenAndServe(address, nil)
	if err != nil {
		log.Fatal("Unable to create http listener: ", err)
	}
}

func handleSignals(router *weave.Router) {
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGQUIT, syscall.SIGUSR1)
	buf := make([]byte, 1<<20)
	for {
		sig := <-sigs
		switch sig {
		case syscall.SIGQUIT:
			runtime.Stack(buf, true)
			log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf)
		case syscall.SIGUSR1:
			log.Printf("=== received SIGUSR1 ===\n*** status...\n%s\n*** end\n", router.Status())
		}
	}
}
<|endoftext|>