├── .gitignore ├── Godeps ├── _workspace │ ├── .gitignore │ └── src │ │ └── github.com │ │ ├── cenkalti │ │ └── backoff │ │ │ ├── .travis.yml │ │ │ ├── .gitignore │ │ │ ├── retry_test.go │ │ │ ├── backoff_test.go │ │ │ ├── ticker_test.go │ │ │ ├── LICENSE │ │ │ ├── retry.go │ │ │ ├── backoff.go │ │ │ ├── README.md │ │ │ ├── ticker.go │ │ │ ├── exponential_test.go │ │ │ └── exponential.go │ │ ├── ugorji │ │ └── go │ │ │ ├── codec │ │ │ ├── prebuild.go │ │ │ ├── codecgen │ │ │ │ ├── z.go │ │ │ │ ├── README.md │ │ │ │ └── gen.go │ │ │ ├── helper_not_unsafe.go │ │ │ ├── helper_unsafe.go │ │ │ ├── gen-dec-map.go.tmpl │ │ │ ├── gen-dec-array.go.tmpl │ │ │ ├── gen-helper.generated.go │ │ │ ├── test.py │ │ │ ├── helper_internal.go │ │ │ ├── gen.generated.go │ │ │ ├── rpc.go │ │ │ ├── README.md │ │ │ ├── 0doc.go │ │ │ ├── noop.go │ │ │ ├── prebuild.sh │ │ │ ├── time.go │ │ │ └── gen-helper.go.tmpl │ │ │ └── LICENSE │ │ ├── op │ │ └── go-logging │ │ │ ├── .travis.yml │ │ │ ├── examples │ │ │ ├── example.png │ │ │ └── example.go │ │ │ ├── CONTRIBUTORS │ │ │ ├── CHANGELOG.md │ │ │ ├── syslog_fallback.go │ │ │ ├── backend.go │ │ │ ├── LICENSE │ │ │ ├── syslog.go │ │ │ ├── multi.go │ │ │ ├── log_nix.go │ │ │ ├── README.md │ │ │ ├── log_windows.go │ │ │ ├── level.go │ │ │ ├── memory.go │ │ │ ├── logger.go │ │ │ └── format.go │ │ ├── coreos │ │ └── go-etcd │ │ │ ├── etcd │ │ │ ├── version.go │ │ │ ├── add_child.go │ │ │ ├── member.go │ │ │ ├── compare_and_delete.go │ │ │ ├── compare_and_swap.go │ │ │ ├── get.go │ │ │ ├── cluster.go │ │ │ ├── delete.go │ │ │ ├── error.go │ │ │ ├── debug.go │ │ │ ├── options.go │ │ │ ├── response.go │ │ │ ├── watch.go │ │ │ ├── set_update_create.go │ │ │ └── requests.go │ │ │ └── LICENSE │ │ └── upfluence │ │ └── goutils │ │ └── log │ │ └── logger.go ├── Readme └── Godeps.json ├── Dockerfile ├── etcdenv ├── error.go ├── runner.go └── context.go ├── release ├── README.md └── etcdenv.go /.gitignore: -------------------------------------------------------------------------------- 1 | etcdenv-* 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 1.3.3 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/prebuild.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | //go:generate bash prebuild.sh 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.0 5 | - 1.1 6 | - tip 7 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/z.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const genCodecPath = "github.com/ugorji/go/codec" 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/version.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | const ( 4 | version = "v2" 5 | packageVersion = "v2.0.0" 6 | ) 7 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/examples/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upfluence/etcdenv/HEAD/Godeps/_workspace/src/github.com/op/go-logging/examples/example.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM busybox 2 | 3 | ENV ETCDENV_VERSION=0.4.1 4 | 5 | ADD https://github.com/upfluence/etcdenv/releases/download/v${ETCDENV_VERSION}/etcdenv-linux-amd64-${ETCDENV_VERSION} /etcdenv 6 | RUN ["chmod", "+x", "/etcdenv"] 7 | 8 | ENTRYPOINT ["/etcdenv"] 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Alec Thomas 2 | Guilhem Lettron 3 | Ivan Daniluk 4 | Nimi Wariboko Jr 5 | Róbert Selvek 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /etcdenv/error.go: -------------------------------------------------------------------------------- 1 | package etcdenv 2 | 3 | const ( 4 | ErrKeyNotFound = 100 5 | ErrAlreadyStarted = iota 6 | ErrNotStarted 7 | ) 8 | 9 | var ( 10 | errorMap = map[int]string{ 11 | ErrAlreadyStarted: "The process is already started", 12 | ErrNotStarted: "The process is not started yet", 13 | } 14 | ) 15 | 16 | type EtcdenvError struct { 17 | ErrorCode int 18 | Message string 19 | } 20 | 21 | func (e EtcdenvError) Error() string { 22 | return e.Message 23 | } 24 | 25 | func newError(errorCode int) *EtcdenvError { 26 | return &EtcdenvError{ErrorCode: errorCode, Message: errorMap[errorCode]} 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/add_child.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | // Add a new directory with a random etcd-generated key under the given path. 4 | func (c *Client) AddChildDir(key string, ttl uint64) (*Response, error) { 5 | raw, err := c.post(key, "", ttl) 6 | 7 | if err != nil { 8 | return nil, err 9 | } 10 | 11 | return raw.Unmarshal() 12 | } 13 | 14 | // Add a new file with a random etcd-generated key under the given path. 15 | func (c *Client) AddChild(key string, value string, ttl uint64) (*Response, error) { 16 | raw, err := c.post(key, value, ttl) 17 | 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | return raw.Unmarshal() 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/member.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import "encoding/json" 4 | 5 | type Member struct { 6 | ID string `json:"id"` 7 | Name string `json:"name"` 8 | PeerURLs []string `json:"peerURLs"` 9 | ClientURLs []string `json:"clientURLs"` 10 | } 11 | 12 | type memberCollection []Member 13 | 14 | func (c *memberCollection) UnmarshalJSON(data []byte) error { 15 | d := struct { 16 | Members []Member 17 | }{} 18 | 19 | if err := json.Unmarshal(data, &d); err != nil { 20 | return err 21 | } 22 | 23 | if d.Members == nil { 24 | *c = make([]Member, 0) 25 | return nil 26 | } 27 | 28 | *c = d.Members 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /release: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$#" -ne 1 ]; then 4 | echo "Usage: $0 VERSION" >&2 5 | exit 1 6 | fi 7 | 8 | export GOPATH=`pwd`/Godeps/_workspace:$GOPATH 9 | 10 | version=$1 11 | sed -i "/const currentVersion/c\const currentVersion = \"$version\"" etcdenv.go 12 | sed -i "/ENV ETCDENV_VERSION/c\ENV ETCDENV_VERSION=$version" Dockerfile 13 | 14 | git commit etcdenv.go Dockerfile -m "Release $version" 15 | 16 | git tag v$version 17 | 18 | GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -o etcdenv-linux-amd64-$version . 19 | GOOS=darwin CGO_ENABLED=0 GOARCH=amd64 go build -o etcdenv-darwin-amd64-$version . 20 | 21 | hub release create -a etcdenv-linux-amd64-$version -a etcdenv-darwin-amd64-$version v$version 22 | 23 | rm etcdenv-* 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/retry_test.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "testing" 7 | ) 8 | 9 | func TestRetry(t *testing.T) { 10 | const successOn = 3 11 | var i = 0 12 | 13 | // This function is successfull on "successOn" calls. 14 | f := func() error { 15 | i++ 16 | log.Printf("function is called %d. time\n", i) 17 | 18 | if i == successOn { 19 | log.Println("OK") 20 | return nil 21 | } 22 | 23 | log.Println("error") 24 | return errors.New("error") 25 | } 26 | 27 | err := Retry(f, NewExponentialBackOff()) 28 | if err != nil { 29 | t.Errorf("unexpected error: %s", err.Error()) 30 | } 31 | if i != successOn { 32 | t.Errorf("invalid number of retries: %d", i) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/backoff_test.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "time" 5 | 6 | "testing" 7 | ) 8 | 9 | func TestNextBackOffMillis(t *testing.T) { 10 | subtestNextBackOff(t, 0, new(ZeroBackOff)) 11 | subtestNextBackOff(t, Stop, new(StopBackOff)) 12 | } 13 | 14 | func subtestNextBackOff(t *testing.T, expectedValue time.Duration, backOffPolicy BackOff) { 15 | for i := 0; i < 10; i++ { 16 | next := backOffPolicy.NextBackOff() 17 | if next != expectedValue { 18 | t.Errorf("got: %d expected: %d", next, expectedValue) 19 | } 20 | } 21 | } 22 | 23 | func TestConstantBackOff(t *testing.T) { 24 | backoff := NewConstantBackOff(time.Second) 25 | if backoff.NextBackOff() != time.Second { 26 | t.Error("invalid interval") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 2.0.0-rc1 (2016-02-11) 4 | 5 | Time flies and it has been three years since this package was first released. 6 | There have been a couple of API changes I have wanted to do for some time but 7 | I've tried to maintain backwards compatibility. Some inconsistencies in the 8 | API have started to show, proper vendor support in Go out of the box and 9 | the fact that `go vet` will give warnings -- I have decided to bump the major 10 | version. 11 | 12 | * Make eg. `Info` and `Infof` do different things. You want to change all calls 13 | to `Info` with a string format go to `Infof` etc. In many cases, `go vet` will 14 | guide you. 15 | * `Id` in `Record` is now called `ID` 16 | 17 | ## 1.0.0 (2013-02-21) 18 | 19 | Initial release 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/helper_not_unsafe.go: -------------------------------------------------------------------------------- 1 | //+build !unsafe 2 | 3 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 4 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 5 | 6 | package codec 7 | 8 | // stringView returns a view of the []byte as a string. 9 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 10 | // In regular safe mode, it is an allocation and copy. 11 | func stringView(v []byte) string { 12 | return string(v) 13 | } 14 | 15 | // bytesView returns a view of the string as a []byte. 16 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 17 | // In regular safe mode, it is an allocation and copy. 18 | func bytesView(v string) []byte { 19 | return []byte(v) 20 | } 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/syslog_fallback.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013, Örjan Persson. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //+build windows plan9 6 | 7 | package logging 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | type Priority int 14 | 15 | type SyslogBackend struct { 16 | } 17 | 18 | func NewSyslogBackend(prefix string) (b *SyslogBackend, err error) { 19 | return nil, fmt.Errorf("Platform does not support syslog") 20 | } 21 | 22 | func NewSyslogBackendPriority(prefix string, priority Priority) (b *SyslogBackend, err error) { 23 | return nil, fmt.Errorf("Platform does not support syslog") 24 | } 25 | 26 | func (b *SyslogBackend) Log(level Level, calldepth int, rec *Record) error { 27 | return fmt.Errorf("Platform does not support syslog") 28 | } 29 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/upfluence/etcdenv", 3 | "GoVersion": "go1.4", 4 | "GodepVersion": "v80", 5 | "Packages": [ 6 | "./..." 7 | ], 8 | "Deps": [ 9 | { 10 | "ImportPath": "github.com/cenkalti/backoff", 11 | "Rev": "9831e1e25c874e0a0601b6dc43641071414eec7a" 12 | }, 13 | { 14 | "ImportPath": "github.com/coreos/go-etcd/etcd", 15 | "Comment": "v2.0.0", 16 | "Rev": "f02171fbd43c7b9b53ce8679b03235a1ef3c7b12" 17 | }, 18 | { 19 | "ImportPath": "github.com/op/go-logging", 20 | "Comment": "v1-7-g970db52", 21 | "Rev": "970db520ece77730c7e4724c61121037378659d9" 22 | }, 23 | { 24 | "ImportPath": "github.com/ugorji/go/codec", 25 | "Rev": "821cda7e48749cacf7cad2c6ed01e96457ca7e9d" 26 | }, 27 | { 28 | "ImportPath": "github.com/upfluence/goutils/log", 29 | "Rev": "e9897046d38aee2ab46ddeed46dbf4db76e9a49c" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_delete.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import "fmt" 4 | 5 | func (c *Client) CompareAndDelete(key string, prevValue string, prevIndex uint64) (*Response, error) { 6 | raw, err := c.RawCompareAndDelete(key, prevValue, prevIndex) 7 | if err != nil { 8 | return nil, err 9 | } 10 | 11 | return raw.Unmarshal() 12 | } 13 | 14 | func (c *Client) RawCompareAndDelete(key string, prevValue string, prevIndex uint64) (*RawResponse, error) { 15 | if prevValue == "" && prevIndex == 0 { 16 | return nil, fmt.Errorf("You must give either prevValue or prevIndex.") 17 | } 18 | 19 | options := Options{} 20 | if prevValue != "" { 21 | options["prevValue"] = prevValue 22 | } 23 | if prevIndex != 0 { 24 | options["prevIndex"] = prevIndex 25 | } 26 | 27 | raw, err := c.delete(key, options) 28 | 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | return raw, err 34 | } 35 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/ticker_test.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "testing" 7 | ) 8 | 9 | func TestTicker(t *testing.T) { 10 | const successOn = 3 11 | var i = 0 12 | 13 | // This function is successfull on "successOn" calls. 14 | f := func() error { 15 | i++ 16 | log.Printf("function is called %d. time\n", i) 17 | 18 | if i == successOn { 19 | log.Println("OK") 20 | return nil 21 | } 22 | 23 | log.Println("error") 24 | return errors.New("error") 25 | } 26 | 27 | b := NewExponentialBackOff() 28 | ticker := NewTicker(b) 29 | 30 | var err error 31 | for _ = range ticker.C { 32 | if err = f(); err != nil { 33 | t.Log(err) 34 | continue 35 | } 36 | 37 | break 38 | } 39 | if err != nil { 40 | t.Errorf("unexpected error: %s", err.Error()) 41 | } 42 | if i != successOn { 43 | t.Errorf("invalid number of retries: %d", i) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/compare_and_swap.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import "fmt" 4 | 5 | func (c *Client) CompareAndSwap(key string, value string, ttl uint64, 6 | prevValue string, prevIndex uint64) (*Response, error) { 7 | raw, err := c.RawCompareAndSwap(key, value, ttl, prevValue, prevIndex) 8 | if err != nil { 9 | return nil, err 10 | } 11 | 12 | return raw.Unmarshal() 13 | } 14 | 15 | func (c *Client) RawCompareAndSwap(key string, value string, ttl uint64, 16 | prevValue string, prevIndex uint64) (*RawResponse, error) { 17 | if prevValue == "" && prevIndex == 0 { 18 | return nil, fmt.Errorf("You must give either prevValue or prevIndex.") 19 | } 20 | 21 | options := Options{} 22 | if prevValue != "" { 23 | options["prevValue"] = prevValue 24 | } 25 | if prevIndex != 0 { 26 | options["prevIndex"] = prevIndex 27 | } 28 | 29 | raw, err := c.put(key, value, ttl, options) 30 | 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | return raw, err 36 | } 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/get.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | // Get gets the file or directory associated with the given key. 4 | // If the key points to a directory, files and directories under 5 | // it will be returned in sorted or unsorted order, depending on 6 | // the sort flag. 7 | // If recursive is set to false, contents under child directories 8 | // will not be returned. 9 | // If recursive is set to true, all the contents will be returned. 10 | func (c *Client) Get(key string, sort, recursive bool) (*Response, error) { 11 | raw, err := c.RawGet(key, sort, recursive) 12 | 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return raw.Unmarshal() 18 | } 19 | 20 | func (c *Client) RawGet(key string, sort, recursive bool) (*RawResponse, error) { 21 | var q bool 22 | if c.config.Consistency == STRONG_CONSISTENCY { 23 | q = true 24 | } 25 | ops := Options{ 26 | "recursive": recursive, 27 | "sorted": sort, 28 | "quorum": q, 29 | } 30 | 31 | return c.get(key, ops) 32 | } 33 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/cluster.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | ) 7 | 8 | type Cluster struct { 9 | Leader string `json:"leader"` 10 | Machines []string `json:"machines"` 11 | picked int 12 | } 13 | 14 | func NewCluster(machines []string) *Cluster { 15 | // if an empty slice was sent in then just assume HTTP 4001 on localhost 16 | if len(machines) == 0 { 17 | machines = []string{"http://127.0.0.1:4001"} 18 | } 19 | 20 | // default leader and machines 21 | return &Cluster{ 22 | Leader: "", 23 | Machines: machines, 24 | picked: rand.Intn(len(machines)), 25 | } 26 | } 27 | 28 | func (cl *Cluster) failure() { cl.picked = rand.Intn(len(cl.Machines)) } 29 | func (cl *Cluster) pick() string { return cl.Machines[cl.picked] } 30 | 31 | func (cl *Cluster) updateFromStr(machines string) { 32 | cl.Machines = strings.Split(machines, ",") 33 | for i := range cl.Machines { 34 | cl.Machines[i] = strings.TrimSpace(cl.Machines[i]) 35 | } 36 | cl.picked = rand.Intn(len(cl.Machines)) 37 | } 38 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/README.md: -------------------------------------------------------------------------------- 1 | # codecgen tool 2 | 3 | Generate is given a list of *.go files to parse, and an output file (fout), 4 | codecgen will create an output file __file.go__ which 5 | contains `codec.Selfer` implementations for the named types found 6 | in the files parsed. 7 | 8 | Using codecgen is very straightforward. 9 | 10 | **Download and install the tool** 11 | 12 | `go get -u github.com/ugorji/go/codec/codecgen` 13 | 14 | **Run the tool on your files** 15 | 16 | The command line format is: 17 | 18 | `codecgen [options] (-o outfile) (infile ...)` 19 | 20 | ```sh 21 | % codecgen -? 22 | Usage of codecgen: 23 | -c="github.com/ugorji/go/codec": codec path 24 | -o="": out file 25 | -r=".*": regex for type name to match 26 | -rt="": tags for go run 27 | -t="": build tag to put in file 28 | -u=false: Use unsafe, e.g. to avoid unnecessary allocation on []byte->string 29 | -x=false: keep temp file 30 | 31 | % codecgen -o values_codecgen.go values.go values2.go moretypedefs.go 32 | ``` 33 | 34 | Please see the [blog article](http://ugorji.net/blog/go-codecgen) 35 | for more information on how to use the tool. 36 | 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/delete.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | // Delete deletes the given key. 4 | // 5 | // When recursive set to false, if the key points to a 6 | // directory the method will fail. 7 | // 8 | // When recursive set to true, if the key points to a file, 9 | // the file will be deleted; if the key points to a directory, 10 | // then everything under the directory (including all child directories) 11 | // will be deleted. 12 | func (c *Client) Delete(key string, recursive bool) (*Response, error) { 13 | raw, err := c.RawDelete(key, recursive, false) 14 | 15 | if err != nil { 16 | return nil, err 17 | } 18 | 19 | return raw.Unmarshal() 20 | } 21 | 22 | // DeleteDir deletes an empty directory or a key value pair 23 | func (c *Client) DeleteDir(key string) (*Response, error) { 24 | raw, err := c.RawDelete(key, false, true) 25 | 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | return raw.Unmarshal() 31 | } 32 | 33 | func (c *Client) RawDelete(key string, recursive bool, dir bool) (*RawResponse, error) { 34 | ops := Options{ 35 | "recursive": recursive, 36 | "dir": dir, 37 | } 38 | 39 | return c.delete(key, ops) 40 | } 41 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Cenk Altı 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/error.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | const ( 9 | ErrCodeEtcdNotReachable = 501 10 | ErrCodeUnhandledHTTPStatus = 502 11 | ) 12 | 13 | var ( 14 | errorMap = map[int]string{ 15 | ErrCodeEtcdNotReachable: "All the given peers are not reachable", 16 | } 17 | ) 18 | 19 | type EtcdError struct { 20 | ErrorCode int `json:"errorCode"` 21 | Message string `json:"message"` 22 | Cause string `json:"cause,omitempty"` 23 | Index uint64 `json:"index"` 24 | } 25 | 26 | func (e EtcdError) Error() string { 27 | return fmt.Sprintf("%v: %v (%v) [%v]", e.ErrorCode, e.Message, e.Cause, e.Index) 28 | } 29 | 30 | func newError(errorCode int, cause string, index uint64) *EtcdError { 31 | return &EtcdError{ 32 | ErrorCode: errorCode, 33 | Message: errorMap[errorCode], 34 | Cause: cause, 35 | Index: index, 36 | } 37 | } 38 | 39 | func handleError(b []byte) error { 40 | etcdErr := new(EtcdError) 41 | 42 | err := json.Unmarshal(b, etcdErr) 43 | if err != nil { 44 | logger.Warningf("cannot unmarshal etcd error: %v", err) 45 | return err 46 | } 47 | 48 | return etcdErr 49 | } 50 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2015 Ugorji Nwoke. 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/helper_unsafe.go: -------------------------------------------------------------------------------- 1 | //+build unsafe 2 | 3 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 4 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 5 | 6 | package codec 7 | 8 | import ( 9 | "unsafe" 10 | ) 11 | 12 | // This file has unsafe variants of some helper methods. 13 | 14 | type unsafeString struct { 15 | Data uintptr 16 | Len int 17 | } 18 | 19 | type unsafeBytes struct { 20 | Data uintptr 21 | Len int 22 | Cap int 23 | } 24 | 25 | // stringView returns a view of the []byte as a string. 26 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 27 | // In regular safe mode, it is an allocation and copy. 28 | func stringView(v []byte) string { 29 | x := unsafeString{uintptr(unsafe.Pointer(&v[0])), len(v)} 30 | return *(*string)(unsafe.Pointer(&x)) 31 | } 32 | 33 | // bytesView returns a view of the string as a []byte. 34 | // In unsafe mode, it doesn't incur allocation and copying caused by conversion. 35 | // In regular safe mode, it is an allocation and copy. 36 | func bytesView(v string) []byte { 37 | x := unsafeBytes{uintptr(unsafe.Pointer(&v)), len(v), len(v)} 38 | return *(*[]byte)(unsafe.Pointer(&x)) 39 | } 40 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/debug.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "strings" 8 | ) 9 | 10 | var logger *etcdLogger 11 | 12 | func SetLogger(l *log.Logger) { 13 | logger = &etcdLogger{l} 14 | } 15 | 16 | func GetLogger() *log.Logger { 17 | return logger.log 18 | } 19 | 20 | type etcdLogger struct { 21 | log *log.Logger 22 | } 23 | 24 | func (p *etcdLogger) Debug(args ...interface{}) { 25 | msg := "DEBUG: " + fmt.Sprint(args...) 26 | p.log.Println(msg) 27 | } 28 | 29 | func (p *etcdLogger) Debugf(f string, args ...interface{}) { 30 | msg := "DEBUG: " + fmt.Sprintf(f, args...) 31 | // Append newline if necessary 32 | if !strings.HasSuffix(msg, "\n") { 33 | msg = msg + "\n" 34 | } 35 | p.log.Print(msg) 36 | } 37 | 38 | func (p *etcdLogger) Warning(args ...interface{}) { 39 | msg := "WARNING: " + fmt.Sprint(args...) 40 | p.log.Println(msg) 41 | } 42 | 43 | func (p *etcdLogger) Warningf(f string, args ...interface{}) { 44 | msg := "WARNING: " + fmt.Sprintf(f, args...) 45 | // Append newline if necessary 46 | if !strings.HasSuffix(msg, "\n") { 47 | msg = msg + "\n" 48 | } 49 | p.log.Print(msg) 50 | } 51 | 52 | func init() { 53 | // Default logger uses the go default log. 54 | SetLogger(log.New(ioutil.Discard, "go-etcd", log.LstdFlags)) 55 | } 56 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/backend.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013, Örjan Persson. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package logging 6 | 7 | // defaultBackend is the backend used for all logging calls. 8 | var defaultBackend LeveledBackend 9 | 10 | // Backend is the interface which a log backend need to implement to be able to 11 | // be used as a logging backend. 12 | type Backend interface { 13 | Log(Level, int, *Record) error 14 | } 15 | 16 | // SetBackend replaces the backend currently set with the given new logging 17 | // backend. 18 | func SetBackend(backends ...Backend) LeveledBackend { 19 | var backend Backend 20 | if len(backends) == 1 { 21 | backend = backends[0] 22 | } else { 23 | backend = MultiLogger(backends...) 24 | } 25 | 26 | defaultBackend = AddModuleLevel(backend) 27 | return defaultBackend 28 | } 29 | 30 | // SetLevel sets the logging level for the specified module. The module 31 | // corresponds to the string specified in GetLogger. 32 | func SetLevel(level Level, module string) { 33 | defaultBackend.SetLevel(level, module) 34 | } 35 | 36 | // GetLevel returns the logging level for the specified module. 37 | func GetLevel(module string) Level { 38 | return defaultBackend.GetLevel(module) 39 | } 40 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/retry.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import "time" 4 | 5 | // Retry the function f until it does not return error or BackOff stops. 6 | // f is guaranteed to be run at least once. 7 | // It is the caller's responsibility to reset b after Retry returns. 8 | // 9 | // Retry sleeps the goroutine for the duration returned by BackOff after a 10 | // failed operation returns. 11 | // 12 | // Usage: 13 | // operation := func() error { 14 | // // An operation that may fail 15 | // } 16 | // 17 | // err := backoff.Retry(operation, backoff.NewExponentialBackOff()) 18 | // if err != nil { 19 | // // Operation has failed. 20 | // } 21 | // 22 | // // Operation is successfull. 23 | // 24 | func Retry(f func() error, b BackOff) error { return RetryNotify(f, b, nil) } 25 | 26 | // RetryNotify calls notify function with the error and wait duration for each failed attempt before sleep. 27 | func RetryNotify(f func() error, b BackOff, notify func(err error, wait time.Duration)) error { 28 | var err error 29 | var next time.Duration 30 | 31 | b.Reset() 32 | for { 33 | if err = f(); err == nil { 34 | return nil 35 | } 36 | 37 | if next = b.NextBackOff(); next == Stop { 38 | return err 39 | } 40 | 41 | if notify != nil { 42 | notify(err, next) 43 | } 44 | 45 | time.Sleep(next) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Örjan Persson. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/examples/example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/op/go-logging" 7 | ) 8 | 9 | var log = logging.MustGetLogger("example") 10 | 11 | // Example format string. Everything except the message has a custom color 12 | // which is dependent on the log level. Many fields have a custom output 13 | // formatting too, eg. the time returns the hour down to the milli second. 14 | var format = logging.MustStringFormatter( 15 | `%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`, 16 | ) 17 | 18 | // Password is just an example type implementing the Redactor interface. Any 19 | // time this is logged, the Redacted() function will be called. 20 | type Password string 21 | 22 | func (p Password) Redacted() interface{} { 23 | return logging.Redact(string(p)) 24 | } 25 | 26 | func main() { 27 | // For demo purposes, create two backend for os.Stderr. 28 | backend1 := logging.NewLogBackend(os.Stderr, "", 0) 29 | backend2 := logging.NewLogBackend(os.Stderr, "", 0) 30 | 31 | // For messages written to backend2 we want to add some additional 32 | // information to the output, including the used log level and the name of 33 | // the function. 34 | backend2Formatter := logging.NewBackendFormatter(backend2, format) 35 | 36 | // Only errors and more severe messages should be sent to backend1 37 | backend1Leveled := logging.AddModuleLevel(backend1) 38 | backend1Leveled.SetLevel(logging.ERROR, "") 39 | 40 | // Set the backends to be used. 41 | logging.SetBackend(backend1Leveled, backend2Formatter) 42 | 43 | log.Debugf("debug %s", Password("secret")) 44 | log.Info("info") 45 | log.Notice("notice") 46 | log.Warning("warning") 47 | log.Error("err") 48 | log.Critical("crit") 49 | } 50 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/gen-dec-map.go.tmpl: -------------------------------------------------------------------------------- 1 | {{var "v"}} := *{{ .Varname }} 2 | {{var "l"}} := r.ReadMapStart() 3 | if {{var "v"}} == nil { 4 | if {{var "l"}} > 0 { 5 | {{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "l"}}) 6 | } else { 7 | {{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}) // supports indefinite-length, etc 8 | } 9 | *{{ .Varname }} = {{var "v"}} 10 | } 11 | if {{var "l"}} > 0 { 12 | for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ { 13 | var {{var "mk"}} {{ .KTyp }} 14 | {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} 15 | {{ if eq .KTyp "interface{}" }}// special case if a byte array. 16 | if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { 17 | {{var "mk"}} = string({{var "bv"}}) 18 | } 19 | {{ end }} 20 | {{var "mv"}} := {{var "v"}}[{{var "mk"}}] 21 | {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} 22 | if {{var "v"}} != nil { 23 | {{var "v"}}[{{var "mk"}}] = {{var "mv"}} 24 | } 25 | } 26 | } else if {{var "l"}} < 0 { 27 | for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ { 28 | if {{var "j"}} > 0 { 29 | r.ReadMapEntrySeparator() 30 | } 31 | var {{var "mk"}} {{ .KTyp }} 32 | {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} 33 | {{ if eq .KTyp "interface{}" }}// special case if a byte array. 34 | if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { 35 | {{var "mk"}} = string({{var "bv"}}) 36 | } 37 | {{ end }} 38 | r.ReadMapKVSeparator() 39 | {{var "mv"}} := {{var "v"}}[{{var "mk"}}] 40 | {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} 41 | if {{var "v"}} != nil { 42 | {{var "v"}}[{{var "mk"}}] = {{var "mv"}} 43 | } 44 | } 45 | r.ReadMapEnd() 46 | } // else len==0: TODO: Should we clear map entries? 47 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/syslog.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013, Örjan Persson. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //+build !windows,!plan9 6 | 7 | package logging 8 | 9 | import "log/syslog" 10 | 11 | // SyslogBackend is a simple logger to syslog backend. It automatically maps 12 | // the internal log levels to appropriate syslog log levels. 13 | type SyslogBackend struct { 14 | Writer *syslog.Writer 15 | } 16 | 17 | // NewSyslogBackend connects to the syslog daemon using UNIX sockets with the 18 | // given prefix. If prefix is not given, the prefix will be derived from the 19 | // launched command. 20 | func NewSyslogBackend(prefix string) (b *SyslogBackend, err error) { 21 | var w *syslog.Writer 22 | w, err = syslog.New(syslog.LOG_CRIT, prefix) 23 | return &SyslogBackend{w}, err 24 | } 25 | 26 | // NewSyslogBackendPriority is the same as NewSyslogBackend, but with custom 27 | // syslog priority, like syslog.LOG_LOCAL3|syslog.LOG_DEBUG etc. 28 | func NewSyslogBackendPriority(prefix string, priority syslog.Priority) (b *SyslogBackend, err error) { 29 | var w *syslog.Writer 30 | w, err = syslog.New(priority, prefix) 31 | return &SyslogBackend{w}, err 32 | } 33 | 34 | // Log implements the Backend interface. 35 | func (b *SyslogBackend) Log(level Level, calldepth int, rec *Record) error { 36 | line := rec.Formatted(calldepth + 1) 37 | switch level { 38 | case CRITICAL: 39 | return b.Writer.Crit(line) 40 | case ERROR: 41 | return b.Writer.Err(line) 42 | case WARNING: 43 | return b.Writer.Warning(line) 44 | case NOTICE: 45 | return b.Writer.Notice(line) 46 | case INFO: 47 | return b.Writer.Info(line) 48 | case DEBUG: 49 | return b.Writer.Debug(line) 50 | default: 51 | } 52 | panic("unhandled log level") 53 | } 54 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/backoff.go: -------------------------------------------------------------------------------- 1 | // Package backoff implements backoff algorithms for retrying operations. 2 | // 3 | // Also has a Retry() helper for retrying operations that may fail. 4 | package backoff 5 | 6 | import "time" 7 | 8 | // Back-off policy when retrying an operation. 9 | type BackOff interface { 10 | // Gets the duration to wait before retrying the operation or 11 | // backoff.Stop to indicate that no retries should be made. 12 | // 13 | // Example usage: 14 | // 15 | // duration := backoff.NextBackOff(); 16 | // if (duration == backoff.Stop) { 17 | // // do not retry operation 18 | // } else { 19 | // // sleep for duration and retry operation 20 | // } 21 | // 22 | NextBackOff() time.Duration 23 | 24 | // Reset to initial state. 25 | Reset() 26 | } 27 | 28 | // Indicates that no more retries should be made for use in NextBackOff(). 29 | const Stop time.Duration = -1 30 | 31 | // ZeroBackOff is a fixed back-off policy whose back-off time is always zero, 32 | // meaning that the operation is retried immediately without waiting. 33 | type ZeroBackOff struct{} 34 | 35 | func (b *ZeroBackOff) Reset() {} 36 | 37 | func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } 38 | 39 | // StopBackOff is a fixed back-off policy that always returns backoff.Stop for 40 | // NextBackOff(), meaning that the operation should not be retried. 41 | type StopBackOff struct{} 42 | 43 | func (b *StopBackOff) Reset() {} 44 | 45 | func (b *StopBackOff) NextBackOff() time.Duration { return Stop } 46 | 47 | type ConstantBackOff struct { 48 | Interval time.Duration 49 | } 50 | 51 | func (b *ConstantBackOff) Reset() {} 52 | func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } 53 | 54 | func NewConstantBackOff(d time.Duration) *ConstantBackOff { 55 | return &ConstantBackOff{Interval: d} 56 | } 57 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/README.md: -------------------------------------------------------------------------------- 1 | # backoff 2 | 3 | [![GoDoc](https://godoc.org/github.com/cenkalti/backoff?status.png)](https://godoc.org/github.com/cenkalti/backoff) 4 | [![Build Status](https://travis-ci.org/cenkalti/backoff.png)](https://travis-ci.org/cenkalti/backoff) 5 | 6 | This is a Go port of the exponential backoff algorithm from 7 | [google-http-java-client](https://code.google.com/p/google-http-java-client/wiki/ExponentialBackoff). 8 | 9 | [Exponential backoff](http://en.wikipedia.org/wiki/Exponential_backoff) 10 | is an algorithm that uses feedback to multiplicatively decrease the rate of some process, 11 | in order to gradually find an acceptable rate. 12 | The retries exponentially increase and stop increasing when a certain threshold is met. 13 | 14 | 15 | 16 | 17 | ## Install 18 | 19 | ```bash 20 | go get github.com/cenkalti/backoff 21 | ``` 22 | 23 | ## Example 24 | 25 | Simple retry helper that uses exponential back-off algorithm: 26 | 27 | ```go 28 | operation := func() error { 29 | // An operation that might fail 30 | } 31 | 32 | err := backoff.Retry(operation, backoff.NewExponentialBackOff()) 33 | if err != nil { 34 | // handle error 35 | } 36 | 37 | // operation is successfull 38 | ``` 39 | 40 | Ticker example: 41 | 42 | ```go 43 | operation := func() error { 44 | // An operation that may fail 45 | } 46 | 47 | b := backoff.NewExponentialBackOff() 48 | ticker := backoff.NewTicker(b) 49 | 50 | var err error 51 | 52 | // Ticks will continue to arrive when the previous operation is still running, 53 | // so operations that take a while to fail could run in quick succession. 54 | for t = range ticker.C { 55 | if err = operation(); err != nil { 56 | log.Println(err, "will retry...") 57 | continue 58 | } 59 | 60 | ticker.Stop() 61 | break 62 | } 63 | 64 | if err != nil { 65 | // Operation has failed. 66 | } 67 | 68 | // Operation is successfull. 69 | ``` 70 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/options.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "fmt" 5 | "net/url" 6 | "reflect" 7 | ) 8 | 9 | type Options map[string]interface{} 10 | 11 | // An internally-used data structure that represents a mapping 12 | // between valid options and their kinds 13 | type validOptions map[string]reflect.Kind 14 | 15 | // Valid options for GET, PUT, POST, DELETE 16 | // Using CAPITALIZED_UNDERSCORE to emphasize that these 17 | // values are meant to be used as constants. 18 | var ( 19 | VALID_GET_OPTIONS = validOptions{ 20 | "recursive": reflect.Bool, 21 | "quorum": reflect.Bool, 22 | "sorted": reflect.Bool, 23 | "wait": reflect.Bool, 24 | "waitIndex": reflect.Uint64, 25 | } 26 | 27 | VALID_PUT_OPTIONS = validOptions{ 28 | "prevValue": reflect.String, 29 | "prevIndex": reflect.Uint64, 30 | "prevExist": reflect.Bool, 31 | "dir": reflect.Bool, 32 | } 33 | 34 | VALID_POST_OPTIONS = validOptions{} 35 | 36 | VALID_DELETE_OPTIONS = validOptions{ 37 | "recursive": reflect.Bool, 38 | "dir": reflect.Bool, 39 | "prevValue": reflect.String, 40 | "prevIndex": reflect.Uint64, 41 | } 42 | ) 43 | 44 | // Convert options to a string of HTML parameters 45 | func (ops Options) toParameters(validOps validOptions) (string, error) { 46 | p := "?" 47 | values := url.Values{} 48 | 49 | if ops == nil { 50 | return "", nil 51 | } 52 | 53 | for k, v := range ops { 54 | // Check if the given option is valid (that it exists) 55 | kind := validOps[k] 56 | if kind == reflect.Invalid { 57 | return "", fmt.Errorf("Invalid option: %v", k) 58 | } 59 | 60 | // Check if the given option is of the valid type 61 | t := reflect.TypeOf(v) 62 | if kind != t.Kind() { 63 | return "", fmt.Errorf("Option %s should be of %v kind, not of %v kind.", 64 | k, kind, t.Kind()) 65 | } 66 | 67 | values.Set(k, fmt.Sprintf("%v", v)) 68 | } 69 | 70 | p += values.Encode() 71 | return p, nil 72 | } 73 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/multi.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013, Örjan Persson. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package logging 6 | 7 | // TODO remove Level stuff from the multi logger. Do one thing. 8 | 9 | // multiLogger is a log multiplexer which can be used to utilize multiple log 10 | // backends at once. 11 | type multiLogger struct { 12 | backends []LeveledBackend 13 | } 14 | 15 | // MultiLogger creates a logger which contain multiple loggers. 16 | func MultiLogger(backends ...Backend) LeveledBackend { 17 | var leveledBackends []LeveledBackend 18 | for _, backend := range backends { 19 | leveledBackends = append(leveledBackends, AddModuleLevel(backend)) 20 | } 21 | return &multiLogger{leveledBackends} 22 | } 23 | 24 | // Log passes the log record to all backends. 25 | func (b *multiLogger) Log(level Level, calldepth int, rec *Record) (err error) { 26 | for _, backend := range b.backends { 27 | if backend.IsEnabledFor(level, rec.Module) { 28 | // Shallow copy of the record for the formatted cache on Record and get the 29 | // record formatter from the backend. 30 | r2 := *rec 31 | if e := backend.Log(level, calldepth+1, &r2); e != nil { 32 | err = e 33 | } 34 | } 35 | } 36 | return 37 | } 38 | 39 | // GetLevel returns the highest level enabled by all backends. 40 | func (b *multiLogger) GetLevel(module string) Level { 41 | var level Level 42 | for _, backend := range b.backends { 43 | if backendLevel := backend.GetLevel(module); backendLevel > level { 44 | level = backendLevel 45 | } 46 | } 47 | return level 48 | } 49 | 50 | // SetLevel propagates the same level to all backends. 51 | func (b *multiLogger) SetLevel(level Level, module string) { 52 | for _, backend := range b.backends { 53 | backend.SetLevel(level, module) 54 | } 55 | } 56 | 57 | // IsEnabledFor returns true if any of the backends are enabled for it. 58 | func (b *multiLogger) IsEnabledFor(level Level, module string) bool { 59 | for _, backend := range b.backends { 60 | if backend.IsEnabledFor(level, module) { 61 | return true 62 | } 63 | } 64 | return false 65 | } 66 | -------------------------------------------------------------------------------- /etcdenv/runner.go: -------------------------------------------------------------------------------- 1 | package etcdenv 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | "syscall" 8 | "time" 9 | ) 10 | 11 | type Runner struct { 12 | Command []string 13 | DefaultEnv []string 14 | IsRestarting bool 15 | 16 | cmd *exec.Cmd 17 | } 18 | 19 | func NewRunner(command []string) *Runner { 20 | return &Runner{ 21 | Command: command, 22 | DefaultEnv: os.Environ(), 23 | } 24 | } 25 | 26 | func (r *Runner) buildEnvs(envVariables map[string]string) []string { 27 | envs := r.DefaultEnv 28 | 29 | for k, v := range envVariables { 30 | envs = append(envs, fmt.Sprintf("%s=%s", k, v)) 31 | } 32 | 33 | return envs 34 | } 35 | 36 | func (r *Runner) Start(envVariables map[string]string) error { 37 | if r.cmd != nil && r.cmd.Process != nil { 38 | return newError(ErrAlreadyStarted) 39 | } 40 | 41 | r.cmd = exec.Command(r.Command[0], r.Command[1:]...) 42 | 43 | r.cmd.Env = r.buildEnvs(envVariables) 44 | r.cmd.Stdout = os.Stdout 45 | r.cmd.Stderr = os.Stderr 46 | r.cmd.Stdin = os.Stdin 47 | 48 | r.cmd.Start() 49 | 50 | return nil 51 | } 52 | 53 | func (r *Runner) Stop() error { 54 | if r.cmd == nil || r.cmd.Process == nil { 55 | return newError(ErrNotStarted) 56 | } 57 | 58 | r.cmd.Process.Kill() 59 | r.cmd.Process.Wait() 60 | 61 | r.cmd = nil 62 | 63 | return nil 64 | } 65 | 66 | func (r *Runner) Restart(envVariables map[string]string) error { 67 | r.IsRestarting = true 68 | defer func() { r.IsRestarting = false }() 69 | 70 | r.Stop() 71 | 72 | return r.Start(envVariables) 73 | } 74 | 75 | func (r *Runner) Wait() error { 76 | if r.cmd == nil || r.cmd.Process == nil { 77 | return newError(ErrNotStarted) 78 | } 79 | 80 | err := r.cmd.Wait() 81 | 82 | return err 83 | } 84 | 85 | func (r *Runner) WatchProcess(exitStatus chan int) { 86 | for { 87 | time.Sleep(200 * time.Millisecond) 88 | err := r.Wait() 89 | 90 | if !r.IsRestarting { 91 | if exiterr, ok := err.(*exec.ExitError); ok { 92 | if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { 93 | exitStatus <- status.ExitStatus() 94 | } else { 95 | exitStatus <- 0 96 | } 97 | } else { 98 | exitStatus <- 0 99 | } 100 | break 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/upfluence/goutils/log/logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "github.com/op/go-logging" 5 | "os" 6 | ) 7 | 8 | const defaultLevel = logging.NOTICE 9 | 10 | var ( 11 | logger = &logging.Logger{Module: "upfluence", ExtraCalldepth: 1} 12 | format = logging.MustStringFormatter( 13 | `[%{level:.1s} %{time:060102 15:04:05} %{shortfile}] %{message}`, 14 | ) 15 | backend = logging.AddModuleLevel( 16 | logging.NewBackendFormatter( 17 | logging.NewLogBackend(os.Stdout, "", 0), 18 | format, 19 | ), 20 | ) 21 | ) 22 | 23 | func init() { 24 | var ( 25 | level logging.Level 26 | err error 27 | ) 28 | 29 | if level, err = logging.LogLevel(os.Getenv("LOGGER_LEVEL")); err != nil { 30 | level = defaultLevel 31 | } 32 | 33 | backend.SetLevel(level, "") 34 | logging.SetBackend(backend) 35 | } 36 | 37 | func Fatal(args ...interface{}) { 38 | logger.Fatal(args...) 39 | } 40 | 41 | func Fatalf(format string, args ...interface{}) { 42 | logger.Fatalf(format, args...) 43 | } 44 | 45 | func Panic(args ...interface{}) { 46 | logger.Panic(args...) 47 | } 48 | 49 | func Panicf(format string, args ...interface{}) { 50 | logger.Panicf(format, args...) 51 | } 52 | 53 | func Critical(args ...interface{}) { 54 | logger.Critical(args...) 55 | } 56 | 57 | func Criticalf(format string, args ...interface{}) { 58 | logger.Criticalf(format, args...) 59 | } 60 | 61 | func Error(args ...interface{}) { 62 | logger.Error(args...) 63 | } 64 | 65 | func Errorf(format string, args ...interface{}) { 66 | logger.Errorf(format, args...) 67 | } 68 | 69 | func Warning(args ...interface{}) { 70 | logger.Warning(args...) 71 | } 72 | 73 | func Warningf(format string, args ...interface{}) { 74 | logger.Warningf(format, args...) 75 | } 76 | 77 | func Notice(args ...interface{}) { 78 | logger.Notice(args...) 79 | } 80 | 81 | func Noticef(format string, args ...interface{}) { 82 | logger.Noticef(format, args...) 83 | } 84 | 85 | func Info(args ...interface{}) { 86 | logger.Info(args...) 87 | } 88 | 89 | func Infof(format string, args ...interface{}) { 90 | logger.Infof(format, args...) 91 | } 92 | 93 | func Debug(args ...interface{}) { 94 | logger.Debug(args...) 95 | } 96 | 97 | func Debugf(format string, args ...interface{}) { 98 | logger.Debugf(format, args...) 99 | } 100 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/response.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | const ( 11 | rawResponse = iota 12 | normalResponse 13 | ) 14 | 15 | type responseType int 16 | 17 | type RawResponse struct { 18 | StatusCode int 19 | Body []byte 20 | Header http.Header 21 | } 22 | 23 | var ( 24 | validHttpStatusCode = map[int]bool{ 25 | http.StatusCreated: true, 26 | http.StatusOK: true, 27 | http.StatusBadRequest: true, 28 | http.StatusNotFound: true, 29 | http.StatusPreconditionFailed: true, 30 | http.StatusForbidden: true, 31 | } 32 | ) 33 | 34 | // Unmarshal parses RawResponse and stores the result in Response 35 | func (rr *RawResponse) Unmarshal() (*Response, error) { 36 | if rr.StatusCode != http.StatusOK && rr.StatusCode != http.StatusCreated { 37 | return nil, handleError(rr.Body) 38 | } 39 | 40 | resp := new(Response) 41 | 42 | err := json.Unmarshal(rr.Body, resp) 43 | 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | // attach index and term to response 49 | resp.EtcdIndex, _ = strconv.ParseUint(rr.Header.Get("X-Etcd-Index"), 10, 64) 50 | resp.RaftIndex, _ = strconv.ParseUint(rr.Header.Get("X-Raft-Index"), 10, 64) 51 | resp.RaftTerm, _ = strconv.ParseUint(rr.Header.Get("X-Raft-Term"), 10, 64) 52 | 53 | return resp, nil 54 | } 55 | 56 | type Response struct { 57 | Action string `json:"action"` 58 | Node *Node `json:"node"` 59 | PrevNode *Node `json:"prevNode,omitempty"` 60 | EtcdIndex uint64 `json:"etcdIndex"` 61 | RaftIndex uint64 `json:"raftIndex"` 62 | RaftTerm uint64 `json:"raftTerm"` 63 | } 64 | 65 | type Node struct { 66 | Key string `json:"key, omitempty"` 67 | Value string `json:"value,omitempty"` 68 | Dir bool `json:"dir,omitempty"` 69 | Expiration *time.Time `json:"expiration,omitempty"` 70 | TTL int64 `json:"ttl,omitempty"` 71 | Nodes Nodes `json:"nodes,omitempty"` 72 | ModifiedIndex uint64 `json:"modifiedIndex,omitempty"` 73 | CreatedIndex uint64 `json:"createdIndex,omitempty"` 74 | } 75 | 76 | type Nodes []*Node 77 | 78 | // interfaces for sorting 79 | func (ns Nodes) Len() int { 80 | return len(ns) 81 | } 82 | 83 | func (ns Nodes) Less(i, j int) bool { 84 | return ns[i].Key < ns[j].Key 85 | } 86 | 87 | func (ns Nodes) Swap(i, j int) { 88 | ns[i], ns[j] = ns[j], ns[i] 89 | } 90 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/ticker.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "runtime" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | // Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. 10 | // 11 | // Ticks will continue to arrive when the previous operation is still running, 12 | // so operations that take a while to fail could run in quick succession. 13 | // 14 | // Usage: 15 | // operation := func() error { 16 | // // An operation that may fail 17 | // } 18 | // 19 | // b := backoff.NewExponentialBackOff() 20 | // ticker := backoff.NewTicker(b) 21 | // 22 | // var err error 23 | // for _ = range ticker.C { 24 | // if err = operation(); err != nil { 25 | // log.Println(err, "will retry...") 26 | // continue 27 | // } 28 | // 29 | // ticker.Stop() 30 | // break 31 | // } 32 | // 33 | // if err != nil { 34 | // // Operation has failed. 35 | // } 36 | // 37 | // // Operation is successfull. 38 | // 39 | type Ticker struct { 40 | C <-chan time.Time 41 | c chan time.Time 42 | b BackOff 43 | stop chan struct{} 44 | stopOnce sync.Once 45 | } 46 | 47 | // NewTicker returns a new Ticker containing a channel that will send the time at times 48 | // specified by the BackOff argument. Ticker is guaranteed to tick at least once. 49 | // The channel is closed when Stop method is called or BackOff stops. 50 | func NewTicker(b BackOff) *Ticker { 51 | c := make(chan time.Time) 52 | t := &Ticker{ 53 | C: c, 54 | c: c, 55 | b: b, 56 | stop: make(chan struct{}), 57 | } 58 | go t.run() 59 | runtime.SetFinalizer(t, (*Ticker).Stop) 60 | return t 61 | } 62 | 63 | // Stop turns off a ticker. After Stop, no more ticks will be sent. 64 | func (t *Ticker) Stop() { 65 | t.stopOnce.Do(func() { close(t.stop) }) 66 | } 67 | 68 | func (t *Ticker) run() { 69 | c := t.c 70 | defer close(c) 71 | t.b.Reset() 72 | 73 | // Ticker is guaranteed to tick at least once. 74 | afterC := t.send(time.Now()) 75 | 76 | for { 77 | if afterC == nil { 78 | return 79 | } 80 | 81 | select { 82 | case tick := <-afterC: 83 | afterC = t.send(tick) 84 | case <-t.stop: 85 | t.c = nil // Prevent future ticks from being sent to the channel. 86 | return 87 | } 88 | } 89 | } 90 | 91 | func (t *Ticker) send(tick time.Time) <-chan time.Time { 92 | select { 93 | case t.c <- tick: 94 | case <-t.stop: 95 | return nil 96 | } 97 | 98 | next := t.b.NextBackOff() 99 | if next == Stop { 100 | t.Stop() 101 | return nil 102 | } 103 | 104 | return time.After(next) 105 | } 106 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/gen-dec-array.go.tmpl: -------------------------------------------------------------------------------- 1 | {{var "v"}} := *{{ .Varname }} 2 | {{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() 3 | 4 | var {{var "c"}} bool 5 | {{ if not isArray }}if {{var "v"}} == nil { 6 | if {{var "l"}} <= 0 { 7 | {{var "v"}} = make({{ .CTyp }}, 0) 8 | } else { 9 | {{var "v"}} = make({{ .CTyp }}, {{var "l"}}) 10 | } 11 | {{var "c"}} = true 12 | } 13 | {{ end }} 14 | if {{var "l"}} == 0 { {{ if isSlice }} 15 | if len({{var "v"}}) != 0 { 16 | {{var "v"}} = {{var "v"}}[:0] 17 | {{var "c"}} = true 18 | } {{ end }} 19 | } else if {{var "l"}} > 0 { 20 | {{ if isChan }} 21 | for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ { 22 | var {{var "t"}} {{ .Typ }} 23 | {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} 24 | {{var "v"}} <- {{var "t"}} 25 | {{ else }} 26 | {{var "n"}} := {{var "l"}} 27 | if {{var "l"}} > cap({{var "v"}}) { 28 | {{ if isArray }}r.ReadArrayCannotExpand(len({{var "v"}}), {{var "l"}}) 29 | {{var "n"}} = len({{var "v"}}) 30 | {{ else }}{{ if .Immutable }} 31 | {{var "v2"}} := {{var "v"}} 32 | {{var "v"}} = make([]{{ .Typ }}, {{var "l"}}, {{var "l"}}) 33 | if len({{var "v"}}) > 0 { 34 | copy({{var "v"}}, {{var "v2"}}[:cap({{var "v2"}})]) 35 | } 36 | {{ else }}{{var "v"}} = make([]{{ .Typ }}, {{var "l"}}, {{var "l"}}) 37 | {{ end }}{{var "c"}} = true 38 | {{ end }} 39 | } else if {{var "l"}} != len({{var "v"}}) { 40 | {{var "v"}} = {{var "v"}}[:{{var "l"}}] 41 | {{var "c"}} = true 42 | } 43 | {{var "j"}} := 0 44 | for ; {{var "j"}} < {{var "n"}} ; {{var "j"}}++ { 45 | {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} 46 | } {{ if isArray }} 47 | for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ { 48 | z.DecSwallow() 49 | }{{ end }} 50 | {{ end }}{{/* closing if not chan */}} 51 | } else { 52 | for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ { 53 | if {{var "j"}} >= len({{var "v"}}) { 54 | {{ if isArray }}r.ReadArrayCannotExpand(len({{var "v"}}), {{var "j"}}+1) 55 | {{ else if isSlice}}{{var "v"}} = append({{var "v"}}, {{zero}})// var {{var "z"}} {{ .Typ }} 56 | {{var "c"}} = true {{ end }} 57 | } 58 | if {{var "j"}} > 0 { 59 | {{var "h"}}.Sep({{var "j"}}) 60 | } 61 | {{ if isChan}} 62 | var {{var "t"}} {{ .Typ }} 63 | {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} 64 | {{var "v"}} <- {{var "t"}} 65 | {{ else }} 66 | if {{var "j"}} < len({{var "v"}}) { 67 | {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} 68 | } else { 69 | z.DecSwallow() 70 | } 71 | {{ end }} 72 | } 73 | {{var "h"}}.End() 74 | } 75 | if {{var "c"}} { 76 | *{{ .Varname }} = {{var "v"}} 77 | } 78 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/watch.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // Errors introduced by the Watch command. 8 | var ( 9 | ErrWatchStoppedByUser = errors.New("Watch stopped by the user via stop channel") 10 | ) 11 | 12 | // If recursive is set to true the watch returns the first change under the given 13 | // prefix since the given index. 14 | // 15 | // If recursive is set to false the watch returns the first change to the given key 16 | // since the given index. 17 | // 18 | // To watch for the latest change, set waitIndex = 0. 19 | // 20 | // If a receiver channel is given, it will be a long-term watch. Watch will block at the 21 | //channel. After someone receives the channel, it will go on to watch that 22 | // prefix. If a stop channel is given, the client can close long-term watch using 23 | // the stop channel. 24 | func (c *Client) Watch(prefix string, waitIndex uint64, recursive bool, 25 | receiver chan *Response, stop chan bool) (*Response, error) { 26 | logger.Debugf("watch %s [%s]", prefix, c.cluster.Leader) 27 | if receiver == nil { 28 | raw, err := c.watchOnce(prefix, waitIndex, recursive, stop) 29 | 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | return raw.Unmarshal() 35 | } 36 | defer close(receiver) 37 | 38 | for { 39 | raw, err := c.watchOnce(prefix, waitIndex, recursive, stop) 40 | 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | resp, err := raw.Unmarshal() 46 | 47 | if err != nil { 48 | return nil, err 49 | } 50 | 51 | waitIndex = resp.Node.ModifiedIndex + 1 52 | receiver <- resp 53 | } 54 | } 55 | 56 | func (c *Client) RawWatch(prefix string, waitIndex uint64, recursive bool, 57 | receiver chan *RawResponse, stop chan bool) (*RawResponse, error) { 58 | 59 | logger.Debugf("rawWatch %s [%s]", prefix, c.cluster.Leader) 60 | if receiver == nil { 61 | return c.watchOnce(prefix, waitIndex, recursive, stop) 62 | } 63 | 64 | for { 65 | raw, err := c.watchOnce(prefix, waitIndex, recursive, stop) 66 | 67 | if err != nil { 68 | return nil, err 69 | } 70 | 71 | resp, err := raw.Unmarshal() 72 | 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | waitIndex = resp.Node.ModifiedIndex + 1 78 | receiver <- raw 79 | } 80 | } 81 | 82 | // helper func 83 | // return when there is change under the given prefix 84 | func (c *Client) watchOnce(key string, waitIndex uint64, recursive bool, stop chan bool) (*RawResponse, error) { 85 | 86 | options := Options{ 87 | "wait": true, 88 | } 89 | if waitIndex > 0 { 90 | options["waitIndex"] = waitIndex 91 | } 92 | if recursive { 93 | options["recursive"] = true 94 | } 95 | 96 | resp, err := c.getCancelable(key, options, stop) 97 | 98 | if err == ErrRequestCancelled { 99 | return nil, ErrWatchStoppedByUser 100 | } 101 | 102 | return resp, err 103 | } 104 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/log_nix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | // Copyright 2013, Örjan Persson. All rights reserved. 4 | // Use of this source code is governed by a BSD-style 5 | // license that can be found in the LICENSE file. 6 | 7 | package logging 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | "io" 13 | "log" 14 | ) 15 | 16 | type color int 17 | 18 | const ( 19 | ColorBlack = iota + 30 20 | ColorRed 21 | ColorGreen 22 | ColorYellow 23 | ColorBlue 24 | ColorMagenta 25 | ColorCyan 26 | ColorWhite 27 | ) 28 | 29 | var ( 30 | colors = []string{ 31 | CRITICAL: ColorSeq(ColorMagenta), 32 | ERROR: ColorSeq(ColorRed), 33 | WARNING: ColorSeq(ColorYellow), 34 | NOTICE: ColorSeq(ColorGreen), 35 | DEBUG: ColorSeq(ColorCyan), 36 | } 37 | boldcolors = []string{ 38 | CRITICAL: ColorSeqBold(ColorMagenta), 39 | ERROR: ColorSeqBold(ColorRed), 40 | WARNING: ColorSeqBold(ColorYellow), 41 | NOTICE: ColorSeqBold(ColorGreen), 42 | DEBUG: ColorSeqBold(ColorCyan), 43 | } 44 | ) 45 | 46 | // LogBackend utilizes the standard log module. 47 | type LogBackend struct { 48 | Logger *log.Logger 49 | Color bool 50 | ColorConfig []string 51 | } 52 | 53 | // NewLogBackend creates a new LogBackend. 54 | func NewLogBackend(out io.Writer, prefix string, flag int) *LogBackend { 55 | return &LogBackend{Logger: log.New(out, prefix, flag)} 56 | } 57 | 58 | // Log implements the Backend interface. 59 | func (b *LogBackend) Log(level Level, calldepth int, rec *Record) error { 60 | if b.Color { 61 | col := colors[level] 62 | if len(b.ColorConfig) > int(level) && b.ColorConfig[level] != "" { 63 | col = b.ColorConfig[level] 64 | } 65 | 66 | buf := &bytes.Buffer{} 67 | buf.Write([]byte(col)) 68 | buf.Write([]byte(rec.Formatted(calldepth + 1))) 69 | buf.Write([]byte("\033[0m")) 70 | // For some reason, the Go logger arbitrarily decided "2" was the correct 71 | // call depth... 72 | return b.Logger.Output(calldepth+2, buf.String()) 73 | } 74 | 75 | return b.Logger.Output(calldepth+2, rec.Formatted(calldepth+1)) 76 | } 77 | 78 | // ConvertColors takes a list of ints representing colors for log levels and 79 | // converts them into strings for ANSI color formatting 80 | func ConvertColors(colors []int, bold bool) []string { 81 | converted := []string{} 82 | for _, i := range colors { 83 | if bold { 84 | converted = append(converted, ColorSeqBold(color(i))) 85 | } else { 86 | converted = append(converted, ColorSeq(color(i))) 87 | } 88 | } 89 | 90 | return converted 91 | } 92 | 93 | func ColorSeq(color color) string { 94 | return fmt.Sprintf("\033[%dm", int(color)) 95 | } 96 | 97 | func ColorSeqBold(color color) string { 98 | return fmt.Sprintf("\033[%d;1m", int(color)) 99 | } 100 | 101 | func doFmtVerbLevelColor(layout string, level Level, output io.Writer) { 102 | if layout == "bold" { 103 | output.Write([]byte(boldcolors[level])) 104 | } else if layout == "reset" { 105 | output.Write([]byte("\033[0m")) 106 | } else { 107 | output.Write([]byte(colors[level])) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # etcdenv 2 | 3 | Etcdenv provide a convenient way to populate environments variables from one your etcd directory 4 | 5 | ## Installation 6 | 7 | Easy! You can just download the binary from the command line: 8 | 9 | * Linux 10 | 11 | ```shell 12 | curl -sL https://github.com/upfluence/etcdenv/releases/download/v0.0.1/etcdenv-linux-amd64-0.0.1 > etcdenv 13 | ``` 14 | 15 | * OSX 16 | 17 | ```shell 18 | curl -sL https://github.com/upfluence/etcdenv/releases/download/v0.0.1/etcdenv-darwin-amd64-0.0.1 > etcdenv 19 | ``` 20 | 21 | If you would prefer compile the binary (assuming buildtools and Go are installed) : 22 | 23 | ```shell 24 | git clone git@github.com:upfluence/etcdenv.git 25 | cd etcdenv 26 | go get github.com/tools/godep 27 | GOPATH=`pwd`/Godeps/_workspace go build -o etcdenv . 28 | ``` 29 | 30 | ## Usage 31 | 32 | ### Options 33 | 34 | | Option | Default | Description | 35 | | ------ | ------- | ----------- | 36 | | `server`, `s` | http://127.0.0.1:4001 | Location of the etcd server | 37 | | `namespace`, `n`| /environments/production | Etcd directory where the environment variables are fetched. You can watch multiple namespaces by using a comma-separated list (/environments/production,/environments/global) | 38 | | `shutdown-behaviour`, `b` | exit | Strategy to apply when the process exit, further information into the next paragraph | 39 | | `watched`, `w` | `""` | A comma-separated list of environment variables triggering the command restart when they change | 40 | 41 | 42 | ### Shutdown strategies 43 | 44 | * `restart`: `etcdenv` rerun the command when the wrapped process exits 45 | * `exit`: The `etcdenv` process exits with the same exit status as the 46 | wrapped process's 47 | * `keepalive`: The `etcdenv` process will stay alive and keep looking 48 | for etcd changes to re-run the command 49 | 50 | ### Command line 51 | 52 | The CLI interface supports all of the options detailed above. 53 | 54 | 55 | #### Example 56 | 57 | *Assuming a etcd server is launched on your machine* 58 | 59 | **You can print env variables fetched from the `/` directory of your local node of etcd** 60 | 61 | ```shell 62 | $ curl -XPOST -d "value=bar" http://127.0.0.1:4001/v2/keys/FOO 63 | $ etcdenv -n / -r false printenv 64 | # ... your local environment variables 65 | FOO=bar 66 | $ 67 | ``` 68 | 69 | **You can also follow the changes of the directory** 70 | 71 | ```shell 72 | $ curl -XPOST -d "value=bar" http://127.0.0.1:4001/v2/keys/FOO 73 | $ etcdenv -n / printenv & 74 | # ... your local environment variables 75 | FOO=bar 76 | $ curl -XPOST -d "value=buz" http://127.0.0.1:4001/v2/keys/FOO 77 | 2014/12/29 00:30:00 Restarted 78 | # ... your local environment variables 79 | FOO=buz 80 | ``` 81 | 82 | **To watch a set of keys only** 83 | 84 | ```shell 85 | $ curl -XPOST -d "value=google.com" http://127.0.0.1:4001/v2/keys/GOOGLE_URL 86 | $ etcdenv -n / -w "FOO,GOOGLE_URL" printenv & 87 | # ... your local environment variables 88 | GOOGLE_URL=google.com 89 | $ curl -XPOST -d "value=foo" http://127.0.0.1:4001/v2/keys/BAR 90 | # ... the running command does not restart 91 | $ curl -XPOST -d "value=baz" http://127.0.0.1:4001/v2/keys/FOO 92 | # ... your local environment variables 93 | FOO=baz 94 | ``` 95 | 96 | ## Contributing 97 | 98 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/README.md: -------------------------------------------------------------------------------- 1 | ## Golang logging library 2 | 3 | [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/op/go-logging) [![build](https://img.shields.io/travis/op/go-logging.svg?style=flat)](https://travis-ci.org/op/go-logging) 4 | 5 | Package logging implements a logging infrastructure for Go. Its output format 6 | is customizable and supports different logging backends like syslog, file and 7 | memory. Multiple backends can be utilized with different log levels per backend 8 | and logger. 9 | 10 | **_NOTE:_** backwards compatibility promise have been dropped for master. Please 11 | vendor this package or use `gopkg.in/op/go-logging.v1` for previous version. See 12 | [changelog](CHANGELOG.md) for details. 13 | 14 | ## Example 15 | 16 | Let's have a look at an [example](examples/example.go) which demonstrates most 17 | of the features found in this library. 18 | 19 | [![Example Output](examples/example.png)](examples/example.go) 20 | 21 | ```go 22 | package main 23 | 24 | import ( 25 | "os" 26 | 27 | "github.com/op/go-logging" 28 | ) 29 | 30 | var log = logging.MustGetLogger("example") 31 | 32 | // Example format string. Everything except the message has a custom color 33 | // which is dependent on the log level. Many fields have a custom output 34 | // formatting too, eg. the time returns the hour down to the milli second. 35 | var format = logging.MustStringFormatter( 36 | `%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`, 37 | ) 38 | 39 | // Password is just an example type implementing the Redactor interface. Any 40 | // time this is logged, the Redacted() function will be called. 41 | type Password string 42 | 43 | func (p Password) Redacted() interface{} { 44 | return logging.Redact(string(p)) 45 | } 46 | 47 | func main() { 48 | // For demo purposes, create two backend for os.Stderr. 49 | backend1 := logging.NewLogBackend(os.Stderr, "", 0) 50 | backend2 := logging.NewLogBackend(os.Stderr, "", 0) 51 | 52 | // For messages written to backend2 we want to add some additional 53 | // information to the output, including the used log level and the name of 54 | // the function. 55 | backend2Formatter := logging.NewBackendFormatter(backend2, format) 56 | 57 | // Only errors and more severe messages should be sent to backend1 58 | backend1Leveled := logging.AddModuleLevel(backend1) 59 | backend1Leveled.SetLevel(logging.ERROR, "") 60 | 61 | // Set the backends to be used. 62 | logging.SetBackend(backend1Leveled, backend2Formatter) 63 | 64 | log.Debugf("debug %s", Password("secret")) 65 | log.Info("info") 66 | log.Notice("notice") 67 | log.Warning("warning") 68 | log.Error("err") 69 | log.Critical("crit") 70 | } 71 | ``` 72 | 73 | ## Installing 74 | 75 | ### Using *go get* 76 | 77 | $ go get github.com/op/go-logging 78 | 79 | After this command *go-logging* is ready to use. Its source will be in: 80 | 81 | $GOPATH/src/pkg/github.com/op/go-logging 82 | 83 | You can use `go get -u` to update the package. 84 | 85 | ## Documentation 86 | 87 | For docs, see http://godoc.org/github.com/op/go-logging or run: 88 | 89 | $ godoc github.com/op/go-logging 90 | 91 | ## Additional resources 92 | 93 | * [wslog](https://godoc.org/github.com/cryptix/exp/wslog) -- exposes log messages through a WebSocket. 94 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/log_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | // Copyright 2013, Örjan Persson. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package logging 7 | 8 | import ( 9 | "bytes" 10 | "io" 11 | "log" 12 | "syscall" 13 | ) 14 | 15 | var ( 16 | kernel32DLL = syscall.NewLazyDLL("kernel32.dll") 17 | setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute") 18 | ) 19 | 20 | // Character attributes 21 | // Note: 22 | // -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan). 23 | // Clearing all foreground or background colors results in black; setting all creates white. 24 | // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes. 25 | const ( 26 | fgBlack = 0x0000 27 | fgBlue = 0x0001 28 | fgGreen = 0x0002 29 | fgCyan = 0x0003 30 | fgRed = 0x0004 31 | fgMagenta = 0x0005 32 | fgYellow = 0x0006 33 | fgWhite = 0x0007 34 | fgIntensity = 0x0008 35 | fgMask = 0x000F 36 | ) 37 | 38 | var ( 39 | colors = []uint16{ 40 | INFO: fgWhite, 41 | CRITICAL: fgMagenta, 42 | ERROR: fgRed, 43 | WARNING: fgYellow, 44 | NOTICE: fgGreen, 45 | DEBUG: fgCyan, 46 | } 47 | boldcolors = []uint16{ 48 | INFO: fgWhite | fgIntensity, 49 | CRITICAL: fgMagenta | fgIntensity, 50 | ERROR: fgRed | fgIntensity, 51 | WARNING: fgYellow | fgIntensity, 52 | NOTICE: fgGreen | fgIntensity, 53 | DEBUG: fgCyan | fgIntensity, 54 | } 55 | ) 56 | 57 | type file interface { 58 | Fd() uintptr 59 | } 60 | 61 | // LogBackend utilizes the standard log module. 62 | type LogBackend struct { 63 | Logger *log.Logger 64 | Color bool 65 | 66 | // f is set to a non-nil value if the underlying writer which logs writes to 67 | // implements the file interface. This makes us able to colorise the output. 68 | f file 69 | } 70 | 71 | // NewLogBackend creates a new LogBackend. 72 | func NewLogBackend(out io.Writer, prefix string, flag int) *LogBackend { 73 | b := &LogBackend{Logger: log.New(out, prefix, flag)} 74 | 75 | // Unfortunately, the API used only takes an io.Writer where the Windows API 76 | // need the actual fd to change colors. 77 | if f, ok := out.(file); ok { 78 | b.f = f 79 | } 80 | 81 | return b 82 | } 83 | 84 | func (b *LogBackend) Log(level Level, calldepth int, rec *Record) error { 85 | if b.Color && b.f != nil { 86 | buf := &bytes.Buffer{} 87 | setConsoleTextAttribute(b.f, colors[level]) 88 | buf.Write([]byte(rec.Formatted(calldepth + 1))) 89 | err := b.Logger.Output(calldepth+2, buf.String()) 90 | setConsoleTextAttribute(b.f, fgWhite) 91 | return err 92 | } 93 | return b.Logger.Output(calldepth+2, rec.Formatted(calldepth+1)) 94 | } 95 | 96 | // setConsoleTextAttribute sets the attributes of characters written to the 97 | // console screen buffer by the WriteFile or WriteConsole function. 98 | // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx. 99 | func setConsoleTextAttribute(f file, attribute uint16) bool { 100 | ok, _, _ := setConsoleTextAttributeProc.Call(f.Fd(), uintptr(attribute), 0) 101 | return ok != 0 102 | } 103 | 104 | func doFmtVerbLevelColor(layout string, level Level, output io.Writer) { 105 | // TODO not supported on Windows since the io.Writer here is actually a 106 | // bytes.Buffer. 107 | } 108 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/level.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013, Örjan Persson. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package logging 6 | 7 | import ( 8 | "errors" 9 | "strings" 10 | "sync" 11 | ) 12 | 13 | // ErrInvalidLogLevel is used when an invalid log level has been used. 14 | var ErrInvalidLogLevel = errors.New("logger: invalid log level") 15 | 16 | // Level defines all available log levels for log messages. 17 | type Level int 18 | 19 | // Log levels. 20 | const ( 21 | CRITICAL Level = iota 22 | ERROR 23 | WARNING 24 | NOTICE 25 | INFO 26 | DEBUG 27 | ) 28 | 29 | var levelNames = []string{ 30 | "CRITICAL", 31 | "ERROR", 32 | "WARNING", 33 | "NOTICE", 34 | "INFO", 35 | "DEBUG", 36 | } 37 | 38 | // String returns the string representation of a logging level. 39 | func (p Level) String() string { 40 | return levelNames[p] 41 | } 42 | 43 | // LogLevel returns the log level from a string representation. 44 | func LogLevel(level string) (Level, error) { 45 | for i, name := range levelNames { 46 | if strings.EqualFold(name, level) { 47 | return Level(i), nil 48 | } 49 | } 50 | return ERROR, ErrInvalidLogLevel 51 | } 52 | 53 | // Leveled interface is the interface required to be able to add leveled 54 | // logging. 55 | type Leveled interface { 56 | GetLevel(string) Level 57 | SetLevel(Level, string) 58 | IsEnabledFor(Level, string) bool 59 | } 60 | 61 | // LeveledBackend is a log backend with additional knobs for setting levels on 62 | // individual modules to different levels. 63 | type LeveledBackend interface { 64 | Backend 65 | Leveled 66 | } 67 | 68 | type moduleLeveled struct { 69 | levels map[string]Level 70 | backend Backend 71 | formatter Formatter 72 | once sync.Once 73 | } 74 | 75 | // AddModuleLevel wraps a log backend with knobs to have different log levels 76 | // for different modules. 77 | func AddModuleLevel(backend Backend) LeveledBackend { 78 | var leveled LeveledBackend 79 | var ok bool 80 | if leveled, ok = backend.(LeveledBackend); !ok { 81 | leveled = &moduleLeveled{ 82 | levels: make(map[string]Level), 83 | backend: backend, 84 | } 85 | } 86 | return leveled 87 | } 88 | 89 | // GetLevel returns the log level for the given module. 90 | func (l *moduleLeveled) GetLevel(module string) Level { 91 | level, exists := l.levels[module] 92 | if exists == false { 93 | level, exists = l.levels[""] 94 | // no configuration exists, default to debug 95 | if exists == false { 96 | level = DEBUG 97 | } 98 | } 99 | return level 100 | } 101 | 102 | // SetLevel sets the log level for the given module. 103 | func (l *moduleLeveled) SetLevel(level Level, module string) { 104 | l.levels[module] = level 105 | } 106 | 107 | // IsEnabledFor will return true if logging is enabled for the given module. 108 | func (l *moduleLeveled) IsEnabledFor(level Level, module string) bool { 109 | return level <= l.GetLevel(module) 110 | } 111 | 112 | func (l *moduleLeveled) Log(level Level, calldepth int, rec *Record) (err error) { 113 | if l.IsEnabledFor(level, rec.Module) { 114 | // TODO get rid of traces of formatter here. BackendFormatter should be used. 115 | rec.formatter = l.getFormatterAndCacheCurrent() 116 | err = l.backend.Log(level, calldepth+1, rec) 117 | } 118 | return 119 | } 120 | 121 | func (l *moduleLeveled) getFormatterAndCacheCurrent() Formatter { 122 | l.once.Do(func() { 123 | if l.formatter == nil { 124 | l.formatter = getFormatter() 125 | } 126 | }) 127 | return l.formatter 128 | } 129 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/exponential_test.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func TestBackOff(t *testing.T) { 10 | var ( 11 | testInitialInterval = 500 * time.Millisecond 12 | testRandomizationFactor = 0.1 13 | testMultiplier = 2.0 14 | testMaxInterval = 5 * time.Second 15 | testMaxElapsedTime = 15 * time.Minute 16 | ) 17 | 18 | exp := NewExponentialBackOff() 19 | exp.InitialInterval = testInitialInterval 20 | exp.RandomizationFactor = testRandomizationFactor 21 | exp.Multiplier = testMultiplier 22 | exp.MaxInterval = testMaxInterval 23 | exp.MaxElapsedTime = testMaxElapsedTime 24 | exp.Reset() 25 | 26 | var expectedResults = []time.Duration{500, 1000, 2000, 4000, 5000, 5000, 5000, 5000, 5000, 5000} 27 | for i, d := range expectedResults { 28 | expectedResults[i] = d * time.Millisecond 29 | } 30 | 31 | for _, expected := range expectedResults { 32 | assertEquals(t, expected, exp.currentInterval) 33 | // Assert that the next back off falls in the expected range. 34 | var minInterval = expected - time.Duration(testRandomizationFactor*float64(expected)) 35 | var maxInterval = expected + time.Duration(testRandomizationFactor*float64(expected)) 36 | var actualInterval = exp.NextBackOff() 37 | if !(minInterval <= actualInterval && actualInterval <= maxInterval) { 38 | t.Error("error") 39 | } 40 | } 41 | } 42 | 43 | func TestGetRandomizedInterval(t *testing.T) { 44 | // 33% chance of being 1. 45 | assertEquals(t, 1, getRandomValueFromInterval(0.5, 0, 2)) 46 | assertEquals(t, 1, getRandomValueFromInterval(0.5, 0.33, 2)) 47 | // 33% chance of being 2. 48 | assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.34, 2)) 49 | assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.66, 2)) 50 | // 33% chance of being 3. 51 | assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.67, 2)) 52 | assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.99, 2)) 53 | } 54 | 55 | type TestClock struct { 56 | i time.Duration 57 | start time.Time 58 | } 59 | 60 | func (c *TestClock) Now() time.Time { 61 | t := c.start.Add(c.i) 62 | c.i += time.Second 63 | return t 64 | } 65 | 66 | func TestGetElapsedTime(t *testing.T) { 67 | var exp = NewExponentialBackOff() 68 | exp.Clock = &TestClock{} 69 | exp.Reset() 70 | 71 | var elapsedTime = exp.GetElapsedTime() 72 | if elapsedTime != time.Second { 73 | t.Errorf("elapsedTime=%d", elapsedTime) 74 | } 75 | } 76 | 77 | func TestMaxElapsedTime(t *testing.T) { 78 | var exp = NewExponentialBackOff() 79 | exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)} 80 | if exp.NextBackOff() != Stop { 81 | t.Error("error2") 82 | } 83 | // Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater 84 | // than the max elapsed time. 85 | exp.startTime = time.Time{} 86 | assertEquals(t, Stop, exp.NextBackOff()) 87 | } 88 | 89 | func TestBackOffOverflow(t *testing.T) { 90 | var ( 91 | testInitialInterval time.Duration = math.MaxInt64 / 2 92 | testMaxInterval time.Duration = math.MaxInt64 93 | testMultiplier float64 = 2.1 94 | ) 95 | 96 | exp := NewExponentialBackOff() 97 | exp.InitialInterval = testInitialInterval 98 | exp.Multiplier = testMultiplier 99 | exp.MaxInterval = testMaxInterval 100 | exp.Reset() 101 | 102 | exp.NextBackOff() 103 | // Assert that when an overflow is possible the current varerval time.Duration is set to the max varerval time.Duration . 104 | assertEquals(t, testMaxInterval, exp.currentInterval) 105 | } 106 | 107 | func assertEquals(t *testing.T, expected, value time.Duration) { 108 | if expected != value { 109 | t.Errorf("got: %d, expected: %d", value, expected) 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/set_update_create.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | // Set sets the given key to the given value. 4 | // It will create a new key value pair or replace the old one. 5 | // It will not replace a existing directory. 6 | func (c *Client) Set(key string, value string, ttl uint64) (*Response, error) { 7 | raw, err := c.RawSet(key, value, ttl) 8 | 9 | if err != nil { 10 | return nil, err 11 | } 12 | 13 | return raw.Unmarshal() 14 | } 15 | 16 | // SetDir sets the given key to a directory. 17 | // It will create a new directory or replace the old key value pair by a directory. 18 | // It will not replace a existing directory. 19 | func (c *Client) SetDir(key string, ttl uint64) (*Response, error) { 20 | raw, err := c.RawSetDir(key, ttl) 21 | 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | return raw.Unmarshal() 27 | } 28 | 29 | // CreateDir creates a directory. It succeeds only if 30 | // the given key does not yet exist. 31 | func (c *Client) CreateDir(key string, ttl uint64) (*Response, error) { 32 | raw, err := c.RawCreateDir(key, ttl) 33 | 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | return raw.Unmarshal() 39 | } 40 | 41 | // UpdateDir updates the given directory. It succeeds only if the 42 | // given key already exists. 43 | func (c *Client) UpdateDir(key string, ttl uint64) (*Response, error) { 44 | raw, err := c.RawUpdateDir(key, ttl) 45 | 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | return raw.Unmarshal() 51 | } 52 | 53 | // Create creates a file with the given value under the given key. It succeeds 54 | // only if the given key does not yet exist. 55 | func (c *Client) Create(key string, value string, ttl uint64) (*Response, error) { 56 | raw, err := c.RawCreate(key, value, ttl) 57 | 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | return raw.Unmarshal() 63 | } 64 | 65 | // CreateInOrder creates a file with a key that's guaranteed to be higher than other 66 | // keys in the given directory. It is useful for creating queues. 67 | func (c *Client) CreateInOrder(dir string, value string, ttl uint64) (*Response, error) { 68 | raw, err := c.RawCreateInOrder(dir, value, ttl) 69 | 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | return raw.Unmarshal() 75 | } 76 | 77 | // Update updates the given key to the given value. It succeeds only if the 78 | // given key already exists. 79 | func (c *Client) Update(key string, value string, ttl uint64) (*Response, error) { 80 | raw, err := c.RawUpdate(key, value, ttl) 81 | 82 | if err != nil { 83 | return nil, err 84 | } 85 | 86 | return raw.Unmarshal() 87 | } 88 | 89 | func (c *Client) RawUpdateDir(key string, ttl uint64) (*RawResponse, error) { 90 | ops := Options{ 91 | "prevExist": true, 92 | "dir": true, 93 | } 94 | 95 | return c.put(key, "", ttl, ops) 96 | } 97 | 98 | func (c *Client) RawCreateDir(key string, ttl uint64) (*RawResponse, error) { 99 | ops := Options{ 100 | "prevExist": false, 101 | "dir": true, 102 | } 103 | 104 | return c.put(key, "", ttl, ops) 105 | } 106 | 107 | func (c *Client) RawSet(key string, value string, ttl uint64) (*RawResponse, error) { 108 | return c.put(key, value, ttl, nil) 109 | } 110 | 111 | func (c *Client) RawSetDir(key string, ttl uint64) (*RawResponse, error) { 112 | ops := Options{ 113 | "dir": true, 114 | } 115 | 116 | return c.put(key, "", ttl, ops) 117 | } 118 | 119 | func (c *Client) RawUpdate(key string, value string, ttl uint64) (*RawResponse, error) { 120 | ops := Options{ 121 | "prevExist": true, 122 | } 123 | 124 | return c.put(key, value, ttl, ops) 125 | } 126 | 127 | func (c *Client) RawCreate(key string, value string, ttl uint64) (*RawResponse, error) { 128 | ops := Options{ 129 | "prevExist": false, 130 | } 131 | 132 | return c.put(key, value, ttl, ops) 133 | } 134 | 135 | func (c *Client) RawCreateInOrder(dir string, value string, ttl uint64) (*RawResponse, error) { 136 | return c.post(dir, value, ttl) 137 | } 138 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/gen-helper.generated.go: -------------------------------------------------------------------------------- 1 | // //+build ignore 2 | 3 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 4 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 5 | 6 | // ************************************************************ 7 | // DO NOT EDIT. 8 | // THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl 9 | // ************************************************************ 10 | 11 | package codec 12 | 13 | // This file is used to generate helper code for codecgen. 14 | // The values here i.e. genHelper(En|De)coder are not to be used directly by 15 | // library users. They WILL change continously and without notice. 16 | // 17 | // To help enforce this, we create an unexported type with exported members. 18 | // The only way to get the type is via the one exported type that we control (somewhat). 19 | // 20 | // When static codecs are created for types, they will use this value 21 | // to perform encoding or decoding of primitives or known slice or map types. 22 | 23 | // GenHelperEncoder is exported so that it can be used externally by codecgen. 24 | // Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. 25 | func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) { 26 | return genHelperEncoder{e: e}, e.e 27 | } 28 | 29 | // GenHelperDecoder is exported so that it can be used externally by codecgen. 30 | // Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. 31 | func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) { 32 | return genHelperDecoder{d: d}, d.d 33 | } 34 | 35 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 36 | type genHelperEncoder struct { 37 | e *Encoder 38 | F fastpathT 39 | } 40 | 41 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 42 | type genHelperDecoder struct { 43 | d *Decoder 44 | F fastpathT 45 | } 46 | 47 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 48 | func (f genHelperEncoder) EncBasicHandle() *BasicHandle { 49 | return f.e.h 50 | } 51 | 52 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 53 | func (f genHelperEncoder) EncBinary() bool { 54 | return f.e.be // f.e.hh.isBinaryEncoding() 55 | } 56 | 57 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 58 | func (f genHelperEncoder) EncFallback(iv interface{}) { 59 | // println(">>>>>>>>> EncFallback") 60 | f.e.encodeI(iv, false, false) 61 | } 62 | 63 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 64 | func (f genHelperDecoder) DecBasicHandle() *BasicHandle { 65 | return f.d.h 66 | } 67 | 68 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 69 | func (f genHelperDecoder) DecBinary() bool { 70 | return f.d.be // f.d.hh.isBinaryEncoding() 71 | } 72 | 73 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 74 | func (f genHelperDecoder) DecSwallow() { 75 | f.d.swallow() 76 | } 77 | 78 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 79 | func (f genHelperDecoder) DecScratchBuffer() []byte { 80 | return f.d.b[:] 81 | } 82 | 83 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 84 | func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) { 85 | // println(">>>>>>>>> DecFallback") 86 | f.d.decodeI(iv, chkPtr, false, false, false) 87 | } 88 | 89 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 90 | func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) { 91 | return f.d.decSliceHelperStart() 92 | } 93 | 94 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 95 | func (f genHelperDecoder) DecStructFieldNotFound(index int, name string) { 96 | f.d.structFieldNotFound(index, name) 97 | } 98 | 99 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 100 | func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) { 101 | f.d.arrayCannotExpand(sliceLen, streamLen) 102 | } 103 | -------------------------------------------------------------------------------- /etcdenv.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Upfluence, Inc. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package main 15 | 16 | import ( 17 | "flag" 18 | "fmt" 19 | "os" 20 | "os/signal" 21 | "strings" 22 | "syscall" 23 | 24 | "github.com/upfluence/etcdenv/etcdenv" 25 | "github.com/upfluence/goutils/log" 26 | ) 27 | 28 | const currentVersion = "0.4.1" 29 | 30 | var ( 31 | flagset = flag.NewFlagSet("etcdenv", flag.ExitOnError) 32 | flags = struct { 33 | Version bool 34 | ShutdownBehaviour string 35 | Server string 36 | Namespace string 37 | WatchedKeys string 38 | UserName string 39 | Password string 40 | }{} 41 | ) 42 | 43 | func usage() { 44 | fmt.Fprintf(os.Stderr, ` 45 | NAME 46 | etcdenv - use your etcd keys as environment variables 47 | 48 | USAGE 49 | etcdenv [options] 50 | 51 | OPTIONS 52 | `) 53 | flagset.PrintDefaults() 54 | } 55 | 56 | func init() { 57 | flagset.BoolVar(&flags.Version, "version", false, "Print the version and exit") 58 | flagset.BoolVar(&flags.Version, "v", false, "Print the version and exit") 59 | 60 | flagset.StringVar(&flags.ShutdownBehaviour, "b", "exit", "Behaviour when the process stop [exit|keepalive|restart]") 61 | flagset.StringVar(&flags.ShutdownBehaviour, "shutdown-behaviour", "exit", "Behaviour when the process stop [exit|keepalive|restart]") 62 | 63 | flagset.StringVar(&flags.Server, "server", "http://127.0.0.1:4001", "Location of the etcd server") 64 | flagset.StringVar(&flags.Server, "s", "http://127.0.0.1:4001", "Location of the etcd server") 65 | 66 | flagset.StringVar(&flags.Namespace, "namespace", "/environments/production", "etcd directory where the environment variables are fetched") 67 | flagset.StringVar(&flags.Namespace, "n", "/environments/production", "etcd directory where the environment variables are fetched") 68 | 69 | flagset.StringVar(&flags.WatchedKeys, "watched", "", "environment variables to watch, comma-separated") 70 | flagset.StringVar(&flags.WatchedKeys, "w", "", "environment variables to watch, comma-separated") 71 | 72 | flagset.StringVar(&flags.UserName, "user", "", "user to authenticate to etcd server") 73 | flagset.StringVar(&flags.UserName, "u", "", "user to authenticate to etcd server") 74 | 75 | flagset.StringVar(&flags.Password, "password", "", "password to authenticate to etcd server") 76 | flagset.StringVar(&flags.Password, "p", "", "password to authenticate to etcd server") 77 | } 78 | 79 | func main() { 80 | var watchedKeysList []string 81 | 82 | flagset.Parse(os.Args[1:]) 83 | flagset.Usage = usage 84 | 85 | if len(os.Args) < 2 { 86 | flagset.Usage() 87 | os.Exit(0) 88 | } 89 | 90 | if flags.Version { 91 | fmt.Printf("etcdenv v%s", currentVersion) 92 | os.Exit(0) 93 | } 94 | 95 | signalChan := make(chan os.Signal) 96 | signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) 97 | 98 | if flags.WatchedKeys == "" { 99 | watchedKeysList = []string{} 100 | } else { 101 | watchedKeysList = strings.Split(flags.WatchedKeys, ",") 102 | } 103 | 104 | ctx, err := etcdenv.NewContext( 105 | strings.Split(flags.Namespace, ","), 106 | []string{flags.Server}, 107 | flagset.Args(), 108 | flags.ShutdownBehaviour, 109 | watchedKeysList, 110 | flags.UserName, 111 | flags.Password, 112 | ) 113 | 114 | if err != nil { 115 | log.Fatalf(err.Error()) 116 | os.Exit(1) 117 | } 118 | 119 | go ctx.Run() 120 | 121 | select { 122 | case sig := <-signalChan: 123 | log.Noticef("Received signal %s", sig) 124 | ctx.ExitChan <- true 125 | case <-ctx.ExitChan: 126 | log.Infof("Catching ExitChan, doing nothin'") 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This will create golden files in a directory passed to it. 4 | # A Test calls this internally to create the golden files 5 | # So it can process them (so we don't have to checkin the files). 6 | 7 | # Ensure msgpack-python and cbor are installed first, using: 8 | # pip install --user msgpack-python 9 | # pip install --user cbor 10 | 11 | import cbor, msgpack, msgpackrpc, sys, os, threading 12 | 13 | def get_test_data_list(): 14 | # get list with all primitive types, and a combo type 15 | l0 = [ 16 | -8, 17 | -1616, 18 | -32323232, 19 | -6464646464646464, 20 | 192, 21 | 1616, 22 | 32323232, 23 | 6464646464646464, 24 | 192, 25 | -3232.0, 26 | -6464646464.0, 27 | 3232.0, 28 | 6464646464.0, 29 | False, 30 | True, 31 | None, 32 | u"someday", 33 | u"", 34 | u"bytestring", 35 | 1328176922000002000, 36 | -2206187877999998000, 37 | 270, 38 | -2013855847999995777, 39 | #-6795364578871345152, 40 | ] 41 | l1 = [ 42 | { "true": True, 43 | "false": False }, 44 | { "true": "True", 45 | "false": False, 46 | "uint16(1616)": 1616 }, 47 | { "list": [1616, 32323232, True, -3232.0, {"TRUE":True, "FALSE":False}, [True, False] ], 48 | "int32":32323232, "bool": True, 49 | "LONG STRING": "123456789012345678901234567890123456789012345678901234567890", 50 | "SHORT STRING": "1234567890" }, 51 | { True: "true", 8: False, "false": 0 } 52 | ] 53 | 54 | l = [] 55 | l.extend(l0) 56 | l.append(l0) 57 | l.extend(l1) 58 | return l 59 | 60 | def build_test_data(destdir): 61 | l = get_test_data_list() 62 | for i in range(len(l)): 63 | # packer = msgpack.Packer() 64 | serialized = msgpack.dumps(l[i]) 65 | f = open(os.path.join(destdir, str(i) + '.msgpack.golden'), 'wb') 66 | f.write(serialized) 67 | f.close() 68 | serialized = cbor.dumps(l[i]) 69 | f = open(os.path.join(destdir, str(i) + '.cbor.golden'), 'wb') 70 | f.write(serialized) 71 | f.close() 72 | 73 | def doRpcServer(port, stopTimeSec): 74 | class EchoHandler(object): 75 | def Echo123(self, msg1, msg2, msg3): 76 | return ("1:%s 2:%s 3:%s" % (msg1, msg2, msg3)) 77 | def EchoStruct(self, msg): 78 | return ("%s" % msg) 79 | 80 | addr = msgpackrpc.Address('localhost', port) 81 | server = msgpackrpc.Server(EchoHandler()) 82 | server.listen(addr) 83 | # run thread to stop it after stopTimeSec seconds if > 0 84 | if stopTimeSec > 0: 85 | def myStopRpcServer(): 86 | server.stop() 87 | t = threading.Timer(stopTimeSec, myStopRpcServer) 88 | t.start() 89 | server.start() 90 | 91 | def doRpcClientToPythonSvc(port): 92 | address = msgpackrpc.Address('localhost', port) 93 | client = msgpackrpc.Client(address, unpack_encoding='utf-8') 94 | print client.call("Echo123", "A1", "B2", "C3") 95 | print client.call("EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}) 96 | 97 | def doRpcClientToGoSvc(port): 98 | # print ">>>> port: ", port, " <<<<<" 99 | address = msgpackrpc.Address('localhost', port) 100 | client = msgpackrpc.Client(address, unpack_encoding='utf-8') 101 | print client.call("TestRpcInt.Echo123", ["A1", "B2", "C3"]) 102 | print client.call("TestRpcInt.EchoStruct", {"A" :"Aa", "B":"Bb", "C":"Cc"}) 103 | 104 | def doMain(args): 105 | if len(args) == 2 and args[0] == "testdata": 106 | build_test_data(args[1]) 107 | elif len(args) == 3 and args[0] == "rpc-server": 108 | doRpcServer(int(args[1]), int(args[2])) 109 | elif len(args) == 2 and args[0] == "rpc-client-python-service": 110 | doRpcClientToPythonSvc(int(args[1])) 111 | elif len(args) == 2 and args[0] == "rpc-client-go-service": 112 | doRpcClientToGoSvc(int(args[1])) 113 | else: 114 | print("Usage: test.py " + 115 | "[testdata|rpc-server|rpc-client-python-service|rpc-client-go-service] ...") 116 | 117 | if __name__ == "__main__": 118 | doMain(sys.argv[1:]) 119 | 120 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/helper_internal.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 3 | 4 | package codec 5 | 6 | // All non-std package dependencies live in this file, 7 | // so porting to different environment is easy (just update functions). 8 | 9 | import ( 10 | "errors" 11 | "fmt" 12 | "math" 13 | "reflect" 14 | ) 15 | 16 | func panicValToErr(panicVal interface{}, err *error) { 17 | if panicVal == nil { 18 | return 19 | } 20 | // case nil 21 | switch xerr := panicVal.(type) { 22 | case error: 23 | *err = xerr 24 | case string: 25 | *err = errors.New(xerr) 26 | default: 27 | *err = fmt.Errorf("%v", panicVal) 28 | } 29 | return 30 | } 31 | 32 | func hIsEmptyValue(v reflect.Value, deref, checkStruct bool) bool { 33 | switch v.Kind() { 34 | case reflect.Invalid: 35 | return true 36 | case reflect.Array, reflect.Map, reflect.Slice, reflect.String: 37 | return v.Len() == 0 38 | case reflect.Bool: 39 | return !v.Bool() 40 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 41 | return v.Int() == 0 42 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 43 | return v.Uint() == 0 44 | case reflect.Float32, reflect.Float64: 45 | return v.Float() == 0 46 | case reflect.Interface, reflect.Ptr: 47 | if deref { 48 | if v.IsNil() { 49 | return true 50 | } 51 | return hIsEmptyValue(v.Elem(), deref, checkStruct) 52 | } else { 53 | return v.IsNil() 54 | } 55 | case reflect.Struct: 56 | if !checkStruct { 57 | return false 58 | } 59 | // return true if all fields are empty. else return false. 60 | // we cannot use equality check, because some fields may be maps/slices/etc 61 | // and consequently the structs are not comparable. 62 | // return v.Interface() == reflect.Zero(v.Type()).Interface() 63 | for i, n := 0, v.NumField(); i < n; i++ { 64 | if !hIsEmptyValue(v.Field(i), deref, checkStruct) { 65 | return false 66 | } 67 | } 68 | return true 69 | } 70 | return false 71 | } 72 | 73 | func isEmptyValue(v reflect.Value) bool { 74 | return hIsEmptyValue(v, derefForIsEmptyValue, checkStructForEmptyValue) 75 | } 76 | 77 | func pruneSignExt(v []byte, pos bool) (n int) { 78 | if len(v) < 2 { 79 | } else if pos && v[0] == 0 { 80 | for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ { 81 | } 82 | } else if !pos && v[0] == 0xff { 83 | for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ { 84 | } 85 | } 86 | return 87 | } 88 | 89 | func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) { 90 | if typ == nil { 91 | return 92 | } 93 | rt := typ 94 | // The type might be a pointer and we need to keep 95 | // dereferencing to the base type until we find an implementation. 96 | for { 97 | if rt.Implements(iTyp) { 98 | return true, indir 99 | } 100 | if p := rt; p.Kind() == reflect.Ptr { 101 | indir++ 102 | if indir >= math.MaxInt8 { // insane number of indirections 103 | return false, 0 104 | } 105 | rt = p.Elem() 106 | continue 107 | } 108 | break 109 | } 110 | // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. 111 | if typ.Kind() != reflect.Ptr { 112 | // Not a pointer, but does the pointer work? 113 | if reflect.PtrTo(typ).Implements(iTyp) { 114 | return true, -1 115 | } 116 | } 117 | return false, 0 118 | } 119 | 120 | // validate that this function is correct ... 121 | // culled from OGRE (Object-Oriented Graphics Rendering Engine) 122 | // function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html) 123 | func halfFloatToFloatBits(yy uint16) (d uint32) { 124 | y := uint32(yy) 125 | s := (y >> 15) & 0x01 126 | e := (y >> 10) & 0x1f 127 | m := y & 0x03ff 128 | 129 | if e == 0 { 130 | if m == 0 { // plu or minus 0 131 | return s << 31 132 | } else { // Denormalized number -- renormalize it 133 | for (m & 0x00000400) == 0 { 134 | m <<= 1 135 | e -= 1 136 | } 137 | e += 1 138 | const zz uint32 = 0x0400 139 | m &= ^zz 140 | } 141 | } else if e == 31 { 142 | if m == 0 { // Inf 143 | return (s << 31) | 0x7f800000 144 | } else { // NaN 145 | return (s << 31) | 0x7f800000 | (m << 13) 146 | } 147 | } 148 | e = e + (127 - 15) 149 | m = m << 13 150 | return (s << 31) | (e << 23) | m 151 | } 152 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/gen.generated.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 3 | 4 | package codec 5 | 6 | // DO NOT EDIT. THIS FILE IS AUTO-GENERATED FROM gen-dec-(map|array).go.tmpl 7 | 8 | const genDecMapTmpl = ` 9 | {{var "v"}} := *{{ .Varname }} 10 | {{var "l"}} := r.ReadMapStart() 11 | if {{var "v"}} == nil { 12 | if {{var "l"}} > 0 { 13 | {{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "l"}}) 14 | } else { 15 | {{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}) // supports indefinite-length, etc 16 | } 17 | *{{ .Varname }} = {{var "v"}} 18 | } 19 | if {{var "l"}} > 0 { 20 | for {{var "j"}} := 0; {{var "j"}} < {{var "l"}}; {{var "j"}}++ { 21 | var {{var "mk"}} {{ .KTyp }} 22 | {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} 23 | {{ if eq .KTyp "interface{}" }}// special case if a byte array. 24 | if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { 25 | {{var "mk"}} = string({{var "bv"}}) 26 | } 27 | {{ end }} 28 | {{var "mv"}} := {{var "v"}}[{{var "mk"}}] 29 | {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} 30 | if {{var "v"}} != nil { 31 | {{var "v"}}[{{var "mk"}}] = {{var "mv"}} 32 | } 33 | } 34 | } else if {{var "l"}} < 0 { 35 | for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ { 36 | if {{var "j"}} > 0 { 37 | r.ReadMapEntrySeparator() 38 | } 39 | var {{var "mk"}} {{ .KTyp }} 40 | {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }} 41 | {{ if eq .KTyp "interface{}" }}// special case if a byte array. 42 | if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} { 43 | {{var "mk"}} = string({{var "bv"}}) 44 | } 45 | {{ end }} 46 | r.ReadMapKVSeparator() 47 | {{var "mv"}} := {{var "v"}}[{{var "mk"}}] 48 | {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ decLineVar $x }} 49 | if {{var "v"}} != nil { 50 | {{var "v"}}[{{var "mk"}}] = {{var "mv"}} 51 | } 52 | } 53 | r.ReadMapEnd() 54 | } // else len==0: TODO: Should we clear map entries? 55 | ` 56 | 57 | const genDecListTmpl = ` 58 | {{var "v"}} := *{{ .Varname }} 59 | {{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() 60 | 61 | var {{var "c"}} bool 62 | {{ if not isArray }}if {{var "v"}} == nil { 63 | if {{var "l"}} <= 0 { 64 | {{var "v"}} = make({{ .CTyp }}, 0) 65 | } else { 66 | {{var "v"}} = make({{ .CTyp }}, {{var "l"}}) 67 | } 68 | {{var "c"}} = true 69 | } 70 | {{ end }} 71 | if {{var "l"}} == 0 { {{ if isSlice }} 72 | if len({{var "v"}}) != 0 { 73 | {{var "v"}} = {{var "v"}}[:0] 74 | {{var "c"}} = true 75 | } {{ end }} 76 | } else if {{var "l"}} > 0 { 77 | {{ if isChan }} 78 | for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ { 79 | var {{var "t"}} {{ .Typ }} 80 | {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} 81 | {{var "v"}} <- {{var "t"}} 82 | {{ else }} 83 | {{var "n"}} := {{var "l"}} 84 | if {{var "l"}} > cap({{var "v"}}) { 85 | {{ if isArray }}r.ReadArrayCannotExpand(len({{var "v"}}), {{var "l"}}) 86 | {{var "n"}} = len({{var "v"}}) 87 | {{ else }}{{ if .Immutable }} 88 | {{var "v2"}} := {{var "v"}} 89 | {{var "v"}} = make([]{{ .Typ }}, {{var "l"}}, {{var "l"}}) 90 | if len({{var "v"}}) > 0 { 91 | copy({{var "v"}}, {{var "v2"}}[:cap({{var "v2"}})]) 92 | } 93 | {{ else }}{{var "v"}} = make([]{{ .Typ }}, {{var "l"}}, {{var "l"}}) 94 | {{ end }}{{var "c"}} = true 95 | {{ end }} 96 | } else if {{var "l"}} != len({{var "v"}}) { 97 | {{var "v"}} = {{var "v"}}[:{{var "l"}}] 98 | {{var "c"}} = true 99 | } 100 | {{var "j"}} := 0 101 | for ; {{var "j"}} < {{var "n"}} ; {{var "j"}}++ { 102 | {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} 103 | } {{ if isArray }} 104 | for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ { 105 | z.DecSwallow() 106 | }{{ end }} 107 | {{ end }}{{/* closing if not chan */}} 108 | } else { 109 | for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ { 110 | if {{var "j"}} >= len({{var "v"}}) { 111 | {{ if isArray }}r.ReadArrayCannotExpand(len({{var "v"}}), {{var "j"}}+1) 112 | {{ else if isSlice}}{{var "v"}} = append({{var "v"}}, {{zero}})// var {{var "z"}} {{ .Typ }} 113 | {{var "c"}} = true {{ end }} 114 | } 115 | if {{var "j"}} > 0 { 116 | {{var "h"}}.Sep({{var "j"}}) 117 | } 118 | {{ if isChan}} 119 | var {{var "t"}} {{ .Typ }} 120 | {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} 121 | {{var "v"}} <- {{var "t"}} 122 | {{ else }} 123 | if {{var "j"}} < len({{var "v"}}) { 124 | {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} 125 | } else { 126 | z.DecSwallow() 127 | } 128 | {{ end }} 129 | } 130 | {{var "h"}}.End() 131 | } 132 | if {{var "c"}} { 133 | *{{ .Varname }} = {{var "v"}} 134 | } 135 | ` 136 | 137 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/rpc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 3 | 4 | package codec 5 | 6 | import ( 7 | "bufio" 8 | "io" 9 | "net/rpc" 10 | "sync" 11 | ) 12 | 13 | // rpcEncodeTerminator allows a handler specify a []byte terminator to send after each Encode. 14 | // 15 | // Some codecs like json need to put a space after each encoded value, to serve as a 16 | // delimiter for things like numbers (else json codec will continue reading till EOF). 17 | type rpcEncodeTerminator interface { 18 | rpcEncodeTerminate() []byte 19 | } 20 | 21 | // Rpc provides a rpc Server or Client Codec for rpc communication. 22 | type Rpc interface { 23 | ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec 24 | ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec 25 | } 26 | 27 | // RpcCodecBuffered allows access to the underlying bufio.Reader/Writer 28 | // used by the rpc connection. It accomodates use-cases where the connection 29 | // should be used by rpc and non-rpc functions, e.g. streaming a file after 30 | // sending an rpc response. 31 | type RpcCodecBuffered interface { 32 | BufferedReader() *bufio.Reader 33 | BufferedWriter() *bufio.Writer 34 | } 35 | 36 | // ------------------------------------- 37 | 38 | // rpcCodec defines the struct members and common methods. 39 | type rpcCodec struct { 40 | rwc io.ReadWriteCloser 41 | dec *Decoder 42 | enc *Encoder 43 | bw *bufio.Writer 44 | br *bufio.Reader 45 | mu sync.Mutex 46 | cls bool 47 | h Handle 48 | } 49 | 50 | func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec { 51 | bw := bufio.NewWriter(conn) 52 | br := bufio.NewReader(conn) 53 | return rpcCodec{ 54 | rwc: conn, 55 | bw: bw, 56 | br: br, 57 | enc: NewEncoder(bw, h), 58 | dec: NewDecoder(br, h), 59 | h: h, 60 | } 61 | } 62 | 63 | func (c *rpcCodec) BufferedReader() *bufio.Reader { 64 | return c.br 65 | } 66 | 67 | func (c *rpcCodec) BufferedWriter() *bufio.Writer { 68 | return c.bw 69 | } 70 | 71 | func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2, doFlush bool) (err error) { 72 | if c.cls { 73 | return io.EOF 74 | } 75 | if err = c.enc.Encode(obj1); err != nil { 76 | return 77 | } 78 | t, tOk := c.h.(rpcEncodeTerminator) 79 | if tOk { 80 | c.bw.Write(t.rpcEncodeTerminate()) 81 | } 82 | if writeObj2 { 83 | if err = c.enc.Encode(obj2); err != nil { 84 | return 85 | } 86 | if tOk { 87 | c.bw.Write(t.rpcEncodeTerminate()) 88 | } 89 | } 90 | if doFlush { 91 | return c.bw.Flush() 92 | } 93 | return 94 | } 95 | 96 | func (c *rpcCodec) read(obj interface{}) (err error) { 97 | if c.cls { 98 | return io.EOF 99 | } 100 | //If nil is passed in, we should still attempt to read content to nowhere. 101 | if obj == nil { 102 | var obj2 interface{} 103 | return c.dec.Decode(&obj2) 104 | } 105 | return c.dec.Decode(obj) 106 | } 107 | 108 | func (c *rpcCodec) Close() error { 109 | if c.cls { 110 | return io.EOF 111 | } 112 | c.cls = true 113 | return c.rwc.Close() 114 | } 115 | 116 | func (c *rpcCodec) ReadResponseBody(body interface{}) error { 117 | return c.read(body) 118 | } 119 | 120 | // ------------------------------------- 121 | 122 | type goRpcCodec struct { 123 | rpcCodec 124 | } 125 | 126 | func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error { 127 | // Must protect for concurrent access as per API 128 | c.mu.Lock() 129 | defer c.mu.Unlock() 130 | return c.write(r, body, true, true) 131 | } 132 | 133 | func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error { 134 | c.mu.Lock() 135 | defer c.mu.Unlock() 136 | return c.write(r, body, true, true) 137 | } 138 | 139 | func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error { 140 | return c.read(r) 141 | } 142 | 143 | func (c *goRpcCodec) ReadRequestHeader(r *rpc.Request) error { 144 | return c.read(r) 145 | } 146 | 147 | func (c *goRpcCodec) ReadRequestBody(body interface{}) error { 148 | return c.read(body) 149 | } 150 | 151 | // ------------------------------------- 152 | 153 | // goRpc is the implementation of Rpc that uses the communication protocol 154 | // as defined in net/rpc package. 155 | type goRpc struct{} 156 | 157 | // GoRpc implements Rpc using the communication protocol defined in net/rpc package. 158 | // Its methods (ServerCodec and ClientCodec) return values that implement RpcCodecBuffered. 159 | var GoRpc goRpc 160 | 161 | func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec { 162 | return &goRpcCodec{newRPCCodec(conn, h)} 163 | } 164 | 165 | func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec { 166 | return &goRpcCodec{newRPCCodec(conn, h)} 167 | } 168 | 169 | var _ RpcCodecBuffered = (*rpcCodec)(nil) // ensure *rpcCodec implements RpcCodecBuffered 170 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/cenkalti/backoff/exponential.go: -------------------------------------------------------------------------------- 1 | package backoff 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | /* 9 | ExponentialBackOff is an implementation of BackOff that increases the back off 10 | period for each retry attempt using a randomization function that grows exponentially. 11 | 12 | NextBackOff() is calculated using the following formula: 13 | 14 | randomized_interval = 15 | retry_interval * (random value in range [1 - randomization_factor, 1 + randomization_factor]) 16 | 17 | In other words NextBackOff() will range between the randomization factor 18 | percentage below and above the retry interval. For example, using 2 seconds as the base retry 19 | interval and 0.5 as the randomization factor, the actual back off period used in the next retry 20 | attempt will be between 1 and 3 seconds. 21 | 22 | Note: max_interval caps the retry_interval and not the randomized_interval. 23 | 24 | If the time elapsed since an ExponentialBackOff instance is created goes past the 25 | max_elapsed_time then the method NextBackOff() starts returning backoff.Stop. 26 | The elapsed time can be reset by calling Reset(). 27 | 28 | Example: The default retry_interval is .5 seconds, default randomization_factor is 0.5, default 29 | multiplier is 1.5 and the default max_interval is 1 minute. For 10 tries the sequence will be 30 | (values in seconds) and assuming we go over the max_elapsed_time on the 10th try: 31 | 32 | request# retry_interval randomized_interval 33 | 34 | 1 0.5 [0.25, 0.75] 35 | 2 0.75 [0.375, 1.125] 36 | 3 1.125 [0.562, 1.687] 37 | 4 1.687 [0.8435, 2.53] 38 | 5 2.53 [1.265, 3.795] 39 | 6 3.795 [1.897, 5.692] 40 | 7 5.692 [2.846, 8.538] 41 | 8 8.538 [4.269, 12.807] 42 | 9 12.807 [6.403, 19.210] 43 | 10 19.210 backoff.Stop 44 | 45 | Implementation is not thread-safe. 46 | */ 47 | type ExponentialBackOff struct { 48 | InitialInterval time.Duration 49 | RandomizationFactor float64 50 | Multiplier float64 51 | MaxInterval time.Duration 52 | // After MaxElapsedTime the ExponentialBackOff stops. 53 | // It never stops if MaxElapsedTime == 0. 54 | MaxElapsedTime time.Duration 55 | Clock Clock 56 | 57 | currentInterval time.Duration 58 | startTime time.Time 59 | } 60 | 61 | // Clock is an interface that returns current time for BackOff. 62 | type Clock interface { 63 | Now() time.Time 64 | } 65 | 66 | // Default values for ExponentialBackOff. 67 | const ( 68 | DefaultInitialInterval = 500 * time.Millisecond 69 | DefaultRandomizationFactor = 0.5 70 | DefaultMultiplier = 1.5 71 | DefaultMaxInterval = 60 * time.Second 72 | DefaultMaxElapsedTime = 15 * time.Minute 73 | ) 74 | 75 | // NewExponentialBackOff creates an instance of ExponentialBackOff using default values. 76 | func NewExponentialBackOff() *ExponentialBackOff { 77 | return &ExponentialBackOff{ 78 | InitialInterval: DefaultInitialInterval, 79 | RandomizationFactor: DefaultRandomizationFactor, 80 | Multiplier: DefaultMultiplier, 81 | MaxInterval: DefaultMaxInterval, 82 | MaxElapsedTime: DefaultMaxElapsedTime, 83 | Clock: SystemClock, 84 | } 85 | } 86 | 87 | type systemClock struct{} 88 | 89 | func (t systemClock) Now() time.Time { 90 | return time.Now() 91 | } 92 | 93 | // SystemClock implements Clock interface that uses time.Now(). 94 | var SystemClock = systemClock{} 95 | 96 | // Reset the interval back to the initial retry interval and restarts the timer. 97 | func (b *ExponentialBackOff) Reset() { 98 | b.currentInterval = b.InitialInterval 99 | b.startTime = b.Clock.Now() 100 | } 101 | 102 | // NextBackOff calculates the next back off interval using the formula: 103 | // randomized_interval = retry_interval +/- (randomization_factor * retry_interval) 104 | func (b *ExponentialBackOff) NextBackOff() time.Duration { 105 | // Make sure we have not gone over the maximum elapsed time. 106 | if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime { 107 | return Stop 108 | } 109 | defer b.incrementCurrentInterval() 110 | return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) 111 | } 112 | 113 | // GetElapsedTime returns the elapsed time since an ExponentialBackOff instance 114 | // is created and is reset when Reset() is called. 115 | // 116 | // The elapsed time is computed using time.Now().UnixNano(). 117 | func (b *ExponentialBackOff) GetElapsedTime() time.Duration { 118 | return b.Clock.Now().Sub(b.startTime) 119 | } 120 | 121 | // Increments the current interval by multiplying it with the multiplier. 122 | func (b *ExponentialBackOff) incrementCurrentInterval() { 123 | // Check for overflow, if overflow is detected set the current interval to the max interval. 124 | if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { 125 | b.currentInterval = b.MaxInterval 126 | } else { 127 | b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) 128 | } 129 | } 130 | 131 | // Returns a random value from the interval: 132 | // [randomizationFactor * currentInterval, randomizationFactor * currentInterval]. 133 | func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { 134 | var delta = randomizationFactor * float64(currentInterval) 135 | var minInterval = float64(currentInterval) - delta 136 | var maxInterval = float64(currentInterval) + delta 137 | // Get a random value from the range [minInterval, maxInterval]. 138 | // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then 139 | // we want a 33% chance for selecting either 1, 2 or 3. 140 | return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) 141 | } 142 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/README.md: -------------------------------------------------------------------------------- 1 | # Codec 2 | 3 | High Performance, Feature-Rich Idiomatic Go codec/encoding library for 4 | binc, msgpack, cbor, json. 5 | 6 | Supported Serialization formats are: 7 | 8 | - msgpack: https://github.com/msgpack/msgpack 9 | - binc: http://github.com/ugorji/binc 10 | - cbor: http://cbor.io http://tools.ietf.org/html/rfc7049 11 | - json: http://json.org http://tools.ietf.org/html/rfc7159 12 | - simple: 13 | 14 | To install: 15 | 16 | go get github.com/ugorji/go/codec 17 | 18 | This package understands the `unsafe` tag, to allow using unsafe semantics: 19 | 20 | - When decoding into a struct, you need to read the field name as a string 21 | so you can find the struct field it is mapped to. 22 | Using `unsafe` will bypass the allocation and copying overhead of `[]byte->string` conversion. 23 | 24 | To use it, you must pass the `unsafe` tag during install: 25 | 26 | ``` 27 | go install -tags=unsafe github.com/ugorji/go/codec 28 | ``` 29 | 30 | Online documentation: http://godoc.org/github.com/ugorji/go/codec 31 | Detailed Usage/How-to Primer: http://ugorji.net/blog/go-codec-primer 32 | 33 | The idiomatic Go support is as seen in other encoding packages in 34 | the standard library (ie json, xml, gob, etc). 35 | 36 | Rich Feature Set includes: 37 | 38 | - Simple but extremely powerful and feature-rich API 39 | - Very High Performance. 40 | Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X. 41 | - Multiple conversions: 42 | Package coerces types where appropriate 43 | e.g. decode an int in the stream into a float, etc. 44 | - Corner Cases: 45 | Overflows, nil maps/slices, nil values in streams are handled correctly 46 | - Standard field renaming via tags 47 | - Support for omitting empty fields during an encoding 48 | - Encoding from any value and decoding into pointer to any value 49 | (struct, slice, map, primitives, pointers, interface{}, etc) 50 | - Extensions to support efficient encoding/decoding of any named types 51 | - Support encoding.(Binary|Text)(M|Unm)arshaler interfaces 52 | - Decoding without a schema (into a interface{}). 53 | Includes Options to configure what specific map or slice type to use 54 | when decoding an encoded list or map into a nil interface{} 55 | - Encode a struct as an array, and decode struct from an array in the data stream 56 | - Comprehensive support for anonymous fields 57 | - Fast (no-reflection) encoding/decoding of common maps and slices 58 | - Code-generation for faster performance. 59 | - Support binary (e.g. messagepack, cbor) and text (e.g. json) formats 60 | - Support indefinite-length formats to enable true streaming 61 | (for formats which support it e.g. json, cbor) 62 | - Support canonical encoding, where a value is ALWAYS encoded as same sequence of bytes. 63 | This mostly applies to maps, where iteration order is non-deterministic. 64 | - NIL in data stream decoded as zero value 65 | - Never silently skip data when decoding. 66 | User decides whether to return an error or silently skip data when keys or indexes 67 | in the data stream do not map to fields in the struct. 68 | - Encode/Decode from/to chan types (for iterative streaming support) 69 | - Drop-in replacement for encoding/json. `json:` key in struct tag supported. 70 | - Provides a RPC Server and Client Codec for net/rpc communication protocol. 71 | - Handle unique idiosynchracies of codecs e.g. 72 | - For messagepack, configure how ambiguities in handling raw bytes are resolved 73 | - For messagepack, provide rpc server/client codec to support 74 | msgpack-rpc protocol defined at: 75 | https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md 76 | 77 | ## Extension Support 78 | 79 | Users can register a function to handle the encoding or decoding of 80 | their custom types. 81 | 82 | There are no restrictions on what the custom type can be. Some examples: 83 | 84 | type BisSet []int 85 | type BitSet64 uint64 86 | type UUID string 87 | type MyStructWithUnexportedFields struct { a int; b bool; c []int; } 88 | type GifImage struct { ... } 89 | 90 | As an illustration, MyStructWithUnexportedFields would normally be 91 | encoded as an empty map because it has no exported fields, while UUID 92 | would be encoded as a string. However, with extension support, you can 93 | encode any of these however you like. 94 | 95 | ## RPC 96 | 97 | RPC Client and Server Codecs are implemented, so the codecs can be used 98 | with the standard net/rpc package. 99 | 100 | ## Usage 101 | 102 | Typical usage model: 103 | 104 | // create and configure Handle 105 | var ( 106 | bh codec.BincHandle 107 | mh codec.MsgpackHandle 108 | ch codec.CborHandle 109 | ) 110 | 111 | mh.MapType = reflect.TypeOf(map[string]interface{}(nil)) 112 | 113 | // configure extensions 114 | // e.g. for msgpack, define functions and enable Time support for tag 1 115 | // mh.SetExt(reflect.TypeOf(time.Time{}), 1, myExt) 116 | 117 | // create and use decoder/encoder 118 | var ( 119 | r io.Reader 120 | w io.Writer 121 | b []byte 122 | h = &bh // or mh to use msgpack 123 | ) 124 | 125 | dec = codec.NewDecoder(r, h) 126 | dec = codec.NewDecoderBytes(b, h) 127 | err = dec.Decode(&v) 128 | 129 | enc = codec.NewEncoder(w, h) 130 | enc = codec.NewEncoderBytes(&b, h) 131 | err = enc.Encode(v) 132 | 133 | //RPC Server 134 | go func() { 135 | for { 136 | conn, err := listener.Accept() 137 | rpcCodec := codec.GoRpc.ServerCodec(conn, h) 138 | //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h) 139 | rpc.ServeCodec(rpcCodec) 140 | } 141 | }() 142 | 143 | //RPC Communication (client side) 144 | conn, err = net.Dial("tcp", "localhost:5555") 145 | rpcCodec := codec.GoRpc.ClientCodec(conn, h) 146 | //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h) 147 | client := rpc.NewClientWithCodec(rpcCodec) 148 | 149 | -------------------------------------------------------------------------------- /etcdenv/context.go: -------------------------------------------------------------------------------- 1 | package etcdenv 2 | 3 | import ( 4 | "errors" 5 | "os" 6 | "strings" 7 | "time" 8 | 9 | "github.com/cenkalti/backoff" 10 | "github.com/coreos/go-etcd/etcd" 11 | "github.com/upfluence/goutils/log" 12 | ) 13 | 14 | type Context struct { 15 | Namespaces []string 16 | Runner *Runner 17 | ExitChan chan bool 18 | ShutdownBehaviour string 19 | WatchedKeys []string 20 | CurrentEnv map[string]string 21 | maxRetry int 22 | etcdClient *etcd.Client 23 | } 24 | 25 | func NewContext(namespaces []string, endpoints, command []string, 26 | shutdownBehaviour string, watchedKeys []string, username string, password string) (*Context, error) { 27 | 28 | if shutdownBehaviour != "keepalive" && shutdownBehaviour != "restart" && 29 | shutdownBehaviour != "exit" { 30 | return nil, 31 | errors.New( 32 | "Choose a correct shutdown behaviour : keepalive | exit | restart", 33 | ) 34 | } 35 | 36 | etcdClient := etcd.NewClient(endpoints) 37 | 38 | if username != "" && password != "" { 39 | etcdClient.SetCredentials(username, password) 40 | } 41 | 42 | return &Context{ 43 | Namespaces: namespaces, 44 | Runner: NewRunner(command), 45 | etcdClient: etcdClient, 46 | ShutdownBehaviour: shutdownBehaviour, 47 | ExitChan: make(chan bool), 48 | WatchedKeys: watchedKeys, 49 | CurrentEnv: make(map[string]string), 50 | maxRetry: 3, 51 | }, nil 52 | } 53 | 54 | func (ctx *Context) escapeNamespace(key string) string { 55 | for _, namespace := range ctx.Namespaces { 56 | if strings.HasPrefix(key, namespace) { 57 | key = strings.TrimPrefix(key, namespace) 58 | break 59 | } 60 | } 61 | 62 | return strings.TrimPrefix(key, "/") 63 | } 64 | 65 | func (ctx *Context) fetchEtcdNamespaceVariables(namespace string, currentRetry int, b *backoff.ExponentialBackOff) map[string]string { 66 | result := make(map[string]string) 67 | 68 | response, err := ctx.etcdClient.Get(namespace, false, false) 69 | 70 | if err != nil { 71 | log.Errorf("etcd fetching error: %s", err.Error()) 72 | 73 | if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == etcd.ErrCodeEtcdNotReachable { 74 | log.Error("Can't join the etcd server, fallback to the env variables") 75 | } else if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == ErrKeyNotFound { 76 | log.Error("The namespace does not exist, fallback to the env variables") 77 | } 78 | 79 | if currentRetry < ctx.maxRetry { 80 | log.Info("retry fetching variables") 81 | t := b.NextBackOff() 82 | time.Sleep(t) 83 | return ctx.fetchEtcdNamespaceVariables(namespace, currentRetry+1, b) 84 | } else { 85 | return result 86 | } 87 | 88 | } 89 | 90 | for _, node := range response.Node.Nodes { 91 | key := ctx.escapeNamespace(node.Key) 92 | if _, ok := result[key]; !ok { 93 | result[key] = node.Value 94 | } 95 | } 96 | 97 | return result 98 | } 99 | 100 | func (ctx *Context) fetchEtcdVariables() map[string]string { 101 | result := make(map[string]string) 102 | 103 | b := backoff.NewExponentialBackOff() 104 | 105 | for _, namespace := range ctx.Namespaces { 106 | b.Reset() 107 | 108 | for key, value := range ctx.fetchEtcdNamespaceVariables(namespace, 0, b) { 109 | if _, ok := result[key]; !ok { 110 | result[key] = value 111 | } 112 | } 113 | } 114 | 115 | return result 116 | } 117 | 118 | func (ctx *Context) shouldRestart(envVar, value string) bool { 119 | if v, ok := ctx.CurrentEnv[envVar]; ok && v == value { 120 | return false 121 | } 122 | 123 | if len(ctx.WatchedKeys) == 0 || containsString(ctx.WatchedKeys, envVar) { 124 | return true 125 | } 126 | 127 | return false 128 | } 129 | 130 | func (ctx *Context) Run() { 131 | ctx.CurrentEnv = ctx.fetchEtcdVariables() 132 | ctx.Runner.Start(ctx.CurrentEnv) 133 | 134 | responseChan := make(chan *etcd.Response) 135 | processExitChan := make(chan int) 136 | 137 | for _, namespace := range ctx.Namespaces { 138 | go func(namespace string) { 139 | var t time.Duration 140 | b := backoff.NewExponentialBackOff() 141 | b.Reset() 142 | 143 | for { 144 | resp, err := ctx.etcdClient.Watch(namespace, 0, true, nil, ctx.ExitChan) 145 | 146 | if err != nil { 147 | log.Errorf("etcd fetching error: %s", err.Error()) 148 | 149 | if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == etcd.ErrCodeEtcdNotReachable { 150 | t = b.NextBackOff() 151 | log.Noticef("Can't join the etcd server, wait %v", t) 152 | time.Sleep(t) 153 | } 154 | 155 | if t == backoff.Stop { 156 | return 157 | } else { 158 | continue 159 | } 160 | } 161 | 162 | log.Infof("%s key changed", resp.Node.Key) 163 | 164 | if ctx.shouldRestart(ctx.escapeNamespace(resp.Node.Key), resp.Node.Value) { 165 | responseChan <- resp 166 | } 167 | } 168 | }(namespace) 169 | } 170 | 171 | go ctx.Runner.WatchProcess(processExitChan) 172 | 173 | for { 174 | select { 175 | case <-responseChan: 176 | log.Notice("Environment changed, restarting child process..") 177 | ctx.CurrentEnv = ctx.fetchEtcdVariables() 178 | ctx.Runner.Restart(ctx.CurrentEnv) 179 | log.Notice("Process restarted") 180 | case <-ctx.ExitChan: 181 | log.Notice("Asking the runner to stop") 182 | ctx.Runner.Stop() 183 | os.Stderr.Sync() 184 | log.Notice("Runner stopped") 185 | case status := <-processExitChan: 186 | log.Noticef("Child process exited with status %d", status) 187 | if ctx.ShutdownBehaviour == "exit" { 188 | ctx.ExitChan <- true 189 | os.Stderr.Sync() 190 | os.Exit(status) 191 | } else if ctx.ShutdownBehaviour == "restart" { 192 | ctx.CurrentEnv = ctx.fetchEtcdVariables() 193 | ctx.Runner.Restart(ctx.CurrentEnv) 194 | go ctx.Runner.WatchProcess(processExitChan) 195 | log.Notice("Process restarted") 196 | } 197 | } 198 | } 199 | } 200 | 201 | func containsString(keys []string, item string) bool { 202 | for _, elt := range keys { 203 | if elt == item { 204 | return true 205 | } 206 | } 207 | 208 | return false 209 | } 210 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/0doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 3 | 4 | /* 5 | High Performance, Feature-Rich Idiomatic Go codec/encoding library for 6 | binc, msgpack, cbor, json. 7 | 8 | Supported Serialization formats are: 9 | 10 | - msgpack: https://github.com/msgpack/msgpack 11 | - binc: http://github.com/ugorji/binc 12 | - cbor: http://cbor.io http://tools.ietf.org/html/rfc7049 13 | - json: http://json.org http://tools.ietf.org/html/rfc7159 14 | - simple: 15 | 16 | To install: 17 | 18 | go get github.com/ugorji/go/codec 19 | 20 | This package understands the 'unsafe' tag, to allow using unsafe semantics: 21 | 22 | - When decoding into a struct, you need to read the field name as a string 23 | so you can find the struct field it is mapped to. 24 | Using `unsafe` will bypass the allocation and copying overhead of []byte->string conversion. 25 | 26 | To install using unsafe, pass the 'unsafe' tag: 27 | 28 | go get -tags=unsafe github.com/ugorji/go/codec 29 | 30 | For detailed usage information, read the primer at http://ugorji.net/blog/go-codec-primer . 31 | 32 | The idiomatic Go support is as seen in other encoding packages in 33 | the standard library (ie json, xml, gob, etc). 34 | 35 | Rich Feature Set includes: 36 | 37 | - Simple but extremely powerful and feature-rich API 38 | - Very High Performance. 39 | Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X. 40 | - Multiple conversions: 41 | Package coerces types where appropriate 42 | e.g. decode an int in the stream into a float, etc. 43 | - Corner Cases: 44 | Overflows, nil maps/slices, nil values in streams are handled correctly 45 | - Standard field renaming via tags 46 | - Support for omitting empty fields during an encoding 47 | - Encoding from any value and decoding into pointer to any value 48 | (struct, slice, map, primitives, pointers, interface{}, etc) 49 | - Extensions to support efficient encoding/decoding of any named types 50 | - Support encoding.(Binary|Text)(M|Unm)arshaler interfaces 51 | - Decoding without a schema (into a interface{}). 52 | Includes Options to configure what specific map or slice type to use 53 | when decoding an encoded list or map into a nil interface{} 54 | - Encode a struct as an array, and decode struct from an array in the data stream 55 | - Comprehensive support for anonymous fields 56 | - Fast (no-reflection) encoding/decoding of common maps and slices 57 | - Code-generation for faster performance. 58 | - Support binary (e.g. messagepack, cbor) and text (e.g. json) formats 59 | - Support indefinite-length formats to enable true streaming 60 | (for formats which support it e.g. json, cbor) 61 | - Support canonical encoding, where a value is ALWAYS encoded as same sequence of bytes. 62 | This mostly applies to maps, where iteration order is non-deterministic. 63 | - NIL in data stream decoded as zero value 64 | - Never silently skip data when decoding. 65 | User decides whether to return an error or silently skip data when keys or indexes 66 | in the data stream do not map to fields in the struct. 67 | - Encode/Decode from/to chan types (for iterative streaming support) 68 | - Drop-in replacement for encoding/json. `json:` key in struct tag supported. 69 | - Provides a RPC Server and Client Codec for net/rpc communication protocol. 70 | - Handle unique idiosynchracies of codecs e.g. 71 | - For messagepack, configure how ambiguities in handling raw bytes are resolved 72 | - For messagepack, provide rpc server/client codec to support 73 | msgpack-rpc protocol defined at: 74 | https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md 75 | 76 | Extension Support 77 | 78 | Users can register a function to handle the encoding or decoding of 79 | their custom types. 80 | 81 | There are no restrictions on what the custom type can be. Some examples: 82 | 83 | type BisSet []int 84 | type BitSet64 uint64 85 | type UUID string 86 | type MyStructWithUnexportedFields struct { a int; b bool; c []int; } 87 | type GifImage struct { ... } 88 | 89 | As an illustration, MyStructWithUnexportedFields would normally be 90 | encoded as an empty map because it has no exported fields, while UUID 91 | would be encoded as a string. However, with extension support, you can 92 | encode any of these however you like. 93 | 94 | RPC 95 | 96 | RPC Client and Server Codecs are implemented, so the codecs can be used 97 | with the standard net/rpc package. 98 | 99 | Usage 100 | 101 | Typical usage model: 102 | 103 | // create and configure Handle 104 | var ( 105 | bh codec.BincHandle 106 | mh codec.MsgpackHandle 107 | ch codec.CborHandle 108 | ) 109 | 110 | mh.MapType = reflect.TypeOf(map[string]interface{}(nil)) 111 | 112 | // configure extensions 113 | // e.g. for msgpack, define functions and enable Time support for tag 1 114 | // mh.SetExt(reflect.TypeOf(time.Time{}), 1, myExt) 115 | 116 | // create and use decoder/encoder 117 | var ( 118 | r io.Reader 119 | w io.Writer 120 | b []byte 121 | h = &bh // or mh to use msgpack 122 | ) 123 | 124 | dec = codec.NewDecoder(r, h) 125 | dec = codec.NewDecoderBytes(b, h) 126 | err = dec.Decode(&v) 127 | 128 | enc = codec.NewEncoder(w, h) 129 | enc = codec.NewEncoderBytes(&b, h) 130 | err = enc.Encode(v) 131 | 132 | //RPC Server 133 | go func() { 134 | for { 135 | conn, err := listener.Accept() 136 | rpcCodec := codec.GoRpc.ServerCodec(conn, h) 137 | //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h) 138 | rpc.ServeCodec(rpcCodec) 139 | } 140 | }() 141 | 142 | //RPC Communication (client side) 143 | conn, err = net.Dial("tcp", "localhost:5555") 144 | rpcCodec := codec.GoRpc.ClientCodec(conn, h) 145 | //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h) 146 | client := rpc.NewClientWithCodec(rpcCodec) 147 | 148 | */ 149 | package codec 150 | 151 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/noop.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 3 | 4 | package codec 5 | 6 | import ( 7 | "math/rand" 8 | "time" 9 | ) 10 | 11 | // NoopHandle returns a no-op handle. It basically does nothing. 12 | // It is only useful for benchmarking, as it gives an idea of the 13 | // overhead from the codec framework. 14 | // LIBRARY USERS: *** DO NOT USE *** 15 | func NoopHandle(slen int) *noopHandle { 16 | h := noopHandle{} 17 | h.rand = rand.New(rand.NewSource(time.Now().UnixNano())) 18 | h.B = make([][]byte, slen) 19 | h.S = make([]string, slen) 20 | for i := 0; i < len(h.S); i++ { 21 | b := make([]byte, i+1) 22 | for j := 0; j < len(b); j++ { 23 | b[j] = 'a' + byte(i) 24 | } 25 | h.B[i] = b 26 | h.S[i] = string(b) 27 | } 28 | return &h 29 | } 30 | 31 | // noopHandle does nothing. 32 | // It is used to simulate the overhead of the codec framework. 33 | type noopHandle struct { 34 | BasicHandle 35 | binaryEncodingType 36 | noopDrv // noopDrv is unexported here, so we can get a copy of it when needed. 37 | } 38 | 39 | type noopDrv struct { 40 | i int 41 | S []string 42 | B [][]byte 43 | mk bool // are we about to read a map key? 44 | ct valueType // last request for IsContainerType. 45 | cb bool // last response for IsContainerType. 46 | rand *rand.Rand 47 | } 48 | 49 | func (h *noopDrv) r(v int) int { return h.rand.Intn(v) } 50 | func (h *noopDrv) m(v int) int { h.i++; return h.i % v } 51 | 52 | func (h *noopDrv) newEncDriver(_ *Encoder) encDriver { return h } 53 | func (h *noopDrv) newDecDriver(_ *Decoder) decDriver { return h } 54 | 55 | // --- encDriver 56 | 57 | func (h *noopDrv) EncodeBuiltin(rt uintptr, v interface{}) {} 58 | func (h *noopDrv) EncodeNil() {} 59 | func (h *noopDrv) EncodeInt(i int64) {} 60 | func (h *noopDrv) EncodeUint(i uint64) {} 61 | func (h *noopDrv) EncodeBool(b bool) {} 62 | func (h *noopDrv) EncodeFloat32(f float32) {} 63 | func (h *noopDrv) EncodeFloat64(f float64) {} 64 | func (h *noopDrv) EncodeRawExt(re *RawExt, e *Encoder) {} 65 | func (h *noopDrv) EncodeArrayStart(length int) {} 66 | func (h *noopDrv) EncodeArrayEnd() {} 67 | func (h *noopDrv) EncodeArrayEntrySeparator() {} 68 | func (h *noopDrv) EncodeMapStart(length int) {} 69 | func (h *noopDrv) EncodeMapEnd() {} 70 | func (h *noopDrv) EncodeMapEntrySeparator() {} 71 | func (h *noopDrv) EncodeMapKVSeparator() {} 72 | func (h *noopDrv) EncodeString(c charEncoding, v string) {} 73 | func (h *noopDrv) EncodeSymbol(v string) {} 74 | func (h *noopDrv) EncodeStringBytes(c charEncoding, v []byte) {} 75 | 76 | func (h *noopDrv) EncodeExt(rv interface{}, xtag uint64, ext Ext, e *Encoder) {} 77 | 78 | // ---- decDriver 79 | func (h *noopDrv) initReadNext() {} 80 | func (h *noopDrv) CheckBreak() bool { return false } 81 | func (h *noopDrv) IsBuiltinType(rt uintptr) bool { return false } 82 | func (h *noopDrv) DecodeBuiltin(rt uintptr, v interface{}) {} 83 | func (h *noopDrv) DecodeInt(bitsize uint8) (i int64) { return int64(h.m(15)) } 84 | func (h *noopDrv) DecodeUint(bitsize uint8) (ui uint64) { return uint64(h.m(35)) } 85 | func (h *noopDrv) DecodeFloat(chkOverflow32 bool) (f float64) { return float64(h.m(95)) } 86 | func (h *noopDrv) DecodeBool() (b bool) { return h.m(2) == 0 } 87 | func (h *noopDrv) DecodeString() (s string) { return h.S[h.m(8)] } 88 | 89 | // func (h *noopDrv) DecodeStringAsBytes(bs []byte) []byte { return h.DecodeBytes(bs) } 90 | 91 | func (h *noopDrv) DecodeBytes(bs []byte, isstring, zerocopy bool) []byte { return h.B[h.m(len(h.B))] } 92 | 93 | func (h *noopDrv) ReadMapEnd() { h.mk = false } 94 | func (h *noopDrv) ReadArrayEnd() {} 95 | func (h *noopDrv) ReadArrayEntrySeparator() {} 96 | func (h *noopDrv) ReadMapEntrySeparator() { h.mk = true } 97 | func (h *noopDrv) ReadMapKVSeparator() { h.mk = false } 98 | 99 | // toggle map/slice 100 | func (h *noopDrv) ReadMapStart() int { h.mk = true; return h.m(10) } 101 | func (h *noopDrv) ReadArrayStart() int { return h.m(10) } 102 | 103 | func (h *noopDrv) IsContainerType(vt valueType) bool { 104 | // return h.m(2) == 0 105 | // handle kStruct 106 | if h.ct == valueTypeMap && vt == valueTypeArray || h.ct == valueTypeArray && vt == valueTypeMap { 107 | h.cb = !h.cb 108 | h.ct = vt 109 | return h.cb 110 | } 111 | // go in a loop and check it. 112 | h.ct = vt 113 | h.cb = h.m(7) == 0 114 | return h.cb 115 | } 116 | func (h *noopDrv) TryDecodeAsNil() bool { 117 | if h.mk { 118 | return false 119 | } else { 120 | return h.m(8) == 0 121 | } 122 | } 123 | func (h *noopDrv) DecodeExt(rv interface{}, xtag uint64, ext Ext) uint64 { 124 | return 0 125 | } 126 | 127 | func (h *noopDrv) DecodeNaked() (v interface{}, vt valueType, decodeFurther bool) { 128 | // use h.r (random) not h.m() because h.m() could cause the same value to be given. 129 | var sk int 130 | if h.mk { 131 | // if mapkey, do not support values of nil OR bytes, array, map or rawext 132 | sk = h.r(7) + 1 133 | } else { 134 | sk = h.r(12) 135 | } 136 | switch sk { 137 | case 0: 138 | vt = valueTypeNil 139 | case 1: 140 | vt, v = valueTypeBool, false 141 | case 2: 142 | vt, v = valueTypeBool, true 143 | case 3: 144 | vt, v = valueTypeInt, h.DecodeInt(64) 145 | case 4: 146 | vt, v = valueTypeUint, h.DecodeUint(64) 147 | case 5: 148 | vt, v = valueTypeFloat, h.DecodeFloat(true) 149 | case 6: 150 | vt, v = valueTypeFloat, h.DecodeFloat(false) 151 | case 7: 152 | vt, v = valueTypeString, h.DecodeString() 153 | case 8: 154 | vt, v = valueTypeBytes, h.B[h.m(len(h.B))] 155 | case 9: 156 | vt, decodeFurther = valueTypeArray, true 157 | case 10: 158 | vt, decodeFurther = valueTypeMap, true 159 | default: 160 | vt, v = valueTypeExt, &RawExt{Tag: h.DecodeUint(64), Data: h.B[h.m(len(h.B))]} 161 | } 162 | h.ct = vt 163 | return 164 | } 165 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/prebuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # _needgen is a helper function to tell if we need to generate files for msgp, codecgen. 4 | _needgen() { 5 | local a="$1" 6 | zneedgen=0 7 | if [[ ! -e "$a" ]] 8 | then 9 | zneedgen=1 10 | echo 1 11 | return 0 12 | fi 13 | for i in `ls -1 *.go.tmpl gen.go values_test.go` 14 | do 15 | if [[ "$a" -ot "$i" ]] 16 | then 17 | zneedgen=1 18 | echo 1 19 | return 0 20 | fi 21 | done 22 | echo 0 23 | } 24 | 25 | # _build generates fast-path.go and gen-helper.go. 26 | # 27 | # It is needed because there is some dependency between the generated code 28 | # and the other classes. Consequently, we have to totally remove the 29 | # generated files and put stubs in place, before calling "go run" again 30 | # to recreate them. 31 | _build() { 32 | if ! [[ "${zforce}" == "1" || 33 | "1" == $( _needgen "fast-path.generated.go" ) || 34 | "1" == $( _needgen "gen-helper.generated.go" ) || 35 | "1" == $( _needgen "gen.generated.go" ) || 36 | 1 == 0 ]] 37 | then 38 | return 0 39 | fi 40 | 41 | # echo "Running prebuild" 42 | if [ "${zbak}" == "1" ] 43 | then 44 | # echo "Backing up old generated files" 45 | _zts=`date '+%m%d%Y_%H%M%S'` 46 | _gg=".generated.go" 47 | [ -e "gen-helper${_gg}" ] && mv gen-helper${_gg} gen-helper${_gg}__${_zts}.bak 48 | [ -e "fast-path${_gg}" ] && mv fast-path${_gg} fast-path${_gg}__${_zts}.bak 49 | # [ -e "safe${_gg}" ] && mv safe${_gg} safe${_gg}__${_zts}.bak 50 | # [ -e "unsafe${_gg}" ] && mv unsafe${_gg} unsafe${_gg}__${_zts}.bak 51 | else 52 | rm -f fast-path.generated.go gen.generated.go gen-helper.generated.go *safe.generated.go *_generated_test.go *.generated_ffjson_expose.go 53 | fi 54 | 55 | cat > gen.generated.go <> gen.generated.go < gen-dec-map.go.tmpl 67 | 68 | cat >> gen.generated.go <> gen.generated.go < gen-dec-array.go.tmpl 75 | 76 | cat >> gen.generated.go < fast-path.generated.go < gen-from-tmpl.generated.go < 0 && size > b.maxSize { 92 | for { 93 | headp := b.head 94 | head := (*node)(b.head) 95 | if head.next == nil { 96 | break 97 | } 98 | swapped := atomic.CompareAndSwapPointer( 99 | &b.head, 100 | headp, 101 | unsafe.Pointer(head.next), 102 | ) 103 | if swapped == true { 104 | atomic.AddInt32(&b.size, -1) 105 | break 106 | } 107 | } 108 | } 109 | return nil 110 | } 111 | 112 | // Head returns the oldest record node kept in memory. It can be used to 113 | // iterate over records, one by one, up to the last record. 114 | // 115 | // Note: new records can get added while iterating. Hence the number of records 116 | // iterated over might be larger than the maximum size. 117 | func (b *MemoryBackend) Head() *node { 118 | return (*node)(b.head) 119 | } 120 | 121 | type event int 122 | 123 | const ( 124 | eventFlush event = iota 125 | eventStop 126 | ) 127 | 128 | // ChannelMemoryBackend is very similar to the MemoryBackend, except that it 129 | // internally utilizes a channel. 130 | type ChannelMemoryBackend struct { 131 | maxSize int 132 | size int 133 | incoming chan *Record 134 | events chan event 135 | mu sync.Mutex 136 | running bool 137 | flushWg sync.WaitGroup 138 | stopWg sync.WaitGroup 139 | head, tail *node 140 | } 141 | 142 | // NewChannelMemoryBackend creates a simple in-memory logging backend which 143 | // utilizes a go channel for communication. 144 | // 145 | // Start will automatically be called by this function. 146 | func NewChannelMemoryBackend(size int) *ChannelMemoryBackend { 147 | backend := &ChannelMemoryBackend{ 148 | maxSize: size, 149 | incoming: make(chan *Record, 1024), 150 | events: make(chan event), 151 | } 152 | backend.Start() 153 | return backend 154 | } 155 | 156 | // Start launches the internal goroutine which starts processing data from the 157 | // input channel. 158 | func (b *ChannelMemoryBackend) Start() { 159 | b.mu.Lock() 160 | defer b.mu.Unlock() 161 | 162 | // Launch the goroutine unless it's already running. 163 | if b.running != true { 164 | b.running = true 165 | b.stopWg.Add(1) 166 | go b.process() 167 | } 168 | } 169 | 170 | func (b *ChannelMemoryBackend) process() { 171 | defer b.stopWg.Done() 172 | for { 173 | select { 174 | case rec := <-b.incoming: 175 | b.insertRecord(rec) 176 | case e := <-b.events: 177 | switch e { 178 | case eventStop: 179 | return 180 | case eventFlush: 181 | for len(b.incoming) > 0 { 182 | b.insertRecord(<-b.incoming) 183 | } 184 | b.flushWg.Done() 185 | } 186 | } 187 | } 188 | } 189 | 190 | func (b *ChannelMemoryBackend) insertRecord(rec *Record) { 191 | prev := b.tail 192 | b.tail = &node{Record: rec} 193 | if prev == nil { 194 | b.head = b.tail 195 | } else { 196 | prev.next = b.tail 197 | } 198 | 199 | if b.maxSize > 0 && b.size >= b.maxSize { 200 | b.head = b.head.next 201 | } else { 202 | b.size++ 203 | } 204 | } 205 | 206 | // Flush waits until all records in the buffered channel have been processed. 207 | func (b *ChannelMemoryBackend) Flush() { 208 | b.flushWg.Add(1) 209 | b.events <- eventFlush 210 | b.flushWg.Wait() 211 | } 212 | 213 | // Stop signals the internal goroutine to exit and waits until it have. 214 | func (b *ChannelMemoryBackend) Stop() { 215 | b.mu.Lock() 216 | if b.running == true { 217 | b.running = false 218 | b.events <- eventStop 219 | } 220 | b.mu.Unlock() 221 | b.stopWg.Wait() 222 | } 223 | 224 | // Log implements the Log method required by Backend. 225 | func (b *ChannelMemoryBackend) Log(level Level, calldepth int, rec *Record) error { 226 | b.incoming <- rec 227 | return nil 228 | } 229 | 230 | // Head returns the oldest record node kept in memory. It can be used to 231 | // iterate over records, one by one, up to the last record. 232 | // 233 | // Note: new records can get added while iterating. Hence the number of records 234 | // iterated over might be larger than the maximum size. 235 | func (b *ChannelMemoryBackend) Head() *node { 236 | return b.head 237 | } 238 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/time.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 3 | 4 | package codec 5 | 6 | import ( 7 | "time" 8 | ) 9 | 10 | var ( 11 | timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} 12 | ) 13 | 14 | // EncodeTime encodes a time.Time as a []byte, including 15 | // information on the instant in time and UTC offset. 16 | // 17 | // Format Description 18 | // 19 | // A timestamp is composed of 3 components: 20 | // 21 | // - secs: signed integer representing seconds since unix epoch 22 | // - nsces: unsigned integer representing fractional seconds as a 23 | // nanosecond offset within secs, in the range 0 <= nsecs < 1e9 24 | // - tz: signed integer representing timezone offset in minutes east of UTC, 25 | // and a dst (daylight savings time) flag 26 | // 27 | // When encoding a timestamp, the first byte is the descriptor, which 28 | // defines which components are encoded and how many bytes are used to 29 | // encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it 30 | // is not encoded in the byte array explicitly*. 31 | // 32 | // Descriptor 8 bits are of the form `A B C DDD EE`: 33 | // A: Is secs component encoded? 1 = true 34 | // B: Is nsecs component encoded? 1 = true 35 | // C: Is tz component encoded? 1 = true 36 | // DDD: Number of extra bytes for secs (range 0-7). 37 | // If A = 1, secs encoded in DDD+1 bytes. 38 | // If A = 0, secs is not encoded, and is assumed to be 0. 39 | // If A = 1, then we need at least 1 byte to encode secs. 40 | // DDD says the number of extra bytes beyond that 1. 41 | // E.g. if DDD=0, then secs is represented in 1 byte. 42 | // if DDD=2, then secs is represented in 3 bytes. 43 | // EE: Number of extra bytes for nsecs (range 0-3). 44 | // If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above) 45 | // 46 | // Following the descriptor bytes, subsequent bytes are: 47 | // 48 | // secs component encoded in `DDD + 1` bytes (if A == 1) 49 | // nsecs component encoded in `EE + 1` bytes (if B == 1) 50 | // tz component encoded in 2 bytes (if C == 1) 51 | // 52 | // secs and nsecs components are integers encoded in a BigEndian 53 | // 2-complement encoding format. 54 | // 55 | // tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to 56 | // Least significant bit 0 are described below: 57 | // 58 | // Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes). 59 | // Bit 15 = have\_dst: set to 1 if we set the dst flag. 60 | // Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not. 61 | // Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format. 62 | // 63 | func encodeTime(t time.Time) []byte { 64 | //t := rv.Interface().(time.Time) 65 | tsecs, tnsecs := t.Unix(), t.Nanosecond() 66 | var ( 67 | bd byte 68 | btmp [8]byte 69 | bs [16]byte 70 | i int = 1 71 | ) 72 | l := t.Location() 73 | if l == time.UTC { 74 | l = nil 75 | } 76 | if tsecs != 0 { 77 | bd = bd | 0x80 78 | bigen.PutUint64(btmp[:], uint64(tsecs)) 79 | f := pruneSignExt(btmp[:], tsecs >= 0) 80 | bd = bd | (byte(7-f) << 2) 81 | copy(bs[i:], btmp[f:]) 82 | i = i + (8 - f) 83 | } 84 | if tnsecs != 0 { 85 | bd = bd | 0x40 86 | bigen.PutUint32(btmp[:4], uint32(tnsecs)) 87 | f := pruneSignExt(btmp[:4], true) 88 | bd = bd | byte(3-f) 89 | copy(bs[i:], btmp[f:4]) 90 | i = i + (4 - f) 91 | } 92 | if l != nil { 93 | bd = bd | 0x20 94 | // Note that Go Libs do not give access to dst flag. 95 | _, zoneOffset := t.Zone() 96 | //zoneName, zoneOffset := t.Zone() 97 | zoneOffset /= 60 98 | z := uint16(zoneOffset) 99 | bigen.PutUint16(btmp[:2], z) 100 | // clear dst flags 101 | bs[i] = btmp[0] & 0x3f 102 | bs[i+1] = btmp[1] 103 | i = i + 2 104 | } 105 | bs[0] = bd 106 | return bs[0:i] 107 | } 108 | 109 | // DecodeTime decodes a []byte into a time.Time. 110 | func decodeTime(bs []byte) (tt time.Time, err error) { 111 | bd := bs[0] 112 | var ( 113 | tsec int64 114 | tnsec uint32 115 | tz uint16 116 | i byte = 1 117 | i2 byte 118 | n byte 119 | ) 120 | if bd&(1<<7) != 0 { 121 | var btmp [8]byte 122 | n = ((bd >> 2) & 0x7) + 1 123 | i2 = i + n 124 | copy(btmp[8-n:], bs[i:i2]) 125 | //if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it) 126 | if bs[i]&(1<<7) != 0 { 127 | copy(btmp[0:8-n], bsAll0xff) 128 | //for j,k := byte(0), 8-n; j < k; j++ { btmp[j] = 0xff } 129 | } 130 | i = i2 131 | tsec = int64(bigen.Uint64(btmp[:])) 132 | } 133 | if bd&(1<<6) != 0 { 134 | var btmp [4]byte 135 | n = (bd & 0x3) + 1 136 | i2 = i + n 137 | copy(btmp[4-n:], bs[i:i2]) 138 | i = i2 139 | tnsec = bigen.Uint32(btmp[:]) 140 | } 141 | if bd&(1<<5) == 0 { 142 | tt = time.Unix(tsec, int64(tnsec)).UTC() 143 | return 144 | } 145 | // In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name. 146 | // However, we need name here, so it can be shown when time is printed. 147 | // Zone name is in form: UTC-08:00. 148 | // Note that Go Libs do not give access to dst flag, so we ignore dst bits 149 | 150 | i2 = i + 2 151 | tz = bigen.Uint16(bs[i:i2]) 152 | i = i2 153 | // sign extend sign bit into top 2 MSB (which were dst bits): 154 | if tz&(1<<13) == 0 { // positive 155 | tz = tz & 0x3fff //clear 2 MSBs: dst bits 156 | } else { // negative 157 | tz = tz | 0xc000 //set 2 MSBs: dst bits 158 | //tzname[3] = '-' (TODO: verify. this works here) 159 | } 160 | tzint := int16(tz) 161 | if tzint == 0 { 162 | tt = time.Unix(tsec, int64(tnsec)).UTC() 163 | } else { 164 | // For Go Time, do not use a descriptive timezone. 165 | // It's unnecessary, and makes it harder to do a reflect.DeepEqual. 166 | // The Offset already tells what the offset should be, if not on UTC and unknown zone name. 167 | // var zoneName = timeLocUTCName(tzint) 168 | tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60)) 169 | } 170 | return 171 | } 172 | 173 | func timeLocUTCName(tzint int16) string { 174 | if tzint == 0 { 175 | return "UTC" 176 | } 177 | var tzname = []byte("UTC+00:00") 178 | //tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below. 179 | //tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first 180 | var tzhr, tzmin int16 181 | if tzint < 0 { 182 | tzname[3] = '-' // (TODO: verify. this works here) 183 | tzhr, tzmin = -tzint/60, (-tzint)%60 184 | } else { 185 | tzhr, tzmin = tzint/60, tzint%60 186 | } 187 | tzname[4] = timeDigits[tzhr/10] 188 | tzname[5] = timeDigits[tzhr%10] 189 | tzname[7] = timeDigits[tzmin/10] 190 | tzname[8] = timeDigits[tzmin%10] 191 | return string(tzname) 192 | //return time.FixedZone(string(tzname), int(tzint)*60) 193 | } 194 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/logger.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013, Örjan Persson. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package logging implements a logging infrastructure for Go. It supports 6 | // different logging backends like syslog, file and memory. Multiple backends 7 | // can be utilized with different log levels per backend and logger. 8 | package logging 9 | 10 | import ( 11 | "bytes" 12 | "fmt" 13 | "log" 14 | "os" 15 | "strings" 16 | "sync/atomic" 17 | "time" 18 | ) 19 | 20 | // Redactor is an interface for types that may contain sensitive information 21 | // (like passwords), which shouldn't be printed to the log. The idea was found 22 | // in relog as part of the vitness project. 23 | type Redactor interface { 24 | Redacted() interface{} 25 | } 26 | 27 | // Redact returns a string of * having the same length as s. 28 | func Redact(s string) string { 29 | return strings.Repeat("*", len(s)) 30 | } 31 | 32 | var ( 33 | // Sequence number is incremented and utilized for all log records created. 34 | sequenceNo uint64 35 | 36 | // timeNow is a customizable for testing purposes. 37 | timeNow = time.Now 38 | ) 39 | 40 | // Record represents a log record and contains the timestamp when the record 41 | // was created, an increasing id, filename and line and finally the actual 42 | // formatted log line. 43 | type Record struct { 44 | ID uint64 45 | Time time.Time 46 | Module string 47 | Level Level 48 | Args []interface{} 49 | 50 | // message is kept as a pointer to have shallow copies update this once 51 | // needed. 52 | message *string 53 | fmt *string 54 | formatter Formatter 55 | formatted string 56 | } 57 | 58 | // Formatted returns the formatted log record string. 59 | func (r *Record) Formatted(calldepth int) string { 60 | if r.formatted == "" { 61 | var buf bytes.Buffer 62 | r.formatter.Format(calldepth+1, r, &buf) 63 | r.formatted = buf.String() 64 | } 65 | return r.formatted 66 | } 67 | 68 | // Message returns the log record message. 69 | func (r *Record) Message() string { 70 | if r.message == nil { 71 | // Redact the arguments that implements the Redactor interface 72 | for i, arg := range r.Args { 73 | if redactor, ok := arg.(Redactor); ok == true { 74 | r.Args[i] = redactor.Redacted() 75 | } 76 | } 77 | var buf bytes.Buffer 78 | if r.fmt != nil { 79 | fmt.Fprintf(&buf, *r.fmt, r.Args...) 80 | } else { 81 | // use Fprintln to make sure we always get space between arguments 82 | fmt.Fprintln(&buf, r.Args...) 83 | buf.Truncate(buf.Len() - 1) // strip newline 84 | } 85 | msg := buf.String() 86 | r.message = &msg 87 | } 88 | return *r.message 89 | } 90 | 91 | // Logger is the actual logger which creates log records based on the functions 92 | // called and passes them to the underlying logging backend. 93 | type Logger struct { 94 | Module string 95 | backend LeveledBackend 96 | haveBackend bool 97 | 98 | // ExtraCallDepth can be used to add additional call depth when getting the 99 | // calling function. This is normally used when wrapping a logger. 100 | ExtraCalldepth int 101 | } 102 | 103 | // SetBackend overrides any previously defined backend for this logger. 104 | func (l *Logger) SetBackend(backend LeveledBackend) { 105 | l.backend = backend 106 | l.haveBackend = true 107 | } 108 | 109 | // TODO call NewLogger and remove MustGetLogger? 110 | 111 | // GetLogger creates and returns a Logger object based on the module name. 112 | func GetLogger(module string) (*Logger, error) { 113 | return &Logger{Module: module}, nil 114 | } 115 | 116 | // MustGetLogger is like GetLogger but panics if the logger can't be created. 117 | // It simplifies safe initialization of a global logger for eg. a package. 118 | func MustGetLogger(module string) *Logger { 119 | logger, err := GetLogger(module) 120 | if err != nil { 121 | panic("logger: " + module + ": " + err.Error()) 122 | } 123 | return logger 124 | } 125 | 126 | // Reset restores the internal state of the logging library. 127 | func Reset() { 128 | // TODO make a global Init() method to be less magic? or make it such that 129 | // if there's no backends at all configured, we could use some tricks to 130 | // automatically setup backends based if we have a TTY or not. 131 | sequenceNo = 0 132 | b := SetBackend(NewLogBackend(os.Stderr, "", log.LstdFlags)) 133 | b.SetLevel(DEBUG, "") 134 | SetFormatter(DefaultFormatter) 135 | timeNow = time.Now 136 | } 137 | 138 | // IsEnabledFor returns true if the logger is enabled for the given level. 139 | func (l *Logger) IsEnabledFor(level Level) bool { 140 | return defaultBackend.IsEnabledFor(level, l.Module) 141 | } 142 | 143 | func (l *Logger) log(lvl Level, format *string, args ...interface{}) { 144 | if !l.IsEnabledFor(lvl) { 145 | return 146 | } 147 | 148 | // Create the logging record and pass it in to the backend 149 | record := &Record{ 150 | ID: atomic.AddUint64(&sequenceNo, 1), 151 | Time: timeNow(), 152 | Module: l.Module, 153 | Level: lvl, 154 | fmt: format, 155 | Args: args, 156 | } 157 | 158 | // TODO use channels to fan out the records to all backends? 159 | // TODO in case of errors, do something (tricky) 160 | 161 | // calldepth=2 brings the stack up to the caller of the level 162 | // methods, Info(), Fatal(), etc. 163 | // ExtraCallDepth allows this to be extended further up the stack in case we 164 | // are wrapping these methods, eg. to expose them package level 165 | if l.haveBackend { 166 | l.backend.Log(lvl, 2+l.ExtraCalldepth, record) 167 | return 168 | } 169 | 170 | defaultBackend.Log(lvl, 2+l.ExtraCalldepth, record) 171 | } 172 | 173 | // Fatal is equivalent to l.Critical(fmt.Sprint()) followed by a call to os.Exit(1). 174 | func (l *Logger) Fatal(args ...interface{}) { 175 | l.log(CRITICAL, nil, args...) 176 | os.Exit(1) 177 | } 178 | 179 | // Fatalf is equivalent to l.Critical followed by a call to os.Exit(1). 180 | func (l *Logger) Fatalf(format string, args ...interface{}) { 181 | l.log(CRITICAL, &format, args...) 182 | os.Exit(1) 183 | } 184 | 185 | // Panic is equivalent to l.Critical(fmt.Sprint()) followed by a call to panic(). 186 | func (l *Logger) Panic(args ...interface{}) { 187 | l.log(CRITICAL, nil, args...) 188 | panic(fmt.Sprint(args...)) 189 | } 190 | 191 | // Panicf is equivalent to l.Critical followed by a call to panic(). 192 | func (l *Logger) Panicf(format string, args ...interface{}) { 193 | l.log(CRITICAL, &format, args...) 194 | panic(fmt.Sprintf(format, args...)) 195 | } 196 | 197 | // Critical logs a message using CRITICAL as log level. 198 | func (l *Logger) Critical(args ...interface{}) { 199 | l.log(CRITICAL, nil, args...) 200 | } 201 | 202 | // Criticalf logs a message using CRITICAL as log level. 203 | func (l *Logger) Criticalf(format string, args ...interface{}) { 204 | l.log(CRITICAL, &format, args...) 205 | } 206 | 207 | // Error logs a message using ERROR as log level. 208 | func (l *Logger) Error(args ...interface{}) { 209 | l.log(ERROR, nil, args...) 210 | } 211 | 212 | // Errorf logs a message using ERROR as log level. 213 | func (l *Logger) Errorf(format string, args ...interface{}) { 214 | l.log(ERROR, &format, args...) 215 | } 216 | 217 | // Warning logs a message using WARNING as log level. 218 | func (l *Logger) Warning(args ...interface{}) { 219 | l.log(WARNING, nil, args...) 220 | } 221 | 222 | // Warningf logs a message using WARNING as log level. 223 | func (l *Logger) Warningf(format string, args ...interface{}) { 224 | l.log(WARNING, &format, args...) 225 | } 226 | 227 | // Notice logs a message using NOTICE as log level. 228 | func (l *Logger) Notice(args ...interface{}) { 229 | l.log(NOTICE, nil, args...) 230 | } 231 | 232 | // Noticef logs a message using NOTICE as log level. 233 | func (l *Logger) Noticef(format string, args ...interface{}) { 234 | l.log(NOTICE, &format, args...) 235 | } 236 | 237 | // Info logs a message using INFO as log level. 238 | func (l *Logger) Info(args ...interface{}) { 239 | l.log(INFO, nil, args...) 240 | } 241 | 242 | // Infof logs a message using INFO as log level. 243 | func (l *Logger) Infof(format string, args ...interface{}) { 244 | l.log(INFO, &format, args...) 245 | } 246 | 247 | // Debug logs a message using DEBUG as log level. 248 | func (l *Logger) Debug(args ...interface{}) { 249 | l.log(DEBUG, nil, args...) 250 | } 251 | 252 | // Debugf logs a message using DEBUG as log level. 253 | func (l *Logger) Debugf(format string, args ...interface{}) { 254 | l.log(DEBUG, &format, args...) 255 | } 256 | 257 | func init() { 258 | Reset() 259 | } 260 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/gen.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 3 | 4 | // codecgen generates codec.Selfer implementations for a set of types. 5 | package main 6 | 7 | import ( 8 | "bufio" 9 | "bytes" 10 | "errors" 11 | "flag" 12 | "fmt" 13 | "go/ast" 14 | "go/build" 15 | "go/parser" 16 | "go/token" 17 | "os" 18 | "os/exec" 19 | "path/filepath" 20 | "regexp" 21 | "strconv" 22 | "text/template" 23 | "time" 24 | ) 25 | 26 | const genFrunMainTmpl = `//+build ignore 27 | 28 | package main 29 | {{ if .Types }}import "{{ .ImportPath }}"{{ end }} 30 | func main() { 31 | {{ $.PackageName }}.CodecGenTempWrite{{ .RandString }}() 32 | } 33 | ` 34 | 35 | // const genFrunPkgTmpl = `//+build codecgen 36 | const genFrunPkgTmpl = ` 37 | package {{ $.PackageName }} 38 | 39 | import ( 40 | {{ if not .CodecPkgFiles }}{{ .CodecPkgName }} "{{ .CodecImportPath }}"{{ end }} 41 | {{/* 42 | {{ if .Types }}"{{ .ImportPath }}"{{ end }} 43 | "io" 44 | */}} 45 | "os" 46 | "reflect" 47 | "bytes" 48 | "go/format" 49 | ) 50 | 51 | {{/* This is not used anymore. Remove it. 52 | func write(w io.Writer, s string) { 53 | if _, err := io.WriteString(w, s); err != nil { 54 | panic(err) 55 | } 56 | } 57 | */}} 58 | 59 | func CodecGenTempWrite{{ .RandString }}() { 60 | fout, err := os.Create("{{ .OutFile }}") 61 | if err != nil { 62 | panic(err) 63 | } 64 | defer fout.Close() 65 | var out bytes.Buffer 66 | 67 | var typs []reflect.Type 68 | {{ range $index, $element := .Types }} 69 | var t{{ $index }} {{ . }} 70 | typs = append(typs, reflect.TypeOf(t{{ $index }})) 71 | {{ end }} 72 | {{ if not .CodecPkgFiles }}{{ .CodecPkgName }}.{{ end }}Gen(&out, "{{ .BuildTag }}", "{{ .PackageName }}", {{ .UseUnsafe }}, typs...) 73 | bout, err := format.Source(out.Bytes()) 74 | if err != nil { 75 | fout.Write(out.Bytes()) 76 | panic(err) 77 | } 78 | fout.Write(bout) 79 | } 80 | 81 | ` 82 | 83 | // Generate is given a list of *.go files to parse, and an output file (fout). 84 | // 85 | // It finds all types T in the files, and it creates 2 tmp files (frun). 86 | // - main package file passed to 'go run' 87 | // - package level file which calls *genRunner.Selfer to write Selfer impls for each T. 88 | // We use a package level file so that it can reference unexported types in the package being worked on. 89 | // Tool then executes: "go run __frun__" which creates fout. 90 | // fout contains Codec(En|De)codeSelf implementations for every type T. 91 | // 92 | func Generate(outfile, buildTag, codecPkgPath string, useUnsafe bool, goRunTag string, 93 | regexName *regexp.Regexp, deleteTempFile bool, infiles ...string) (err error) { 94 | // For each file, grab AST, find each type, and write a call to it. 95 | if len(infiles) == 0 { 96 | return 97 | } 98 | if outfile == "" || codecPkgPath == "" { 99 | err = errors.New("outfile and codec package path cannot be blank") 100 | return 101 | } 102 | // We have to parse dir for package, before opening the temp file for writing (else ImportDir fails). 103 | // Also, ImportDir(...) must take an absolute path. 104 | lastdir := filepath.Dir(outfile) 105 | absdir, err := filepath.Abs(lastdir) 106 | if err != nil { 107 | return 108 | } 109 | pkg, err := build.Default.ImportDir(absdir, build.AllowBinary) 110 | if err != nil { 111 | return 112 | } 113 | type tmplT struct { 114 | CodecPkgName string 115 | CodecImportPath string 116 | ImportPath string 117 | OutFile string 118 | PackageName string 119 | RandString string 120 | BuildTag string 121 | Types []string 122 | CodecPkgFiles bool 123 | UseUnsafe bool 124 | } 125 | tv := tmplT{ 126 | CodecPkgName: "codec1978", 127 | OutFile: outfile, 128 | CodecImportPath: codecPkgPath, 129 | BuildTag: buildTag, 130 | UseUnsafe: useUnsafe, 131 | RandString: strconv.FormatInt(time.Now().UnixNano(), 10), 132 | } 133 | tv.ImportPath = pkg.ImportPath 134 | if tv.ImportPath == tv.CodecImportPath { 135 | tv.CodecPkgFiles = true 136 | tv.CodecPkgName = "codec" 137 | } 138 | astfiles := make([]*ast.File, len(infiles)) 139 | for i, infile := range infiles { 140 | if filepath.Dir(infile) != lastdir { 141 | err = errors.New("in files must all be in same directory as outfile") 142 | return 143 | } 144 | fset := token.NewFileSet() 145 | astfiles[i], err = parser.ParseFile(fset, infile, nil, 0) 146 | if err != nil { 147 | return 148 | } 149 | if i == 0 { 150 | tv.PackageName = astfiles[i].Name.Name 151 | if tv.PackageName == "main" { 152 | // codecgen cannot be run on types in the 'main' package. 153 | // A temporary 'main' package must be created, and should reference the fully built 154 | // package containing the types. 155 | // Also, the temporary main package will conflict with the main package which already has a main method. 156 | err = errors.New("codecgen cannot be run on types in the 'main' package") 157 | return 158 | } 159 | } 160 | } 161 | 162 | for _, f := range astfiles { 163 | for _, d := range f.Decls { 164 | if gd, ok := d.(*ast.GenDecl); ok { 165 | for _, dd := range gd.Specs { 166 | if td, ok := dd.(*ast.TypeSpec); ok { 167 | // if len(td.Name.Name) == 0 || td.Name.Name[0] > 'Z' || td.Name.Name[0] < 'A' { 168 | if len(td.Name.Name) == 0 { 169 | continue 170 | } 171 | 172 | // only generate for: 173 | // struct: StructType 174 | // primitives (numbers, bool, string): Ident 175 | // map: MapType 176 | // slice, array: ArrayType 177 | // chan: ChanType 178 | // do not generate: 179 | // FuncType, InterfaceType, StarExpr (ptr), etc 180 | switch td.Type.(type) { 181 | case *ast.StructType, *ast.Ident, *ast.MapType, *ast.ArrayType, *ast.ChanType: 182 | if regexName.FindStringIndex(td.Name.Name) != nil { 183 | tv.Types = append(tv.Types, td.Name.Name) 184 | } 185 | } 186 | } 187 | } 188 | } 189 | } 190 | } 191 | 192 | if len(tv.Types) == 0 { 193 | return 194 | } 195 | 196 | // we cannot use ioutil.TempFile, because we cannot guarantee the file suffix (.go). 197 | // Also, we cannot create file in temp directory, 198 | // because go run will not work (as it needs to see the types here). 199 | // Consequently, create the temp file in the current directory, and remove when done. 200 | 201 | // frun, err = ioutil.TempFile("", "codecgen-") 202 | // frunName := filepath.Join(os.TempDir(), "codecgen-"+strconv.FormatInt(time.Now().UnixNano(), 10)+".go") 203 | 204 | frunMainName := "codecgen-main-" + tv.RandString + ".generated.go" 205 | frunPkgName := "codecgen-pkg-" + tv.RandString + ".generated.go" 206 | if deleteTempFile { 207 | defer os.Remove(frunMainName) 208 | defer os.Remove(frunPkgName) 209 | } 210 | // var frunMain, frunPkg *os.File 211 | if _, err = gen1(frunMainName, genFrunMainTmpl, &tv); err != nil { 212 | return 213 | } 214 | if _, err = gen1(frunPkgName, genFrunPkgTmpl, &tv); err != nil { 215 | return 216 | } 217 | 218 | // remove outfile, so "go run ..." will not think that types in outfile already exist. 219 | os.Remove(outfile) 220 | 221 | // execute go run frun 222 | cmd := exec.Command("go", "run", "-tags="+goRunTag, frunMainName) //, frunPkg.Name()) 223 | var buf bytes.Buffer 224 | cmd.Stdout = &buf 225 | cmd.Stderr = &buf 226 | if err = cmd.Run(); err != nil { 227 | err = fmt.Errorf("error running 'go run %s': %v, console: %s", 228 | frunMainName, err, buf.Bytes()) 229 | return 230 | } 231 | os.Stdout.Write(buf.Bytes()) 232 | return 233 | } 234 | 235 | func gen1(frunName, tmplStr string, tv interface{}) (frun *os.File, err error) { 236 | os.Remove(frunName) 237 | if frun, err = os.Create(frunName); err != nil { 238 | return 239 | } 240 | defer frun.Close() 241 | 242 | t := template.New("") 243 | if t, err = t.Parse(tmplStr); err != nil { 244 | return 245 | } 246 | bw := bufio.NewWriter(frun) 247 | if err = t.Execute(bw, tv); err != nil { 248 | return 249 | } 250 | if err = bw.Flush(); err != nil { 251 | return 252 | } 253 | return 254 | } 255 | 256 | func main() { 257 | o := flag.String("o", "", "out file") 258 | c := flag.String("c", genCodecPath, "codec path") 259 | t := flag.String("t", "", "build tag to put in file") 260 | r := flag.String("r", ".*", "regex for type name to match") 261 | rt := flag.String("rt", "", "tags for go run") 262 | x := flag.Bool("x", false, "keep temp file") 263 | u := flag.Bool("u", false, "Use unsafe, e.g. to avoid unnecessary allocation on []byte->string") 264 | 265 | flag.Parse() 266 | if err := Generate(*o, *t, *c, *u, *rt, 267 | regexp.MustCompile(*r), !*x, flag.Args()...); err != nil { 268 | fmt.Fprintf(os.Stderr, "codecgen error: %v\n", err) 269 | os.Exit(1) 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/gen-helper.go.tmpl: -------------------------------------------------------------------------------- 1 | // //+build ignore 2 | 3 | // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 4 | // Use of this source code is governed by a BSD-style license found in the LICENSE file. 5 | 6 | // ************************************************************ 7 | // DO NOT EDIT. 8 | // THIS FILE IS AUTO-GENERATED from gen-helper.go.tmpl 9 | // ************************************************************ 10 | 11 | package codec 12 | 13 | // This file is used to generate helper code for codecgen. 14 | // The values here i.e. genHelper(En|De)coder are not to be used directly by 15 | // library users. They WILL change continously and without notice. 16 | // 17 | // To help enforce this, we create an unexported type with exported members. 18 | // The only way to get the type is via the one exported type that we control (somewhat). 19 | // 20 | // When static codecs are created for types, they will use this value 21 | // to perform encoding or decoding of primitives or known slice or map types. 22 | 23 | // GenHelperEncoder is exported so that it can be used externally by codecgen. 24 | // Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. 25 | func GenHelperEncoder(e *Encoder) (genHelperEncoder, encDriver) { 26 | return genHelperEncoder{e:e}, e.e 27 | } 28 | 29 | // GenHelperDecoder is exported so that it can be used externally by codecgen. 30 | // Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE. 31 | func GenHelperDecoder(d *Decoder) (genHelperDecoder, decDriver) { 32 | return genHelperDecoder{d:d}, d.d 33 | } 34 | 35 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 36 | type genHelperEncoder struct { 37 | e *Encoder 38 | F fastpathT 39 | } 40 | 41 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 42 | type genHelperDecoder struct { 43 | d *Decoder 44 | F fastpathT 45 | } 46 | 47 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 48 | func (f genHelperEncoder) EncBasicHandle() *BasicHandle { 49 | return f.e.h 50 | } 51 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 52 | func (f genHelperEncoder) EncBinary() bool { 53 | return f.e.be // f.e.hh.isBinaryEncoding() 54 | } 55 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 56 | func (f genHelperEncoder) EncFallback(iv interface{}) { 57 | // println(">>>>>>>>> EncFallback") 58 | f.e.encodeI(iv, false, false) 59 | } 60 | 61 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 62 | func (f genHelperDecoder) DecBasicHandle() *BasicHandle { 63 | return f.d.h 64 | } 65 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 66 | func (f genHelperDecoder) DecBinary() bool { 67 | return f.d.be // f.d.hh.isBinaryEncoding() 68 | } 69 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 70 | func (f genHelperDecoder) DecSwallow() { 71 | f.d.swallow() 72 | } 73 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 74 | func (f genHelperDecoder) DecScratchBuffer() []byte { 75 | return f.d.b[:] 76 | } 77 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 78 | func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) { 79 | // println(">>>>>>>>> DecFallback") 80 | f.d.decodeI(iv, chkPtr, false, false, false) 81 | } 82 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 83 | func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) { 84 | return f.d.decSliceHelperStart() 85 | } 86 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 87 | func (f genHelperDecoder) DecStructFieldNotFound(index int, name string) { 88 | f.d.structFieldNotFound(index, name) 89 | } 90 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 91 | func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) { 92 | f.d.arrayCannotExpand(sliceLen, streamLen) 93 | } 94 | 95 | 96 | {{/* 97 | 98 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 99 | func (f genHelperEncoder) EncDriver() encDriver { 100 | return f.e.e 101 | } 102 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 103 | func (f genHelperDecoder) DecDriver() decDriver { 104 | return f.d.d 105 | } 106 | 107 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 108 | func (f genHelperEncoder) EncNil() { 109 | f.e.e.EncodeNil() 110 | } 111 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 112 | func (f genHelperEncoder) EncBytes(v []byte) { 113 | f.e.e.EncodeStringBytes(c_RAW, v) 114 | } 115 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 116 | func (f genHelperEncoder) EncArrayStart(length int) { 117 | f.e.e.EncodeArrayStart(length) 118 | } 119 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 120 | func (f genHelperEncoder) EncArrayEnd() { 121 | f.e.e.EncodeArrayEnd() 122 | } 123 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 124 | func (f genHelperEncoder) EncArrayEntrySeparator() { 125 | f.e.e.EncodeArrayEntrySeparator() 126 | } 127 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 128 | func (f genHelperEncoder) EncMapStart(length int) { 129 | f.e.e.EncodeMapStart(length) 130 | } 131 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 132 | func (f genHelperEncoder) EncMapEnd() { 133 | f.e.e.EncodeMapEnd() 134 | } 135 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 136 | func (f genHelperEncoder) EncMapEntrySeparator() { 137 | f.e.e.EncodeMapEntrySeparator() 138 | } 139 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 140 | func (f genHelperEncoder) EncMapKVSeparator() { 141 | f.e.e.EncodeMapKVSeparator() 142 | } 143 | 144 | // --------- 145 | 146 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 147 | func (f genHelperDecoder) DecBytes(v *[]byte) { 148 | *v = f.d.d.DecodeBytes(*v) 149 | } 150 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 151 | func (f genHelperDecoder) DecTryNil() bool { 152 | return f.d.d.TryDecodeAsNil() 153 | } 154 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 155 | func (f genHelperDecoder) DecContainerIsNil() (b bool) { 156 | return f.d.d.IsContainerType(valueTypeNil) 157 | } 158 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 159 | func (f genHelperDecoder) DecContainerIsMap() (b bool) { 160 | return f.d.d.IsContainerType(valueTypeMap) 161 | } 162 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 163 | func (f genHelperDecoder) DecContainerIsArray() (b bool) { 164 | return f.d.d.IsContainerType(valueTypeArray) 165 | } 166 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 167 | func (f genHelperDecoder) DecCheckBreak() bool { 168 | return f.d.d.CheckBreak() 169 | } 170 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 171 | func (f genHelperDecoder) DecMapStart() int { 172 | return f.d.d.ReadMapStart() 173 | } 174 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 175 | func (f genHelperDecoder) DecArrayStart() int { 176 | return f.d.d.ReadArrayStart() 177 | } 178 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 179 | func (f genHelperDecoder) DecMapEnd() { 180 | f.d.d.ReadMapEnd() 181 | } 182 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 183 | func (f genHelperDecoder) DecArrayEnd() { 184 | f.d.d.ReadArrayEnd() 185 | } 186 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 187 | func (f genHelperDecoder) DecArrayEntrySeparator() { 188 | f.d.d.ReadArrayEntrySeparator() 189 | } 190 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 191 | func (f genHelperDecoder) DecMapEntrySeparator() { 192 | f.d.d.ReadMapEntrySeparator() 193 | } 194 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 195 | func (f genHelperDecoder) DecMapKVSeparator() { 196 | f.d.d.ReadMapKVSeparator() 197 | } 198 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 199 | func (f genHelperDecoder) ReadStringAsBytes(bs []byte) []byte { 200 | return f.d.d.DecodeStringAsBytes(bs) 201 | } 202 | 203 | 204 | // -- encode calls (primitives) 205 | {{range .Values}}{{if .Primitive }}{{if ne .Primitive "interface{}" }} 206 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 207 | func (f genHelperEncoder) {{ .MethodNamePfx "Enc" true }}(v {{ .Primitive }}) { 208 | ee := f.e.e 209 | {{ encmd .Primitive "v" }} 210 | } 211 | {{ end }}{{ end }}{{ end }} 212 | 213 | // -- decode calls (primitives) 214 | {{range .Values}}{{if .Primitive }}{{if ne .Primitive "interface{}" }} 215 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 216 | func (f genHelperDecoder) {{ .MethodNamePfx "Dec" true }}(vp *{{ .Primitive }}) { 217 | dd := f.d.d 218 | *vp = {{ decmd .Primitive }} 219 | } 220 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 221 | func (f genHelperDecoder) {{ .MethodNamePfx "Read" true }}() (v {{ .Primitive }}) { 222 | dd := f.d.d 223 | v = {{ decmd .Primitive }} 224 | return 225 | } 226 | {{ end }}{{ end }}{{ end }} 227 | 228 | 229 | // -- encode calls (slices/maps) 230 | {{range .Values}}{{if not .Primitive }}{{if .Slice }} 231 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 232 | func (f genHelperEncoder) {{ .MethodNamePfx "Enc" false }}(v []{{ .Elem }}) { {{ else }} 233 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 234 | func (f genHelperEncoder) {{ .MethodNamePfx "Enc" false }}(v map[{{ .MapKey }}]{{ .Elem }}) { {{end}} 235 | f.F.{{ .MethodNamePfx "Enc" false }}V(v, false, f.e) 236 | } 237 | {{ end }}{{ end }} 238 | 239 | // -- decode calls (slices/maps) 240 | {{range .Values}}{{if not .Primitive }} 241 | // FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE* 242 | {{if .Slice }}func (f genHelperDecoder) {{ .MethodNamePfx "Dec" false }}(vp *[]{{ .Elem }}) { 243 | {{else}}func (f genHelperDecoder) {{ .MethodNamePfx "Dec" false }}(vp *map[{{ .MapKey }}]{{ .Elem }}) { {{end}} 244 | v, changed := f.F.{{ .MethodNamePfx "Dec" false }}V(*vp, false, true, f.d) 245 | if changed { 246 | *vp = v 247 | } 248 | } 249 | {{ end }}{{ end }} 250 | */}} 251 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/etcd/requests.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "net/http" 9 | "net/url" 10 | "path" 11 | "strings" 12 | "sync" 13 | "time" 14 | ) 15 | 16 | // Errors introduced by handling requests 17 | var ( 18 | ErrRequestCancelled = errors.New("sending request is cancelled") 19 | ) 20 | 21 | type RawRequest struct { 22 | Method string 23 | RelativePath string 24 | Values url.Values 25 | Cancel <-chan bool 26 | } 27 | 28 | // NewRawRequest returns a new RawRequest 29 | func NewRawRequest(method, relativePath string, values url.Values, cancel <-chan bool) *RawRequest { 30 | return &RawRequest{ 31 | Method: method, 32 | RelativePath: relativePath, 33 | Values: values, 34 | Cancel: cancel, 35 | } 36 | } 37 | 38 | // getCancelable issues a cancelable GET request 39 | func (c *Client) getCancelable(key string, options Options, 40 | cancel <-chan bool) (*RawResponse, error) { 41 | logger.Debugf("get %s [%s]", key, c.cluster.pick()) 42 | p := keyToPath(key) 43 | 44 | str, err := options.toParameters(VALID_GET_OPTIONS) 45 | if err != nil { 46 | return nil, err 47 | } 48 | p += str 49 | 50 | req := NewRawRequest("GET", p, nil, cancel) 51 | resp, err := c.SendRequest(req) 52 | 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | return resp, nil 58 | } 59 | 60 | // get issues a GET request 61 | func (c *Client) get(key string, options Options) (*RawResponse, error) { 62 | return c.getCancelable(key, options, nil) 63 | } 64 | 65 | // put issues a PUT request 66 | func (c *Client) put(key string, value string, ttl uint64, 67 | options Options) (*RawResponse, error) { 68 | 69 | logger.Debugf("put %s, %s, ttl: %d, [%s]", key, value, ttl, c.cluster.pick()) 70 | p := keyToPath(key) 71 | 72 | str, err := options.toParameters(VALID_PUT_OPTIONS) 73 | if err != nil { 74 | return nil, err 75 | } 76 | p += str 77 | 78 | req := NewRawRequest("PUT", p, buildValues(value, ttl), nil) 79 | resp, err := c.SendRequest(req) 80 | 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | return resp, nil 86 | } 87 | 88 | // post issues a POST request 89 | func (c *Client) post(key string, value string, ttl uint64) (*RawResponse, error) { 90 | logger.Debugf("post %s, %s, ttl: %d, [%s]", key, value, ttl, c.cluster.pick()) 91 | p := keyToPath(key) 92 | 93 | req := NewRawRequest("POST", p, buildValues(value, ttl), nil) 94 | resp, err := c.SendRequest(req) 95 | 96 | if err != nil { 97 | return nil, err 98 | } 99 | 100 | return resp, nil 101 | } 102 | 103 | // delete issues a DELETE request 104 | func (c *Client) delete(key string, options Options) (*RawResponse, error) { 105 | logger.Debugf("delete %s [%s]", key, c.cluster.pick()) 106 | p := keyToPath(key) 107 | 108 | str, err := options.toParameters(VALID_DELETE_OPTIONS) 109 | if err != nil { 110 | return nil, err 111 | } 112 | p += str 113 | 114 | req := NewRawRequest("DELETE", p, nil, nil) 115 | resp, err := c.SendRequest(req) 116 | 117 | if err != nil { 118 | return nil, err 119 | } 120 | 121 | return resp, nil 122 | } 123 | 124 | // SendRequest sends a HTTP request and returns a Response as defined by etcd 125 | func (c *Client) SendRequest(rr *RawRequest) (*RawResponse, error) { 126 | var req *http.Request 127 | var resp *http.Response 128 | var httpPath string 129 | var err error 130 | var respBody []byte 131 | 132 | var numReqs = 1 133 | 134 | checkRetry := c.CheckRetry 135 | if checkRetry == nil { 136 | checkRetry = DefaultCheckRetry 137 | } 138 | 139 | cancelled := make(chan bool, 1) 140 | reqLock := new(sync.Mutex) 141 | 142 | if rr.Cancel != nil { 143 | cancelRoutine := make(chan bool) 144 | defer close(cancelRoutine) 145 | 146 | go func() { 147 | select { 148 | case <-rr.Cancel: 149 | cancelled <- true 150 | logger.Debug("send.request is cancelled") 151 | case <-cancelRoutine: 152 | return 153 | } 154 | 155 | // Repeat canceling request until this thread is stopped 156 | // because we have no idea about whether it succeeds. 157 | for { 158 | reqLock.Lock() 159 | c.httpClient.Transport.(*http.Transport).CancelRequest(req) 160 | reqLock.Unlock() 161 | 162 | select { 163 | case <-time.After(100 * time.Millisecond): 164 | case <-cancelRoutine: 165 | return 166 | } 167 | } 168 | }() 169 | } 170 | 171 | // If we connect to a follower and consistency is required, retry until 172 | // we connect to a leader 173 | sleep := 25 * time.Millisecond 174 | maxSleep := time.Second 175 | 176 | for attempt := 0; ; attempt++ { 177 | if attempt > 0 { 178 | select { 179 | case <-cancelled: 180 | return nil, ErrRequestCancelled 181 | case <-time.After(sleep): 182 | sleep = sleep * 2 183 | if sleep > maxSleep { 184 | sleep = maxSleep 185 | } 186 | } 187 | } 188 | 189 | logger.Debug("Connecting to etcd: attempt ", attempt+1, " for ", rr.RelativePath) 190 | 191 | // get httpPath if not set 192 | if httpPath == "" { 193 | httpPath = c.getHttpPath(rr.RelativePath) 194 | } 195 | 196 | // Return a cURL command if curlChan is set 197 | if c.cURLch != nil { 198 | command := fmt.Sprintf("curl -X %s %s", rr.Method, httpPath) 199 | for key, value := range rr.Values { 200 | command += fmt.Sprintf(" -d %s=%s", key, value[0]) 201 | } 202 | if c.credentials != nil { 203 | command += fmt.Sprintf(" -u %s", c.credentials.username) 204 | } 205 | c.sendCURL(command) 206 | } 207 | 208 | logger.Debug("send.request.to ", httpPath, " | method ", rr.Method) 209 | 210 | req, err := func() (*http.Request, error) { 211 | reqLock.Lock() 212 | defer reqLock.Unlock() 213 | 214 | if rr.Values == nil { 215 | if req, err = http.NewRequest(rr.Method, httpPath, nil); err != nil { 216 | return nil, err 217 | } 218 | } else { 219 | body := strings.NewReader(rr.Values.Encode()) 220 | if req, err = http.NewRequest(rr.Method, httpPath, body); err != nil { 221 | return nil, err 222 | } 223 | 224 | req.Header.Set("Content-Type", 225 | "application/x-www-form-urlencoded; param=value") 226 | } 227 | return req, nil 228 | }() 229 | 230 | if err != nil { 231 | return nil, err 232 | } 233 | 234 | if c.credentials != nil { 235 | req.SetBasicAuth(c.credentials.username, c.credentials.password) 236 | } 237 | 238 | resp, err = c.httpClient.Do(req) 239 | // clear previous httpPath 240 | httpPath = "" 241 | defer func() { 242 | if resp != nil { 243 | resp.Body.Close() 244 | } 245 | }() 246 | 247 | // If the request was cancelled, return ErrRequestCancelled directly 248 | select { 249 | case <-cancelled: 250 | return nil, ErrRequestCancelled 251 | default: 252 | } 253 | 254 | numReqs++ 255 | 256 | // network error, change a machine! 257 | if err != nil { 258 | logger.Debug("network error: ", err.Error()) 259 | lastResp := http.Response{} 260 | if checkErr := checkRetry(c.cluster, numReqs, lastResp, err); checkErr != nil { 261 | return nil, checkErr 262 | } 263 | 264 | c.cluster.failure() 265 | continue 266 | } 267 | 268 | // if there is no error, it should receive response 269 | logger.Debug("recv.response.from ", httpPath) 270 | 271 | if validHttpStatusCode[resp.StatusCode] { 272 | // try to read byte code and break the loop 273 | respBody, err = ioutil.ReadAll(resp.Body) 274 | if err == nil { 275 | logger.Debug("recv.success ", httpPath) 276 | break 277 | } 278 | // ReadAll error may be caused due to cancel request 279 | select { 280 | case <-cancelled: 281 | return nil, ErrRequestCancelled 282 | default: 283 | } 284 | 285 | if err == io.ErrUnexpectedEOF { 286 | // underlying connection was closed prematurely, probably by timeout 287 | // TODO: empty body or unexpectedEOF can cause http.Transport to get hosed; 288 | // this allows the client to detect that and take evasive action. Need 289 | // to revisit once code.google.com/p/go/issues/detail?id=8648 gets fixed. 290 | respBody = []byte{} 291 | break 292 | } 293 | } 294 | 295 | if resp.StatusCode == http.StatusTemporaryRedirect { 296 | u, err := resp.Location() 297 | 298 | if err != nil { 299 | logger.Warning(err) 300 | } else { 301 | // set httpPath for following redirection 302 | httpPath = u.String() 303 | } 304 | resp.Body.Close() 305 | continue 306 | } 307 | 308 | if checkErr := checkRetry(c.cluster, numReqs, *resp, 309 | errors.New("Unexpected HTTP status code")); checkErr != nil { 310 | return nil, checkErr 311 | } 312 | resp.Body.Close() 313 | } 314 | 315 | r := &RawResponse{ 316 | StatusCode: resp.StatusCode, 317 | Body: respBody, 318 | Header: resp.Header, 319 | } 320 | 321 | return r, nil 322 | } 323 | 324 | // DefaultCheckRetry defines the retrying behaviour for bad HTTP requests 325 | // If we have retried 2 * machine number, stop retrying. 326 | // If status code is InternalServerError, sleep for 200ms. 327 | func DefaultCheckRetry(cluster *Cluster, numReqs int, lastResp http.Response, 328 | err error) error { 329 | 330 | if isEmptyResponse(lastResp) { 331 | // always retry if it failed to get response from one machine 332 | return err 333 | } else if !shouldRetry(lastResp) { 334 | body := []byte("nil") 335 | if lastResp.Body != nil { 336 | if b, err := ioutil.ReadAll(lastResp.Body); err == nil { 337 | body = b 338 | } 339 | } 340 | errStr := fmt.Sprintf("unhandled http status [%s] with body [%s]", http.StatusText(lastResp.StatusCode), body) 341 | return newError(ErrCodeUnhandledHTTPStatus, errStr, 0) 342 | } 343 | 344 | if numReqs > 2*len(cluster.Machines) { 345 | errStr := fmt.Sprintf("failed to propose on members %v twice [last error: %v]", cluster.Machines, err) 346 | return newError(ErrCodeEtcdNotReachable, errStr, 0) 347 | } 348 | if shouldRetry(lastResp) { 349 | // sleep some time and expect leader election finish 350 | time.Sleep(time.Millisecond * 200) 351 | } 352 | 353 | logger.Warning("bad response status code", lastResp.StatusCode) 354 | return nil 355 | } 356 | 357 | func isEmptyResponse(r http.Response) bool { return r.StatusCode == 0 } 358 | 359 | // shouldRetry returns whether the reponse deserves retry. 360 | func shouldRetry(r http.Response) bool { 361 | // TODO: only retry when the cluster is in leader election 362 | // We cannot do it exactly because etcd doesn't support it well. 363 | return r.StatusCode == http.StatusInternalServerError 364 | } 365 | 366 | func (c *Client) getHttpPath(s ...string) string { 367 | fullPath := c.cluster.pick() + "/" + version 368 | for _, seg := range s { 369 | fullPath = fullPath + "/" + seg 370 | } 371 | return fullPath 372 | } 373 | 374 | // buildValues builds a url.Values map according to the given value and ttl 375 | func buildValues(value string, ttl uint64) url.Values { 376 | v := url.Values{} 377 | 378 | if value != "" { 379 | v.Set("value", value) 380 | } 381 | 382 | if ttl > 0 { 383 | v.Set("ttl", fmt.Sprintf("%v", ttl)) 384 | } 385 | 386 | return v 387 | } 388 | 389 | // convert key string to http path exclude version, including URL escaping 390 | // for example: key[foo] -> path[keys/foo] 391 | // key[/%z] -> path[keys/%25z] 392 | // key[/] -> path[keys/] 393 | func keyToPath(key string) string { 394 | // URL-escape our key, except for slashes 395 | p := strings.Replace(url.QueryEscape(path.Join("keys", key)), "%2F", "/", -1) 396 | 397 | // corner case: if key is "/" or "//" ect 398 | // path join will clear the tailing "/" 399 | // we need to add it back 400 | if p == "keys" { 401 | p = "keys/" 402 | } 403 | 404 | return p 405 | } 406 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/coreos/go-etcd/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/op/go-logging/format.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013, Örjan Persson. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package logging 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "fmt" 11 | "io" 12 | "os" 13 | "path" 14 | "path/filepath" 15 | "regexp" 16 | "runtime" 17 | "strconv" 18 | "strings" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | // TODO see Formatter interface in fmt/print.go 24 | // TODO try text/template, maybe it have enough performance 25 | // TODO other template systems? 26 | // TODO make it possible to specify formats per backend? 27 | type fmtVerb int 28 | 29 | const ( 30 | fmtVerbTime fmtVerb = iota 31 | fmtVerbLevel 32 | fmtVerbID 33 | fmtVerbPid 34 | fmtVerbProgram 35 | fmtVerbModule 36 | fmtVerbMessage 37 | fmtVerbLongfile 38 | fmtVerbShortfile 39 | fmtVerbLongpkg 40 | fmtVerbShortpkg 41 | fmtVerbLongfunc 42 | fmtVerbShortfunc 43 | fmtVerbCallpath 44 | fmtVerbLevelColor 45 | 46 | // Keep last, there are no match for these below. 47 | fmtVerbUnknown 48 | fmtVerbStatic 49 | ) 50 | 51 | var fmtVerbs = []string{ 52 | "time", 53 | "level", 54 | "id", 55 | "pid", 56 | "program", 57 | "module", 58 | "message", 59 | "longfile", 60 | "shortfile", 61 | "longpkg", 62 | "shortpkg", 63 | "longfunc", 64 | "shortfunc", 65 | "callpath", 66 | "color", 67 | } 68 | 69 | const rfc3339Milli = "2006-01-02T15:04:05.999Z07:00" 70 | 71 | var defaultVerbsLayout = []string{ 72 | rfc3339Milli, 73 | "s", 74 | "d", 75 | "d", 76 | "s", 77 | "s", 78 | "s", 79 | "s", 80 | "s", 81 | "s", 82 | "s", 83 | "s", 84 | "s", 85 | "0", 86 | "", 87 | } 88 | 89 | var ( 90 | pid = os.Getpid() 91 | program = filepath.Base(os.Args[0]) 92 | ) 93 | 94 | func getFmtVerbByName(name string) fmtVerb { 95 | for i, verb := range fmtVerbs { 96 | if name == verb { 97 | return fmtVerb(i) 98 | } 99 | } 100 | return fmtVerbUnknown 101 | } 102 | 103 | // Formatter is the required interface for a custom log record formatter. 104 | type Formatter interface { 105 | Format(calldepth int, r *Record, w io.Writer) error 106 | } 107 | 108 | // formatter is used by all backends unless otherwise overriden. 109 | var formatter struct { 110 | sync.RWMutex 111 | def Formatter 112 | } 113 | 114 | func getFormatter() Formatter { 115 | formatter.RLock() 116 | defer formatter.RUnlock() 117 | return formatter.def 118 | } 119 | 120 | var ( 121 | // DefaultFormatter is the default formatter used and is only the message. 122 | DefaultFormatter = MustStringFormatter("%{message}") 123 | 124 | // GlogFormatter mimics the glog format 125 | GlogFormatter = MustStringFormatter("%{level:.1s}%{time:0102 15:04:05.999999} %{pid} %{shortfile}] %{message}") 126 | ) 127 | 128 | // SetFormatter sets the default formatter for all new backends. A backend will 129 | // fetch this value once it is needed to format a record. Note that backends 130 | // will cache the formatter after the first point. For now, make sure to set 131 | // the formatter before logging. 132 | func SetFormatter(f Formatter) { 133 | formatter.Lock() 134 | defer formatter.Unlock() 135 | formatter.def = f 136 | } 137 | 138 | var formatRe = regexp.MustCompile(`%{([a-z]+)(?::(.*?[^\\]))?}`) 139 | 140 | type part struct { 141 | verb fmtVerb 142 | layout string 143 | } 144 | 145 | // stringFormatter contains a list of parts which explains how to build the 146 | // formatted string passed on to the logging backend. 147 | type stringFormatter struct { 148 | parts []part 149 | } 150 | 151 | // NewStringFormatter returns a new Formatter which outputs the log record as a 152 | // string based on the 'verbs' specified in the format string. 153 | // 154 | // The verbs: 155 | // 156 | // General: 157 | // %{id} Sequence number for log message (uint64). 158 | // %{pid} Process id (int) 159 | // %{time} Time when log occurred (time.Time) 160 | // %{level} Log level (Level) 161 | // %{module} Module (string) 162 | // %{program} Basename of os.Args[0] (string) 163 | // %{message} Message (string) 164 | // %{longfile} Full file name and line number: /a/b/c/d.go:23 165 | // %{shortfile} Final file name element and line number: d.go:23 166 | // %{callpath} Callpath like main.a.b.c...c "..." meaning recursive call ~. meaning truncated path 167 | // %{color} ANSI color based on log level 168 | // 169 | // For normal types, the output can be customized by using the 'verbs' defined 170 | // in the fmt package, eg. '%{id:04d}' to make the id output be '%04d' as the 171 | // format string. 172 | // 173 | // For time.Time, use the same layout as time.Format to change the time format 174 | // when output, eg "2006-01-02T15:04:05.999Z-07:00". 175 | // 176 | // For the 'color' verb, the output can be adjusted to either use bold colors, 177 | // i.e., '%{color:bold}' or to reset the ANSI attributes, i.e., 178 | // '%{color:reset}' Note that if you use the color verb explicitly, be sure to 179 | // reset it or else the color state will persist past your log message. e.g., 180 | // "%{color:bold}%{time:15:04:05} %{level:-8s}%{color:reset} %{message}" will 181 | // just colorize the time and level, leaving the message uncolored. 182 | // 183 | // For the 'callpath' verb, the output can be adjusted to limit the printing 184 | // the stack depth. i.e. '%{callpath:3}' will print '~.a.b.c' 185 | // 186 | // Colors on Windows is unfortunately not supported right now and is currently 187 | // a no-op. 188 | // 189 | // There's also a couple of experimental 'verbs'. These are exposed to get 190 | // feedback and needs a bit of tinkering. Hence, they might change in the 191 | // future. 192 | // 193 | // Experimental: 194 | // %{longpkg} Full package path, eg. github.com/go-logging 195 | // %{shortpkg} Base package path, eg. go-logging 196 | // %{longfunc} Full function name, eg. littleEndian.PutUint32 197 | // %{shortfunc} Base function name, eg. PutUint32 198 | // %{callpath} Call function path, eg. main.a.b.c 199 | func NewStringFormatter(format string) (Formatter, error) { 200 | var fmter = &stringFormatter{} 201 | 202 | // Find the boundaries of all %{vars} 203 | matches := formatRe.FindAllStringSubmatchIndex(format, -1) 204 | if matches == nil { 205 | return nil, errors.New("logger: invalid log format: " + format) 206 | } 207 | 208 | // Collect all variables and static text for the format 209 | prev := 0 210 | for _, m := range matches { 211 | start, end := m[0], m[1] 212 | if start > prev { 213 | fmter.add(fmtVerbStatic, format[prev:start]) 214 | } 215 | 216 | name := format[m[2]:m[3]] 217 | verb := getFmtVerbByName(name) 218 | if verb == fmtVerbUnknown { 219 | return nil, errors.New("logger: unknown variable: " + name) 220 | } 221 | 222 | // Handle layout customizations or use the default. If this is not for the 223 | // time, color formatting or callpath, we need to prefix with %. 224 | layout := defaultVerbsLayout[verb] 225 | if m[4] != -1 { 226 | layout = format[m[4]:m[5]] 227 | } 228 | if verb != fmtVerbTime && verb != fmtVerbLevelColor && verb != fmtVerbCallpath { 229 | layout = "%" + layout 230 | } 231 | 232 | fmter.add(verb, layout) 233 | prev = end 234 | } 235 | end := format[prev:] 236 | if end != "" { 237 | fmter.add(fmtVerbStatic, end) 238 | } 239 | 240 | // Make a test run to make sure we can format it correctly. 241 | t, err := time.Parse(time.RFC3339, "2010-02-04T21:00:57-08:00") 242 | if err != nil { 243 | panic(err) 244 | } 245 | testFmt := "hello %s" 246 | r := &Record{ 247 | ID: 12345, 248 | Time: t, 249 | Module: "logger", 250 | Args: []interface{}{"go"}, 251 | fmt: &testFmt, 252 | } 253 | if err := fmter.Format(0, r, &bytes.Buffer{}); err != nil { 254 | return nil, err 255 | } 256 | 257 | return fmter, nil 258 | } 259 | 260 | // MustStringFormatter is equivalent to NewStringFormatter with a call to panic 261 | // on error. 262 | func MustStringFormatter(format string) Formatter { 263 | f, err := NewStringFormatter(format) 264 | if err != nil { 265 | panic("Failed to initialized string formatter: " + err.Error()) 266 | } 267 | return f 268 | } 269 | 270 | func (f *stringFormatter) add(verb fmtVerb, layout string) { 271 | f.parts = append(f.parts, part{verb, layout}) 272 | } 273 | 274 | func (f *stringFormatter) Format(calldepth int, r *Record, output io.Writer) error { 275 | for _, part := range f.parts { 276 | if part.verb == fmtVerbStatic { 277 | output.Write([]byte(part.layout)) 278 | } else if part.verb == fmtVerbTime { 279 | output.Write([]byte(r.Time.Format(part.layout))) 280 | } else if part.verb == fmtVerbLevelColor { 281 | doFmtVerbLevelColor(part.layout, r.Level, output) 282 | } else if part.verb == fmtVerbCallpath { 283 | depth, err := strconv.Atoi(part.layout) 284 | if err != nil { 285 | depth = 0 286 | } 287 | output.Write([]byte(formatCallpath(calldepth+1, depth))) 288 | } else { 289 | var v interface{} 290 | switch part.verb { 291 | case fmtVerbLevel: 292 | v = r.Level 293 | break 294 | case fmtVerbID: 295 | v = r.ID 296 | break 297 | case fmtVerbPid: 298 | v = pid 299 | break 300 | case fmtVerbProgram: 301 | v = program 302 | break 303 | case fmtVerbModule: 304 | v = r.Module 305 | break 306 | case fmtVerbMessage: 307 | v = r.Message() 308 | break 309 | case fmtVerbLongfile, fmtVerbShortfile: 310 | _, file, line, ok := runtime.Caller(calldepth + 1) 311 | if !ok { 312 | file = "???" 313 | line = 0 314 | } else if part.verb == fmtVerbShortfile { 315 | file = filepath.Base(file) 316 | } 317 | v = fmt.Sprintf("%s:%d", file, line) 318 | case fmtVerbLongfunc, fmtVerbShortfunc, 319 | fmtVerbLongpkg, fmtVerbShortpkg: 320 | // TODO cache pc 321 | v = "???" 322 | if pc, _, _, ok := runtime.Caller(calldepth + 1); ok { 323 | if f := runtime.FuncForPC(pc); f != nil { 324 | v = formatFuncName(part.verb, f.Name()) 325 | } 326 | } 327 | default: 328 | panic("unhandled format part") 329 | } 330 | fmt.Fprintf(output, part.layout, v) 331 | } 332 | } 333 | return nil 334 | } 335 | 336 | // formatFuncName tries to extract certain part of the runtime formatted 337 | // function name to some pre-defined variation. 338 | // 339 | // This function is known to not work properly if the package path or name 340 | // contains a dot. 341 | func formatFuncName(v fmtVerb, f string) string { 342 | i := strings.LastIndex(f, "/") 343 | j := strings.Index(f[i+1:], ".") 344 | if j < 1 { 345 | return "???" 346 | } 347 | pkg, fun := f[:i+j+1], f[i+j+2:] 348 | switch v { 349 | case fmtVerbLongpkg: 350 | return pkg 351 | case fmtVerbShortpkg: 352 | return path.Base(pkg) 353 | case fmtVerbLongfunc: 354 | return fun 355 | case fmtVerbShortfunc: 356 | i = strings.LastIndex(fun, ".") 357 | return fun[i+1:] 358 | } 359 | panic("unexpected func formatter") 360 | } 361 | 362 | func formatCallpath(calldepth int, depth int) string { 363 | v := "" 364 | callers := make([]uintptr, 64) 365 | n := runtime.Callers(calldepth+2, callers) 366 | oldPc := callers[n-1] 367 | 368 | start := n - 3 369 | if depth > 0 && start >= depth { 370 | start = depth - 1 371 | v += "~." 372 | } 373 | recursiveCall := false 374 | for i := start; i >= 0; i-- { 375 | pc := callers[i] 376 | if oldPc == pc { 377 | recursiveCall = true 378 | continue 379 | } 380 | oldPc = pc 381 | if recursiveCall { 382 | recursiveCall = false 383 | v += ".." 384 | } 385 | if i < start { 386 | v += "." 387 | } 388 | if f := runtime.FuncForPC(pc); f != nil { 389 | v += formatFuncName(fmtVerbShortfunc, f.Name()) 390 | } 391 | } 392 | return v 393 | } 394 | 395 | // backendFormatter combines a backend with a specific formatter making it 396 | // possible to have different log formats for different backends. 397 | type backendFormatter struct { 398 | b Backend 399 | f Formatter 400 | } 401 | 402 | // NewBackendFormatter creates a new backend which makes all records that 403 | // passes through it beeing formatted by the specific formatter. 404 | func NewBackendFormatter(b Backend, f Formatter) Backend { 405 | return &backendFormatter{b, f} 406 | } 407 | 408 | // Log implements the Log function required by the Backend interface. 409 | func (bf *backendFormatter) Log(level Level, calldepth int, r *Record) error { 410 | // Make a shallow copy of the record and replace any formatter 411 | r2 := *r 412 | r2.formatter = bf.f 413 | return bf.b.Log(level, calldepth+1, &r2) 414 | } 415 | --------------------------------------------------------------------------------