├── .dockerignore ├── .gitignore ├── Dockerfile ├── Godeps ├── Godeps.json ├── Readme └── _workspace │ ├── .gitignore │ └── src │ └── github.com │ ├── Sirupsen │ └── logrus │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ ├── entry.go │ │ ├── examples │ │ ├── basic │ │ │ └── basic.go │ │ └── hook │ │ │ └── hook.go │ │ ├── exported.go │ │ ├── formatter.go │ │ ├── formatters │ │ └── logstash │ │ │ └── logstash.go │ │ ├── hooks.go │ │ ├── hooks │ │ ├── airbrake │ │ │ └── airbrake.go │ │ ├── bugsnag │ │ │ └── bugsnag.go │ │ ├── papertrail │ │ │ ├── README.md │ │ │ └── papertrail.go │ │ ├── sentry │ │ │ ├── README.md │ │ │ └── sentry.go │ │ └── syslog │ │ │ ├── README.md │ │ │ └── syslog.go │ │ ├── json_formatter.go │ │ ├── logger.go │ │ ├── logrus.go │ │ ├── terminal_bsd.go │ │ ├── terminal_linux.go │ │ ├── terminal_notwindows.go │ │ ├── terminal_windows.go │ │ ├── text_formatter.go │ │ └── writer.go │ ├── boltdb │ └── bolt │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── batch.go │ │ ├── bolt_386.go │ │ ├── bolt_amd64.go │ │ ├── bolt_arm.go │ │ ├── bolt_linux.go │ │ ├── bolt_openbsd.go │ │ ├── bolt_unix.go │ │ ├── bolt_unix_solaris.go │ │ ├── bolt_windows.go │ │ ├── boltsync_unix.go │ │ ├── bucket.go │ │ ├── cmd │ │ └── bolt │ │ │ └── main.go │ │ ├── cursor.go │ │ ├── db.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── freelist.go │ │ ├── node.go │ │ ├── page.go │ │ └── tx.go │ ├── coreos │ └── go-etcd │ │ └── etcd │ │ ├── add_child.go │ │ ├── client.go │ │ ├── cluster.go │ │ ├── compare_and_delete.go │ │ ├── compare_and_swap.go │ │ ├── debug.go │ │ ├── delete.go │ │ ├── error.go │ │ ├── get.go │ │ ├── member.go │ │ ├── options.go │ │ ├── requests.go │ │ ├── response.generated.go │ │ ├── response.go │ │ ├── set_update_create.go │ │ ├── shuffle.go │ │ ├── version.go │ │ └── watch.go │ ├── docker │ ├── docker │ │ └── pkg │ │ │ └── signal │ │ │ ├── README.md │ │ │ ├── signal.go │ │ │ ├── signal_darwin.go │ │ │ ├── signal_freebsd.go │ │ │ ├── signal_linux.go │ │ │ ├── signal_unix.go │ │ │ ├── signal_unsupported.go │ │ │ ├── signal_windows.go │ │ │ └── trap.go │ └── libkv │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── libkv.go │ │ ├── script │ │ ├── .validate │ │ ├── coverage │ │ ├── travis_consul.sh │ │ ├── travis_etcd.sh │ │ ├── travis_zk.sh │ │ └── validate-gofmt │ │ ├── store │ │ ├── boltdb │ │ │ └── boltdb.go │ │ ├── consul │ │ │ └── consul.go │ │ ├── etcd │ │ │ └── etcd.go │ │ ├── helpers.go │ │ ├── mock │ │ │ └── mock.go │ │ ├── store.go │ │ └── zookeeper │ │ │ └── zookeeper.go │ │ └── testutils │ │ └── utils.go │ ├── hanwen │ └── go-fuse │ │ ├── fuse │ │ ├── .gitignore │ │ ├── api.go │ │ ├── attr.go │ │ ├── attr_darwin.go │ │ ├── attr_linux.go │ │ ├── bufferpool.go │ │ ├── constants.go │ │ ├── constants_freebsd.go │ │ ├── constants_linux.go │ │ ├── defaultraw.go │ │ ├── direntry.go │ │ ├── lockingfs.go │ │ ├── misc.go │ │ ├── mount_darwin.go │ │ ├── mount_linux.go │ │ ├── nodefs │ │ │ ├── api.go │ │ │ ├── defaultfile.go │ │ │ ├── defaultnode.go │ │ │ ├── dir.go │ │ │ ├── files.go │ │ │ ├── files_darwin.go │ │ │ ├── files_linux.go │ │ │ ├── fsconnector.go │ │ │ ├── fsmount.go │ │ │ ├── fsops.go │ │ │ ├── fuse.go │ │ │ ├── handle.go │ │ │ ├── inode.go │ │ │ ├── lockingfile.go │ │ │ ├── memnode.go │ │ │ ├── nodefs.go │ │ │ └── print.go │ │ ├── opcode.go │ │ ├── pathfs │ │ │ ├── api.go │ │ │ ├── copy.go │ │ │ ├── default.go │ │ │ ├── locking.go │ │ │ ├── loopback.go │ │ │ ├── loopback_darwin.go │ │ │ ├── loopback_linux.go │ │ │ ├── pathfs.go │ │ │ ├── prefixfs.go │ │ │ ├── readonlyfs.go │ │ │ └── syscall_linux.go │ │ ├── print.go │ │ ├── print_darwin.go │ │ ├── print_linux.go │ │ ├── read.go │ │ ├── request.go │ │ ├── request_darwin.go │ │ ├── request_linux.go │ │ ├── server.go │ │ ├── server_darwin.go │ │ ├── server_linux.go │ │ ├── splice_darwin.go │ │ ├── splice_linux.go │ │ ├── syscall_darwin.go │ │ ├── syscall_linux.go │ │ ├── test │ │ │ └── verbose.go │ │ ├── typeprint.go │ │ ├── types.go │ │ ├── types_darwin.go │ │ ├── types_linux.go │ │ └── upgrade.go │ │ └── splice │ │ ├── copy.go │ │ ├── pair.go │ │ ├── pair_darwin.go │ │ ├── pair_linux.go │ │ ├── pool.go │ │ └── splice.go │ ├── hashicorp │ └── consul │ │ └── api │ │ ├── README.md │ │ ├── acl.go │ │ ├── agent.go │ │ ├── api.go │ │ ├── catalog.go │ │ ├── event.go │ │ ├── health.go │ │ ├── kv.go │ │ ├── lock.go │ │ ├── raw.go │ │ ├── semaphore.go │ │ ├── session.go │ │ └── status.go │ ├── samuel │ └── go-zookeeper │ │ └── zk │ │ ├── conn.go │ │ ├── constants.go │ │ ├── flw.go │ │ ├── lock.go │ │ ├── server_help.go │ │ ├── server_java.go │ │ ├── structs.go │ │ ├── tracer.go │ │ └── util.go │ └── ugorji │ └── go │ └── codec │ ├── 0doc.go │ ├── README.md │ ├── binc.go │ ├── cbor.go │ ├── codecgen │ ├── README.md │ ├── gen.go │ └── z.go │ ├── decode.go │ ├── encode.go │ ├── fast-path.generated.go │ ├── fast-path.go.tmpl │ ├── gen-dec-array.go.tmpl │ ├── gen-dec-map.go.tmpl │ ├── gen-helper.generated.go │ ├── gen-helper.go.tmpl │ ├── gen.generated.go │ ├── gen.go │ ├── helper.go │ ├── helper_internal.go │ ├── helper_not_unsafe.go │ ├── helper_unsafe.go │ ├── json.go │ ├── msgpack.go │ ├── noop.go │ ├── prebuild.go │ ├── prebuild.sh │ ├── rpc.go │ ├── simple.go │ ├── test-cbor-goldens.json │ ├── test.py │ └── time.go ├── LICENSE ├── README.md ├── fs ├── file.go └── fs.go └── main.go /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | .git 3 | .gitignore 4 | -------------------------------------------------------------------------------- /.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 | *.test 24 | *.prof 25 | 26 | kvfs # make sure we don't commit the binary 27 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.5 2 | ADD . /go/src/github.com/cpuguy83/kvfs 3 | WORKDIR /go/src/github.com/cpuguy83/kvfs 4 | RUN go get github.com/tools/godep 5 | RUN godep get 6 | RUN godep go build && cp kvfs /usr/local/bin/ 7 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/cpuguy83/kvfs", 3 | "GoVersion": "go1.4.2", 4 | "Deps": [ 5 | { 6 | "ImportPath": "github.com/Sirupsen/logrus", 7 | "Comment": "v0.8.7", 8 | "Rev": "418b41d23a1bf978c06faea5313ba194650ac088" 9 | }, 10 | { 11 | "ImportPath": "github.com/boltdb/bolt", 12 | "Comment": "v1.0-125-g033d4ec", 13 | "Rev": "033d4ec028192f38aef67ae47bd7b89f343145b5" 14 | }, 15 | { 16 | "ImportPath": "github.com/coreos/go-etcd/etcd", 17 | "Comment": "v2.0.0-32-g555b418", 18 | "Rev": "555b4186480c545106eb89e0158e9fa0c2bebcf6" 19 | }, 20 | { 21 | "ImportPath": "github.com/docker/docker/pkg/signal", 22 | "Comment": "v1.4.1-6261-g57c6012", 23 | "Rev": "57c6012cf0dbe1097b2b876b0fbca5fa6dbf0e81" 24 | }, 25 | { 26 | "ImportPath": "github.com/docker/libkv", 27 | "Rev": "4aec61dc3c9c1c4f11221a0c0cfde67ccb8f04c3" 28 | }, 29 | { 30 | "ImportPath": "github.com/hanwen/go-fuse/fuse", 31 | "Rev": "324ea173d0a4d90e0e97c464a6ad33f80c9587a8" 32 | }, 33 | { 34 | "ImportPath": "github.com/hanwen/go-fuse/splice", 35 | "Rev": "324ea173d0a4d90e0e97c464a6ad33f80c9587a8" 36 | }, 37 | { 38 | "ImportPath": "github.com/hashicorp/consul/api", 39 | "Comment": "v0.5.2-311-g0b05dbe", 40 | "Rev": "0b05dbeb216f878ab08aa6267c1a23eeaab240ce" 41 | }, 42 | { 43 | "ImportPath": "github.com/samuel/go-zookeeper/zk", 44 | "Rev": "177002e16a0061912f02377e2dd8951a8b3551bc" 45 | }, 46 | { 47 | "ImportPath": "github.com/ugorji/go/codec", 48 | "Rev": "718a1bcd1902bb42e926b0e54f6686879f5a9a79" 49 | } 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /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/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore: -------------------------------------------------------------------------------- 1 | logrus 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.2 4 | - 1.3 5 | - 1.4 6 | - tip 7 | install: 8 | - go get -t ./... 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.8.7 2 | 3 | * logrus/core: fix possible race (#216) 4 | * logrus/doc: small typo fixes and doc improvements 5 | 6 | 7 | # 0.8.6 8 | 9 | * hooks/raven: allow passing an initialized client 10 | 11 | # 0.8.5 12 | 13 | * logrus/core: revert #208 14 | 15 | # 0.8.4 16 | 17 | * formatter/text: fix data race (#218) 18 | 19 | # 0.8.3 20 | 21 | * logrus/core: fix entry log level (#208) 22 | * logrus/core: improve performance of text formatter by 40% 23 | * logrus/core: expose `LevelHooks` type 24 | * logrus/core: add support for DragonflyBSD and NetBSD 25 | * formatter/text: print structs more verbosely 26 | 27 | # 0.8.2 28 | 29 | * logrus: fix more Fatal family functions 30 | 31 | # 0.8.1 32 | 33 | * logrus: fix not exiting on `Fatalf` and `Fatalln` 34 | 35 | # 0.8.0 36 | 37 | * logrus: defaults to stderr instead of stdout 38 | * hooks/sentry: add special field for `*http.Request` 39 | * formatter/text: ignore Windows for colors 40 | 41 | # 0.7.3 42 | 43 | * formatter/\*: allow configuration of timestamp layout 44 | 45 | # 0.7.2 46 | 47 | * formatter/text: Add configuration option for time format (#158) 48 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Simon Eskildsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package logrus is a structured logger for Go, completely API compatible with the standard library logger. 3 | 4 | 5 | The simplest way to use Logrus is simply the package-level exported logger: 6 | 7 | package main 8 | 9 | import ( 10 | log "github.com/Sirupsen/logrus" 11 | ) 12 | 13 | func main() { 14 | log.WithFields(log.Fields{ 15 | "animal": "walrus", 16 | "number": 1, 17 | "size": 10, 18 | }).Info("A walrus appears") 19 | } 20 | 21 | Output: 22 | time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 23 | 24 | For a full guide visit https://github.com/Sirupsen/logrus 25 | */ 26 | package logrus 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/Sirupsen/logrus" 5 | ) 6 | 7 | var log = logrus.New() 8 | 9 | func init() { 10 | log.Formatter = new(logrus.JSONFormatter) 11 | log.Formatter = new(logrus.TextFormatter) // default 12 | log.Level = logrus.DebugLevel 13 | } 14 | 15 | func main() { 16 | defer func() { 17 | err := recover() 18 | if err != nil { 19 | log.WithFields(logrus.Fields{ 20 | "omg": true, 21 | "err": err, 22 | "number": 100, 23 | }).Fatal("The ice breaks!") 24 | } 25 | }() 26 | 27 | log.WithFields(logrus.Fields{ 28 | "animal": "walrus", 29 | "number": 8, 30 | }).Debug("Started observing beach") 31 | 32 | log.WithFields(logrus.Fields{ 33 | "animal": "walrus", 34 | "size": 10, 35 | }).Info("A group of walrus emerges from the ocean") 36 | 37 | log.WithFields(logrus.Fields{ 38 | "omg": true, 39 | "number": 122, 40 | }).Warn("The group's number increased tremendously!") 41 | 42 | log.WithFields(logrus.Fields{ 43 | "temperature": -4, 44 | }).Debug("Temperature changes") 45 | 46 | log.WithFields(logrus.Fields{ 47 | "animal": "orca", 48 | "size": 9009, 49 | }).Panic("It's over 9000!") 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/Sirupsen/logrus" 5 | "github.com/Sirupsen/logrus/hooks/airbrake" 6 | ) 7 | 8 | var log = logrus.New() 9 | 10 | func init() { 11 | log.Formatter = new(logrus.TextFormatter) // default 12 | log.Hooks.Add(airbrake.NewHook("https://example.com", "xyz", "development")) 13 | } 14 | 15 | func main() { 16 | log.WithFields(logrus.Fields{ 17 | "animal": "walrus", 18 | "size": 10, 19 | }).Info("A group of walrus emerges from the ocean") 20 | 21 | log.WithFields(logrus.Fields{ 22 | "omg": true, 23 | "number": 122, 24 | }).Warn("The group's number increased tremendously!") 25 | 26 | log.WithFields(logrus.Fields{ 27 | "omg": true, 28 | "number": 100, 29 | }).Fatal("The ice breaks!") 30 | } 31 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import "time" 4 | 5 | const DefaultTimestampFormat = time.RFC3339 6 | 7 | // The Formatter interface is used to implement a custom Formatter. It takes an 8 | // `Entry`. It exposes all the fields, including the default ones: 9 | // 10 | // * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. 11 | // * `entry.Data["time"]`. The timestamp. 12 | // * `entry.Data["level"]. The level the entry was logged at. 13 | // 14 | // Any additional fields added with `WithField` or `WithFields` are also in 15 | // `entry.Data`. Format is expected to return an array of bytes which are then 16 | // logged to `logger.Out`. 17 | type Formatter interface { 18 | Format(*Entry) ([]byte, error) 19 | } 20 | 21 | // This is to not silently overwrite `time`, `msg` and `level` fields when 22 | // dumping it. If this code wasn't there doing: 23 | // 24 | // logrus.WithField("level", 1).Info("hello") 25 | // 26 | // Would just silently drop the user provided level. Instead with this code 27 | // it'll logged as: 28 | // 29 | // {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} 30 | // 31 | // It's not exported because it's still using Data in an opinionated way. It's to 32 | // avoid code duplication between the two default formatters. 33 | func prefixFieldClashes(data Fields) { 34 | _, ok := data["time"] 35 | if ok { 36 | data["fields.time"] = data["time"] 37 | } 38 | 39 | _, ok = data["msg"] 40 | if ok { 41 | data["fields.msg"] = data["msg"] 42 | } 43 | 44 | _, ok = data["level"] 45 | if ok { 46 | data["fields.level"] = data["level"] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/formatters/logstash/logstash.go: -------------------------------------------------------------------------------- 1 | package logstash 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/Sirupsen/logrus" 8 | ) 9 | 10 | // Formatter generates json in logstash format. 11 | // Logstash site: http://logstash.net/ 12 | type LogstashFormatter struct { 13 | Type string // if not empty use for logstash type field. 14 | 15 | // TimestampFormat sets the format used for timestamps. 16 | TimestampFormat string 17 | } 18 | 19 | func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) { 20 | entry.Data["@version"] = 1 21 | 22 | if f.TimestampFormat == "" { 23 | f.TimestampFormat = logrus.DefaultTimestampFormat 24 | } 25 | 26 | entry.Data["@timestamp"] = entry.Time.Format(f.TimestampFormat) 27 | 28 | // set message field 29 | v, ok := entry.Data["message"] 30 | if ok { 31 | entry.Data["fields.message"] = v 32 | } 33 | entry.Data["message"] = entry.Message 34 | 35 | // set level field 36 | v, ok = entry.Data["level"] 37 | if ok { 38 | entry.Data["fields.level"] = v 39 | } 40 | entry.Data["level"] = entry.Level.String() 41 | 42 | // set type field 43 | if f.Type != "" { 44 | v, ok = entry.Data["type"] 45 | if ok { 46 | entry.Data["fields.type"] = v 47 | } 48 | entry.Data["type"] = f.Type 49 | } 50 | 51 | serialized, err := json.Marshal(entry.Data) 52 | if err != nil { 53 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 54 | } 55 | return append(serialized, '\n'), nil 56 | } 57 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | // A hook to be fired when logging on the logging levels returned from 4 | // `Levels()` on your implementation of the interface. Note that this is not 5 | // fired in a goroutine or a channel with workers, you should handle such 6 | // functionality yourself if your call is non-blocking and you don't wish for 7 | // the logging calls for levels returned from `Levels()` to block. 8 | type Hook interface { 9 | Levels() []Level 10 | Fire(*Entry) error 11 | } 12 | 13 | // Internal type for storing the hooks on a logger instance. 14 | type LevelHooks map[Level][]Hook 15 | 16 | // Add a hook to an instance of logger. This is called with 17 | // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. 18 | func (hooks LevelHooks) Add(hook Hook) { 19 | for _, level := range hook.Levels() { 20 | hooks[level] = append(hooks[level], hook) 21 | } 22 | } 23 | 24 | // Fire all the hooks for the passed level. Used by `entry.log` to fire 25 | // appropriate hooks for a log entry. 26 | func (hooks LevelHooks) Fire(level Level, entry *Entry) error { 27 | for _, hook := range hooks[level] { 28 | if err := hook.Fire(entry); err != nil { 29 | return err 30 | } 31 | } 32 | 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go: -------------------------------------------------------------------------------- 1 | package airbrake 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/Sirupsen/logrus" 8 | "github.com/tobi/airbrake-go" 9 | ) 10 | 11 | // AirbrakeHook to send exceptions to an exception-tracking service compatible 12 | // with the Airbrake API. 13 | type airbrakeHook struct { 14 | APIKey string 15 | Endpoint string 16 | Environment string 17 | } 18 | 19 | func NewHook(endpoint, apiKey, env string) *airbrakeHook { 20 | return &airbrakeHook{ 21 | APIKey: apiKey, 22 | Endpoint: endpoint, 23 | Environment: env, 24 | } 25 | } 26 | 27 | func (hook *airbrakeHook) Fire(entry *logrus.Entry) error { 28 | airbrake.ApiKey = hook.APIKey 29 | airbrake.Endpoint = hook.Endpoint 30 | airbrake.Environment = hook.Environment 31 | 32 | var notifyErr error 33 | err, ok := entry.Data["error"].(error) 34 | if ok { 35 | notifyErr = err 36 | } else { 37 | notifyErr = errors.New(entry.Message) 38 | } 39 | 40 | airErr := airbrake.Notify(notifyErr) 41 | if airErr != nil { 42 | return fmt.Errorf("Failed to send error to Airbrake: %s", airErr) 43 | } 44 | 45 | return nil 46 | } 47 | 48 | func (hook *airbrakeHook) Levels() []logrus.Level { 49 | return []logrus.Level{ 50 | logrus.ErrorLevel, 51 | logrus.FatalLevel, 52 | logrus.PanicLevel, 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/bugsnag/bugsnag.go: -------------------------------------------------------------------------------- 1 | package logrus_bugsnag 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/Sirupsen/logrus" 7 | "github.com/bugsnag/bugsnag-go" 8 | ) 9 | 10 | type bugsnagHook struct{} 11 | 12 | // ErrBugsnagUnconfigured is returned if NewBugsnagHook is called before 13 | // bugsnag.Configure. Bugsnag must be configured before the hook. 14 | var ErrBugsnagUnconfigured = errors.New("bugsnag must be configured before installing this logrus hook") 15 | 16 | // ErrBugsnagSendFailed indicates that the hook failed to submit an error to 17 | // bugsnag. The error was successfully generated, but `bugsnag.Notify()` 18 | // failed. 19 | type ErrBugsnagSendFailed struct { 20 | err error 21 | } 22 | 23 | func (e ErrBugsnagSendFailed) Error() string { 24 | return "failed to send error to Bugsnag: " + e.err.Error() 25 | } 26 | 27 | // NewBugsnagHook initializes a logrus hook which sends exceptions to an 28 | // exception-tracking service compatible with the Bugsnag API. Before using 29 | // this hook, you must call bugsnag.Configure(). The returned object should be 30 | // registered with a log via `AddHook()` 31 | // 32 | // Entries that trigger an Error, Fatal or Panic should now include an "error" 33 | // field to send to Bugsnag. 34 | func NewBugsnagHook() (*bugsnagHook, error) { 35 | if bugsnag.Config.APIKey == "" { 36 | return nil, ErrBugsnagUnconfigured 37 | } 38 | return &bugsnagHook{}, nil 39 | } 40 | 41 | // Fire forwards an error to Bugsnag. Given a logrus.Entry, it extracts the 42 | // "error" field (or the Message if the error isn't present) and sends it off. 43 | func (hook *bugsnagHook) Fire(entry *logrus.Entry) error { 44 | var notifyErr error 45 | err, ok := entry.Data["error"].(error) 46 | if ok { 47 | notifyErr = err 48 | } else { 49 | notifyErr = errors.New(entry.Message) 50 | } 51 | 52 | bugsnagErr := bugsnag.Notify(notifyErr) 53 | if bugsnagErr != nil { 54 | return ErrBugsnagSendFailed{bugsnagErr} 55 | } 56 | 57 | return nil 58 | } 59 | 60 | // Levels enumerates the log levels on which the error should be forwarded to 61 | // bugsnag: everything at or above the "Error" level. 62 | func (hook *bugsnagHook) Levels() []logrus.Level { 63 | return []logrus.Level{ 64 | logrus.ErrorLevel, 65 | logrus.FatalLevel, 66 | logrus.PanicLevel, 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md: -------------------------------------------------------------------------------- 1 | # Papertrail Hook for Logrus :walrus: 2 | 3 | [Papertrail](https://papertrailapp.com) provides hosted log management. Once stored in Papertrail, you can [group](http://help.papertrailapp.com/kb/how-it-works/groups/) your logs on various dimensions, [search](http://help.papertrailapp.com/kb/how-it-works/search-syntax) them, and trigger [alerts](http://help.papertrailapp.com/kb/how-it-works/alerts). 4 | 5 | In most deployments, you'll want to send logs to Papertrail via their [remote_syslog](http://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-text-log-files-in-unix/) daemon, which requires no application-specific configuration. This hook is intended for relatively low-volume logging, likely in managed cloud hosting deployments where installing `remote_syslog` is not possible. 6 | 7 | ## Usage 8 | 9 | You can find your Papertrail UDP port on your [Papertrail account page](https://papertrailapp.com/account/destinations). Substitute it below for `YOUR_PAPERTRAIL_UDP_PORT`. 10 | 11 | For `YOUR_APP_NAME`, substitute a short string that will readily identify your application or service in the logs. 12 | 13 | ```go 14 | import ( 15 | "log/syslog" 16 | "github.com/Sirupsen/logrus" 17 | "github.com/Sirupsen/logrus/hooks/papertrail" 18 | ) 19 | 20 | func main() { 21 | log := logrus.New() 22 | hook, err := logrus_papertrail.NewPapertrailHook("logs.papertrailapp.com", YOUR_PAPERTRAIL_UDP_PORT, YOUR_APP_NAME) 23 | 24 | if err == nil { 25 | log.Hooks.Add(hook) 26 | } 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go: -------------------------------------------------------------------------------- 1 | package logrus_papertrail 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "time" 8 | 9 | "github.com/Sirupsen/logrus" 10 | ) 11 | 12 | const ( 13 | format = "Jan 2 15:04:05" 14 | ) 15 | 16 | // PapertrailHook to send logs to a logging service compatible with the Papertrail API. 17 | type PapertrailHook struct { 18 | Host string 19 | Port int 20 | AppName string 21 | UDPConn net.Conn 22 | } 23 | 24 | // NewPapertrailHook creates a hook to be added to an instance of logger. 25 | func NewPapertrailHook(host string, port int, appName string) (*PapertrailHook, error) { 26 | conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", host, port)) 27 | return &PapertrailHook{host, port, appName, conn}, err 28 | } 29 | 30 | // Fire is called when a log event is fired. 31 | func (hook *PapertrailHook) Fire(entry *logrus.Entry) error { 32 | date := time.Now().Format(format) 33 | msg, _ := entry.String() 34 | payload := fmt.Sprintf("<22> %s %s: %s", date, hook.AppName, msg) 35 | 36 | bytesWritten, err := hook.UDPConn.Write([]byte(payload)) 37 | if err != nil { 38 | fmt.Fprintf(os.Stderr, "Unable to send log line to Papertrail via UDP. Wrote %d bytes before error: %v", bytesWritten, err) 39 | return err 40 | } 41 | 42 | return nil 43 | } 44 | 45 | // Levels returns the available logging levels. 46 | func (hook *PapertrailHook) Levels() []logrus.Level { 47 | return []logrus.Level{ 48 | logrus.PanicLevel, 49 | logrus.FatalLevel, 50 | logrus.ErrorLevel, 51 | logrus.WarnLevel, 52 | logrus.InfoLevel, 53 | logrus.DebugLevel, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/README.md: -------------------------------------------------------------------------------- 1 | # Sentry Hook for Logrus :walrus: 2 | 3 | [Sentry](https://getsentry.com) provides both self-hosted and hosted 4 | solutions for exception tracking. 5 | Both client and server are 6 | [open source](https://github.com/getsentry/sentry). 7 | 8 | ## Usage 9 | 10 | Every sentry application defined on the server gets a different 11 | [DSN](https://www.getsentry.com/docs/). In the example below replace 12 | `YOUR_DSN` with the one created for your application. 13 | 14 | ```go 15 | import ( 16 | "github.com/Sirupsen/logrus" 17 | "github.com/Sirupsen/logrus/hooks/sentry" 18 | ) 19 | 20 | func main() { 21 | log := logrus.New() 22 | hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{ 23 | logrus.PanicLevel, 24 | logrus.FatalLevel, 25 | logrus.ErrorLevel, 26 | }) 27 | 28 | if err == nil { 29 | log.Hooks.Add(hook) 30 | } 31 | } 32 | ``` 33 | 34 | If you wish to initialize a SentryHook with tags, you can use the `NewWithTagsSentryHook` constructor to provide default tags: 35 | 36 | ```go 37 | tags := map[string]string{ 38 | "site": "example.com", 39 | } 40 | levels := []logrus.Level{ 41 | logrus.PanicLevel, 42 | logrus.FatalLevel, 43 | logrus.ErrorLevel, 44 | } 45 | hook, err := logrus_sentry.NewWithTagsSentryHook(YOUR_DSN, tags, levels) 46 | 47 | ``` 48 | 49 | If you wish to initialize a SentryHook with an already initialized raven client, you can use 50 | the `NewWithClientSentryHook` constructor: 51 | 52 | ```go 53 | import ( 54 | "github.com/Sirupsen/logrus" 55 | "github.com/Sirupsen/logrus/hooks/sentry" 56 | "github.com/getsentry/raven-go" 57 | ) 58 | 59 | func main() { 60 | log := logrus.New() 61 | 62 | client, err := raven.New(YOUR_DSN) 63 | if err != nil { 64 | log.Fatal(err) 65 | } 66 | 67 | hook, err := logrus_sentry.NewWithClientSentryHook(client, []logrus.Level{ 68 | logrus.PanicLevel, 69 | logrus.FatalLevel, 70 | logrus.ErrorLevel, 71 | }) 72 | 73 | if err == nil { 74 | log.Hooks.Add(hook) 75 | } 76 | } 77 | 78 | hook, err := NewWithClientSentryHook(client, []logrus.Level{ 79 | logrus.ErrorLevel, 80 | }) 81 | ``` 82 | 83 | ## Special fields 84 | 85 | Some logrus fields have a special meaning in this hook, 86 | these are `server_name`, `logger` and `http_request`. 87 | When logs are sent to sentry these fields are treated differently. 88 | - `server_name` (also known as hostname) is the name of the server which 89 | is logging the event (hostname.example.com) 90 | - `logger` is the part of the application which is logging the event. 91 | In go this usually means setting it to the name of the package. 92 | - `http_request` is the in-coming request(*http.Request). The detailed request data are sent to Sentry. 93 | 94 | ## Timeout 95 | 96 | `Timeout` is the time the sentry hook will wait for a response 97 | from the sentry server. 98 | 99 | If this time elapses with no response from 100 | the server an error will be returned. 101 | 102 | If `Timeout` is set to 0 the SentryHook will not wait for a reply 103 | and will assume a correct delivery. 104 | 105 | The SentryHook has a default timeout of `100 milliseconds` when created 106 | with a call to `NewSentryHook`. This can be changed by assigning a value to the `Timeout` field: 107 | 108 | ```go 109 | hook, _ := logrus_sentry.NewSentryHook(...) 110 | hook.Timeout = 20*time.Second 111 | ``` 112 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md: -------------------------------------------------------------------------------- 1 | # Syslog Hooks for Logrus :walrus: 2 | 3 | ## Usage 4 | 5 | ```go 6 | import ( 7 | "log/syslog" 8 | "github.com/Sirupsen/logrus" 9 | logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" 10 | ) 11 | 12 | func main() { 13 | log := logrus.New() 14 | hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") 15 | 16 | if err == nil { 17 | log.Hooks.Add(hook) 18 | } 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go: -------------------------------------------------------------------------------- 1 | package logrus_syslog 2 | 3 | import ( 4 | "fmt" 5 | "github.com/Sirupsen/logrus" 6 | "log/syslog" 7 | "os" 8 | ) 9 | 10 | // SyslogHook to send logs via syslog. 11 | type SyslogHook struct { 12 | Writer *syslog.Writer 13 | SyslogNetwork string 14 | SyslogRaddr string 15 | } 16 | 17 | // Creates a hook to be added to an instance of logger. This is called with 18 | // `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")` 19 | // `if err == nil { log.Hooks.Add(hook) }` 20 | func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) { 21 | w, err := syslog.Dial(network, raddr, priority, tag) 22 | return &SyslogHook{w, network, raddr}, err 23 | } 24 | 25 | func (hook *SyslogHook) Fire(entry *logrus.Entry) error { 26 | line, err := entry.String() 27 | if err != nil { 28 | fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) 29 | return err 30 | } 31 | 32 | switch entry.Level { 33 | case logrus.PanicLevel: 34 | return hook.Writer.Crit(line) 35 | case logrus.FatalLevel: 36 | return hook.Writer.Crit(line) 37 | case logrus.ErrorLevel: 38 | return hook.Writer.Err(line) 39 | case logrus.WarnLevel: 40 | return hook.Writer.Warning(line) 41 | case logrus.InfoLevel: 42 | return hook.Writer.Info(line) 43 | case logrus.DebugLevel: 44 | return hook.Writer.Debug(line) 45 | default: 46 | return nil 47 | } 48 | } 49 | 50 | func (hook *SyslogHook) Levels() []logrus.Level { 51 | return []logrus.Level{ 52 | logrus.PanicLevel, 53 | logrus.FatalLevel, 54 | logrus.ErrorLevel, 55 | logrus.WarnLevel, 56 | logrus.InfoLevel, 57 | logrus.DebugLevel, 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type JSONFormatter struct { 9 | // TimestampFormat sets the format used for marshaling timestamps. 10 | TimestampFormat string 11 | } 12 | 13 | func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { 14 | data := make(Fields, len(entry.Data)+3) 15 | for k, v := range entry.Data { 16 | switch v := v.(type) { 17 | case error: 18 | // Otherwise errors are ignored by `encoding/json` 19 | // https://github.com/Sirupsen/logrus/issues/137 20 | data[k] = v.Error() 21 | default: 22 | data[k] = v 23 | } 24 | } 25 | prefixFieldClashes(data) 26 | 27 | timestampFormat := f.TimestampFormat 28 | if timestampFormat == "" { 29 | timestampFormat = DefaultTimestampFormat 30 | } 31 | 32 | data["time"] = entry.Time.Format(timestampFormat) 33 | data["msg"] = entry.Message 34 | data["level"] = entry.Level.String() 35 | 36 | serialized, err := json.Marshal(data) 37 | if err != nil { 38 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 39 | } 40 | return append(serialized, '\n'), nil 41 | } 42 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | // Fields type, used to pass to `WithFields`. 9 | type Fields map[string]interface{} 10 | 11 | // Level type 12 | type Level uint8 13 | 14 | // Convert the Level to a string. E.g. PanicLevel becomes "panic". 15 | func (level Level) String() string { 16 | switch level { 17 | case DebugLevel: 18 | return "debug" 19 | case InfoLevel: 20 | return "info" 21 | case WarnLevel: 22 | return "warning" 23 | case ErrorLevel: 24 | return "error" 25 | case FatalLevel: 26 | return "fatal" 27 | case PanicLevel: 28 | return "panic" 29 | } 30 | 31 | return "unknown" 32 | } 33 | 34 | // ParseLevel takes a string level and returns the Logrus log level constant. 35 | func ParseLevel(lvl string) (Level, error) { 36 | switch lvl { 37 | case "panic": 38 | return PanicLevel, nil 39 | case "fatal": 40 | return FatalLevel, nil 41 | case "error": 42 | return ErrorLevel, nil 43 | case "warn", "warning": 44 | return WarnLevel, nil 45 | case "info": 46 | return InfoLevel, nil 47 | case "debug": 48 | return DebugLevel, nil 49 | } 50 | 51 | var l Level 52 | return l, fmt.Errorf("not a valid logrus Level: %q", lvl) 53 | } 54 | 55 | // These are the different logging levels. You can set the logging level to log 56 | // on your instance of logger, obtained with `logrus.New()`. 57 | const ( 58 | // PanicLevel level, highest level of severity. Logs and then calls panic with the 59 | // message passed to Debug, Info, ... 60 | PanicLevel Level = iota 61 | // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the 62 | // logging level is set to Panic. 63 | FatalLevel 64 | // ErrorLevel level. Logs. Used for errors that should definitely be noted. 65 | // Commonly used for hooks to send errors to an error tracking service. 66 | ErrorLevel 67 | // WarnLevel level. Non-critical entries that deserve eyes. 68 | WarnLevel 69 | // InfoLevel level. General operational entries about what's going on inside the 70 | // application. 71 | InfoLevel 72 | // DebugLevel level. Usually only enabled when debugging. Very verbose logging. 73 | DebugLevel 74 | ) 75 | 76 | // Won't compile if StdLogger can't be realized by a log.Logger 77 | var ( 78 | _ StdLogger = &log.Logger{} 79 | _ StdLogger = &Entry{} 80 | _ StdLogger = &Logger{} 81 | ) 82 | 83 | // StdLogger is what your logrus-enabled library should take, that way 84 | // it'll accept a stdlib logger and a logrus logger. There's no standard 85 | // interface, this is the closest we get, unfortunately. 86 | type StdLogger interface { 87 | Print(...interface{}) 88 | Printf(string, ...interface{}) 89 | Println(...interface{}) 90 | 91 | Fatal(...interface{}) 92 | Fatalf(string, ...interface{}) 93 | Fatalln(...interface{}) 94 | 95 | Panic(...interface{}) 96 | Panicf(string, ...interface{}) 97 | Panicln(...interface{}) 98 | } 99 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd openbsd netbsd dragonfly 2 | 3 | package logrus 4 | 5 | import "syscall" 6 | 7 | const ioctlReadTermios = syscall.TIOCGETA 8 | 9 | type Termios syscall.Termios 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2013 The Go Authors. 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 logrus 7 | 8 | import "syscall" 9 | 10 | const ioctlReadTermios = syscall.TCGETS 11 | 12 | type Termios syscall.Termios 13 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. 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 | // +build linux darwin freebsd openbsd netbsd dragonfly 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | // IsTerminal returns true if the given file descriptor is a terminal. 16 | func IsTerminal() bool { 17 | fd := syscall.Stdout 18 | var termios Termios 19 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 20 | return err == 0 21 | } 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. 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 | // +build windows 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 16 | 17 | var ( 18 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 19 | ) 20 | 21 | // IsTerminal returns true if the given file descriptor is a terminal. 22 | func IsTerminal() bool { 23 | fd := syscall.Stdout 24 | var st uint32 25 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 26 | return r != 0 && e == 0 27 | } 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/Sirupsen/logrus/writer.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "runtime" 7 | ) 8 | 9 | func (logger *Logger) Writer() *io.PipeWriter { 10 | reader, writer := io.Pipe() 11 | 12 | go logger.writerScanner(reader) 13 | runtime.SetFinalizer(writer, writerFinalizer) 14 | 15 | return writer 16 | } 17 | 18 | func (logger *Logger) writerScanner(reader *io.PipeReader) { 19 | scanner := bufio.NewScanner(reader) 20 | for scanner.Scan() { 21 | logger.Print(scanner.Text()) 22 | } 23 | if err := scanner.Err(); err != nil { 24 | logger.Errorf("Error while reading from Writer: %s", err) 25 | } 26 | reader.Close() 27 | } 28 | 29 | func writerFinalizer(writer *io.PipeWriter) { 30 | writer.Close() 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/.gitignore: -------------------------------------------------------------------------------- 1 | *.prof 2 | *.test 3 | *.swp 4 | /bin/ 5 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Ben Johnson 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/boltdb/bolt/Makefile: -------------------------------------------------------------------------------- 1 | TEST=. 2 | BENCH=. 3 | COVERPROFILE=/tmp/c.out 4 | BRANCH=`git rev-parse --abbrev-ref HEAD` 5 | COMMIT=`git rev-parse --short HEAD` 6 | GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" 7 | 8 | default: build 9 | 10 | bench: 11 | go test -v -test.run=NOTHINCONTAINSTHIS -test.bench=$(BENCH) 12 | 13 | # http://cloc.sourceforge.net/ 14 | cloc: 15 | @cloc --not-match-f='Makefile|_test.go' . 16 | 17 | cover: fmt 18 | go test -coverprofile=$(COVERPROFILE) -test.run=$(TEST) $(COVERFLAG) . 19 | go tool cover -html=$(COVERPROFILE) 20 | rm $(COVERPROFILE) 21 | 22 | cpuprofile: fmt 23 | @go test -c 24 | @./bolt.test -test.v -test.run=$(TEST) -test.cpuprofile cpu.prof 25 | 26 | # go get github.com/kisielk/errcheck 27 | errcheck: 28 | @echo "=== errcheck ===" 29 | @errcheck github.com/boltdb/bolt 30 | 31 | fmt: 32 | @go fmt ./... 33 | 34 | get: 35 | @go get -d ./... 36 | 37 | build: get 38 | @mkdir -p bin 39 | @go build -ldflags=$(GOLDFLAGS) -a -o bin/bolt ./cmd/bolt 40 | 41 | test: fmt 42 | @go get github.com/stretchr/testify/assert 43 | @echo "=== TESTS ===" 44 | @go test -v -cover -test.run=$(TEST) 45 | @echo "" 46 | @echo "" 47 | @echo "=== CLI ===" 48 | @go test -v -test.run=$(TEST) ./cmd/bolt 49 | @echo "" 50 | @echo "" 51 | @echo "=== RACE DETECTOR ===" 52 | @go test -v -race -test.run="TestSimulate_(100op|1000op)" 53 | 54 | .PHONY: bench cloc cover cpuprofile fmt memprofile test 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/batch.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | // Batch calls fn as part of a batch. It behaves similar to Update, 11 | // except: 12 | // 13 | // 1. concurrent Batch calls can be combined into a single Bolt 14 | // transaction. 15 | // 16 | // 2. the function passed to Batch may be called multiple times, 17 | // regardless of whether it returns error or not. 18 | // 19 | // This means that Batch function side effects must be idempotent and 20 | // take permanent effect only after a successful return is seen in 21 | // caller. 22 | // 23 | // The maximum batch size and delay can be adjusted with DB.MaxBatchSize 24 | // and DB.MaxBatchDelay, respectively. 25 | // 26 | // Batch is only useful when there are multiple goroutines calling it. 27 | func (db *DB) Batch(fn func(*Tx) error) error { 28 | errCh := make(chan error, 1) 29 | 30 | db.batchMu.Lock() 31 | if (db.batch == nil) || (db.batch != nil && len(db.batch.calls) >= db.MaxBatchSize) { 32 | // There is no existing batch, or the existing batch is full; start a new one. 33 | db.batch = &batch{ 34 | db: db, 35 | } 36 | db.batch.timer = time.AfterFunc(db.MaxBatchDelay, db.batch.trigger) 37 | } 38 | db.batch.calls = append(db.batch.calls, call{fn: fn, err: errCh}) 39 | if len(db.batch.calls) >= db.MaxBatchSize { 40 | // wake up batch, it's ready to run 41 | go db.batch.trigger() 42 | } 43 | db.batchMu.Unlock() 44 | 45 | err := <-errCh 46 | if err == trySolo { 47 | err = db.Update(fn) 48 | } 49 | return err 50 | } 51 | 52 | type call struct { 53 | fn func(*Tx) error 54 | err chan<- error 55 | } 56 | 57 | type batch struct { 58 | db *DB 59 | timer *time.Timer 60 | start sync.Once 61 | calls []call 62 | } 63 | 64 | // trigger runs the batch if it hasn't already been run. 65 | func (b *batch) trigger() { 66 | b.start.Do(b.run) 67 | } 68 | 69 | // run performs the transactions in the batch and communicates results 70 | // back to DB.Batch. 71 | func (b *batch) run() { 72 | b.db.batchMu.Lock() 73 | b.timer.Stop() 74 | // Make sure no new work is added to this batch, but don't break 75 | // other batches. 76 | if b.db.batch == b { 77 | b.db.batch = nil 78 | } 79 | b.db.batchMu.Unlock() 80 | 81 | retry: 82 | for len(b.calls) > 0 { 83 | var failIdx = -1 84 | err := b.db.Update(func(tx *Tx) error { 85 | for i, c := range b.calls { 86 | if err := safelyCall(c.fn, tx); err != nil { 87 | failIdx = i 88 | return err 89 | } 90 | } 91 | return nil 92 | }) 93 | 94 | if failIdx >= 0 { 95 | // take the failing transaction out of the batch. it's 96 | // safe to shorten b.calls here because db.batch no longer 97 | // points to us, and we hold the mutex anyway. 98 | c := b.calls[failIdx] 99 | b.calls[failIdx], b.calls = b.calls[len(b.calls)-1], b.calls[:len(b.calls)-1] 100 | // tell the submitter re-run it solo, continue with the rest of the batch 101 | c.err <- trySolo 102 | continue retry 103 | } 104 | 105 | // pass success, or bolt internal errors, to all callers 106 | for _, c := range b.calls { 107 | if c.err != nil { 108 | c.err <- err 109 | } 110 | } 111 | break retry 112 | } 113 | } 114 | 115 | // trySolo is a special sentinel error value used for signaling that a 116 | // transaction function should be re-run. It should never be seen by 117 | // callers. 118 | var trySolo = errors.New("batch function returned an error and should be re-run solo") 119 | 120 | type panicked struct { 121 | reason interface{} 122 | } 123 | 124 | func (p panicked) Error() string { 125 | if err, ok := p.reason.(error); ok { 126 | return err.Error() 127 | } 128 | return fmt.Sprintf("panic: %v", p.reason) 129 | } 130 | 131 | func safelyCall(fn func(*Tx) error, tx *Tx) (err error) { 132 | defer func() { 133 | if p := recover(); p != nil { 134 | err = panicked{p} 135 | } 136 | }() 137 | return fn(tx) 138 | } 139 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_386.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_amd64.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0x7FFFFFFF 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_arm.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_linux.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | var odirect = syscall.O_DIRECT 8 | 9 | // fdatasync flushes written data to a file descriptor. 10 | func fdatasync(db *DB) error { 11 | return syscall.Fdatasync(int(db.file.Fd())) 12 | } 13 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_openbsd.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | msAsync = 1 << iota // perform asynchronous writes 10 | msSync // perform synchronous writes 11 | msInvalidate // invalidate cached data 12 | ) 13 | 14 | var odirect int 15 | 16 | func msync(db *DB) error { 17 | _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate) 18 | if errno != 0 { 19 | return errno 20 | } 21 | return nil 22 | } 23 | 24 | func fdatasync(db *DB) error { 25 | if db.data != nil { 26 | return msync(db) 27 | } 28 | return db.file.Sync() 29 | } 30 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!solaris 2 | 3 | package bolt 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "syscall" 9 | "time" 10 | "unsafe" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(f *os.File, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | flag := syscall.LOCK_SH 25 | if exclusive { 26 | flag = syscall.LOCK_EX 27 | } 28 | 29 | // Otherwise attempt to obtain an exclusive lock. 30 | err := syscall.Flock(int(f.Fd()), flag|syscall.LOCK_NB) 31 | if err == nil { 32 | return nil 33 | } else if err != syscall.EWOULDBLOCK { 34 | return err 35 | } 36 | 37 | // Wait for a bit and try again. 38 | time.Sleep(50 * time.Millisecond) 39 | } 40 | } 41 | 42 | // funlock releases an advisory lock on a file descriptor. 43 | func funlock(f *os.File) error { 44 | return syscall.Flock(int(f.Fd()), syscall.LOCK_UN) 45 | } 46 | 47 | // mmap memory maps a DB's data file. 48 | func mmap(db *DB, sz int) error { 49 | // Truncate and fsync to ensure file size metadata is flushed. 50 | // https://github.com/boltdb/bolt/issues/284 51 | if !db.NoGrowSync && !db.readOnly { 52 | if err := db.file.Truncate(int64(sz)); err != nil { 53 | return fmt.Errorf("file resize error: %s", err) 54 | } 55 | if err := db.file.Sync(); err != nil { 56 | return fmt.Errorf("file sync error: %s", err) 57 | } 58 | } 59 | 60 | // Map the data file to memory. 61 | b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | // Advise the kernel that the mmap is accessed randomly. 67 | if err := madvise(b, syscall.MADV_RANDOM); err != nil { 68 | return fmt.Errorf("madvise: %s", err) 69 | } 70 | 71 | // Save the original byte slice and convert to a byte array pointer. 72 | db.dataref = b 73 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 74 | db.datasz = sz 75 | return nil 76 | } 77 | 78 | // munmap unmaps a DB's data file from memory. 79 | func munmap(db *DB) error { 80 | // Ignore the unmap if we have no mapped data. 81 | if db.dataref == nil { 82 | return nil 83 | } 84 | 85 | // Unmap using the original byte slice. 86 | err := syscall.Munmap(db.dataref) 87 | db.dataref = nil 88 | db.data = nil 89 | db.datasz = 0 90 | return err 91 | } 92 | 93 | // NOTE: This function is copied from stdlib because it is not available on darwin. 94 | func madvise(b []byte, advice int) (err error) { 95 | _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice)) 96 | if e1 != 0 { 97 | err = e1 98 | } 99 | return 100 | } 101 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_unix_solaris.go: -------------------------------------------------------------------------------- 1 | 2 | package bolt 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | "syscall" 8 | "time" 9 | "unsafe" 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(f *os.File, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | var lock syscall.Flock_t 25 | lock.Start = 0 26 | lock.Len = 0 27 | lock.Pid = 0 28 | lock.Whence = 0 29 | lock.Pid = 0 30 | if exclusive { 31 | lock.Type = syscall.F_WRLCK 32 | } else { 33 | lock.Type = syscall.F_RDLCK 34 | } 35 | err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &lock) 36 | if err == nil { 37 | return nil 38 | } else if err != syscall.EAGAIN { 39 | return err 40 | } 41 | 42 | // Wait for a bit and try again. 43 | time.Sleep(50 * time.Millisecond) 44 | } 45 | } 46 | 47 | // funlock releases an advisory lock on a file descriptor. 48 | func funlock(f *os.File) error { 49 | var lock syscall.Flock_t 50 | lock.Start = 0 51 | lock.Len = 0 52 | lock.Type = syscall.F_UNLCK 53 | lock.Whence = 0 54 | return syscall.FcntlFlock(uintptr(f.Fd()), syscall.F_SETLK, &lock) 55 | } 56 | 57 | // mmap memory maps a DB's data file. 58 | func mmap(db *DB, sz int) error { 59 | // Truncate and fsync to ensure file size metadata is flushed. 60 | // https://github.com/boltdb/bolt/issues/284 61 | if !db.NoGrowSync && !db.readOnly { 62 | if err := db.file.Truncate(int64(sz)); err != nil { 63 | return fmt.Errorf("file resize error: %s", err) 64 | } 65 | if err := db.file.Sync(); err != nil { 66 | return fmt.Errorf("file sync error: %s", err) 67 | } 68 | } 69 | 70 | // Map the data file to memory. 71 | b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | // Advise the kernel that the mmap is accessed randomly. 77 | if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { 78 | return fmt.Errorf("madvise: %s", err) 79 | } 80 | 81 | // Save the original byte slice and convert to a byte array pointer. 82 | db.dataref = b 83 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 84 | db.datasz = sz 85 | return nil 86 | } 87 | 88 | // munmap unmaps a DB's data file from memory. 89 | func munmap(db *DB) error { 90 | // Ignore the unmap if we have no mapped data. 91 | if db.dataref == nil { 92 | return nil 93 | } 94 | 95 | // Unmap using the original byte slice. 96 | err := unix.Munmap(db.dataref) 97 | db.dataref = nil 98 | db.data = nil 99 | db.datasz = 0 100 | return err 101 | } 102 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_windows.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | "time" 8 | "unsafe" 9 | ) 10 | 11 | var odirect int 12 | 13 | // fdatasync flushes written data to a file descriptor. 14 | func fdatasync(db *DB) error { 15 | return db.file.Sync() 16 | } 17 | 18 | // flock acquires an advisory lock on a file descriptor. 19 | func flock(f *os.File, _ bool, _ time.Duration) error { 20 | return nil 21 | } 22 | 23 | // funlock releases an advisory lock on a file descriptor. 24 | func funlock(f *os.File) error { 25 | return nil 26 | } 27 | 28 | // mmap memory maps a DB's data file. 29 | // Based on: https://github.com/edsrzf/mmap-go 30 | func mmap(db *DB, sz int) error { 31 | if !db.readOnly { 32 | // Truncate the database to the size of the mmap. 33 | if err := db.file.Truncate(int64(sz)); err != nil { 34 | return fmt.Errorf("truncate: %s", err) 35 | } 36 | } 37 | 38 | // Open a file mapping handle. 39 | sizelo := uint32(sz >> 32) 40 | sizehi := uint32(sz) & 0xffffffff 41 | h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil) 42 | if h == 0 { 43 | return os.NewSyscallError("CreateFileMapping", errno) 44 | } 45 | 46 | // Create the memory map. 47 | addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz)) 48 | if addr == 0 { 49 | return os.NewSyscallError("MapViewOfFile", errno) 50 | } 51 | 52 | // Close mapping handle. 53 | if err := syscall.CloseHandle(syscall.Handle(h)); err != nil { 54 | return os.NewSyscallError("CloseHandle", err) 55 | } 56 | 57 | // Convert to a byte array. 58 | db.data = ((*[maxMapSize]byte)(unsafe.Pointer(addr))) 59 | db.datasz = sz 60 | 61 | return nil 62 | } 63 | 64 | // munmap unmaps a pointer from a file. 65 | // Based on: https://github.com/edsrzf/mmap-go 66 | func munmap(db *DB) error { 67 | if db.data == nil { 68 | return nil 69 | } 70 | 71 | addr := (uintptr)(unsafe.Pointer(&db.data[0])) 72 | if err := syscall.UnmapViewOfFile(addr); err != nil { 73 | return os.NewSyscallError("UnmapViewOfFile", err) 74 | } 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/boltsync_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!linux,!openbsd 2 | 3 | package bolt 4 | 5 | var odirect int 6 | 7 | // fdatasync flushes written data to a file descriptor. 8 | func fdatasync(db *DB) error { 9 | return db.file.Sync() 10 | } 11 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package bolt implements a low-level key/value store in pure Go. It supports 3 | fully serializable transactions, ACID semantics, and lock-free MVCC with 4 | multiple readers and a single writer. Bolt can be used for projects that 5 | want a simple data store without the need to add large dependencies such as 6 | Postgres or MySQL. 7 | 8 | Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is 9 | optimized for fast read access and does not require recovery in the event of a 10 | system crash. Transactions which have not finished committing will simply be 11 | rolled back in the event of a crash. 12 | 13 | The design of Bolt is based on Howard Chu's LMDB database project. 14 | 15 | Bolt currently works on Windows, Mac OS X, and Linux. 16 | 17 | 18 | Basics 19 | 20 | There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is 21 | a collection of buckets and is represented by a single file on disk. A bucket is 22 | a collection of unique keys that are associated with values. 23 | 24 | Transactions provide either read-only or read-write access to the database. 25 | Read-only transactions can retrieve key/value pairs and can use Cursors to 26 | iterate over the dataset sequentially. Read-write transactions can create and 27 | delete buckets and can insert and remove keys. Only one read-write transaction 28 | is allowed at a time. 29 | 30 | 31 | Caveats 32 | 33 | The database uses a read-only, memory-mapped data file to ensure that 34 | applications cannot corrupt the database, however, this means that keys and 35 | values returned from Bolt cannot be changed. Writing to a read-only byte slice 36 | will cause Go to panic. 37 | 38 | Keys and values retrieved from the database are only valid for the life of 39 | the transaction. When used outside the transaction, these byte slices can 40 | point to different data or can point to invalid memory which will cause a panic. 41 | 42 | 43 | */ 44 | package bolt 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/errors.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import "errors" 4 | 5 | // These errors can be returned when opening or calling methods on a DB. 6 | var ( 7 | // ErrDatabaseNotOpen is returned when a DB instance is accessed before it 8 | // is opened or after it is closed. 9 | ErrDatabaseNotOpen = errors.New("database not open") 10 | 11 | // ErrDatabaseOpen is returned when opening a database that is 12 | // already open. 13 | ErrDatabaseOpen = errors.New("database already open") 14 | 15 | // ErrInvalid is returned when a data file is not a Bolt-formatted database. 16 | ErrInvalid = errors.New("invalid database") 17 | 18 | // ErrVersionMismatch is returned when the data file was created with a 19 | // different version of Bolt. 20 | ErrVersionMismatch = errors.New("version mismatch") 21 | 22 | // ErrChecksum is returned when either meta page checksum does not match. 23 | ErrChecksum = errors.New("checksum error") 24 | 25 | // ErrTimeout is returned when a database cannot obtain an exclusive lock 26 | // on the data file after the timeout passed to Open(). 27 | ErrTimeout = errors.New("timeout") 28 | ) 29 | 30 | // These errors can occur when beginning or committing a Tx. 31 | var ( 32 | // ErrTxNotWritable is returned when performing a write operation on a 33 | // read-only transaction. 34 | ErrTxNotWritable = errors.New("tx not writable") 35 | 36 | // ErrTxClosed is returned when committing or rolling back a transaction 37 | // that has already been committed or rolled back. 38 | ErrTxClosed = errors.New("tx closed") 39 | 40 | // ErrDatabaseReadOnly is returned when a mutating transaction is started on a 41 | // read-only database. 42 | ErrDatabaseReadOnly = errors.New("database is in read-only mode") 43 | ) 44 | 45 | // These errors can occur when putting or deleting a value or a bucket. 46 | var ( 47 | // ErrBucketNotFound is returned when trying to access a bucket that has 48 | // not been created yet. 49 | ErrBucketNotFound = errors.New("bucket not found") 50 | 51 | // ErrBucketExists is returned when creating a bucket that already exists. 52 | ErrBucketExists = errors.New("bucket already exists") 53 | 54 | // ErrBucketNameRequired is returned when creating a bucket with a blank name. 55 | ErrBucketNameRequired = errors.New("bucket name required") 56 | 57 | // ErrKeyRequired is returned when inserting a zero-length key. 58 | ErrKeyRequired = errors.New("key required") 59 | 60 | // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize. 61 | ErrKeyTooLarge = errors.New("key too large") 62 | 63 | // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize. 64 | ErrValueTooLarge = errors.New("value too large") 65 | 66 | // ErrIncompatibleValue is returned when trying create or delete a bucket 67 | // on an existing non-bucket key or when trying to create or delete a 68 | // non-bucket key on an existing bucket key. 69 | ErrIncompatibleValue = errors.New("incompatible value") 70 | ) 71 | -------------------------------------------------------------------------------- /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/cluster.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | "sync" 7 | ) 8 | 9 | type Cluster struct { 10 | Leader string `json:"leader"` 11 | Machines []string `json:"machines"` 12 | picked int 13 | mu sync.RWMutex 14 | } 15 | 16 | func NewCluster(machines []string) *Cluster { 17 | // if an empty slice was sent in then just assume HTTP 4001 on localhost 18 | if len(machines) == 0 { 19 | machines = []string{"http://127.0.0.1:4001"} 20 | } 21 | 22 | machines = shuffleStringSlice(machines) 23 | logger.Debug("Shuffle cluster machines", machines) 24 | // default leader and machines 25 | return &Cluster{ 26 | Leader: "", 27 | Machines: machines, 28 | picked: rand.Intn(len(machines)), 29 | } 30 | } 31 | 32 | func (cl *Cluster) failure() { 33 | cl.mu.Lock() 34 | defer cl.mu.Unlock() 35 | cl.picked = (cl.picked + 1) % len(cl.Machines) 36 | } 37 | 38 | func (cl *Cluster) pick() string { 39 | cl.mu.Lock() 40 | defer cl.mu.Unlock() 41 | return cl.Machines[cl.picked] 42 | } 43 | 44 | func (cl *Cluster) updateFromStr(machines string) { 45 | cl.mu.Lock() 46 | defer cl.mu.Unlock() 47 | 48 | cl.Machines = strings.Split(machines, ",") 49 | for i := range cl.Machines { 50 | cl.Machines[i] = strings.TrimSpace(cl.Machines[i]) 51 | } 52 | cl.Machines = shuffleStringSlice(cl.Machines) 53 | cl.picked = rand.Intn(len(cl.Machines)) 54 | } 55 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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/coreos/go-etcd/etcd/response.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | //go:generate codecgen -o response.generated.go response.go 4 | 5 | import ( 6 | "net/http" 7 | "strconv" 8 | "time" 9 | 10 | "github.com/ugorji/go/codec" 11 | ) 12 | 13 | const ( 14 | rawResponse = iota 15 | normalResponse 16 | ) 17 | 18 | type responseType int 19 | 20 | type RawResponse struct { 21 | StatusCode int 22 | Body []byte 23 | Header http.Header 24 | } 25 | 26 | var ( 27 | validHttpStatusCode = map[int]bool{ 28 | http.StatusCreated: true, 29 | http.StatusOK: true, 30 | http.StatusBadRequest: true, 31 | http.StatusNotFound: true, 32 | http.StatusPreconditionFailed: true, 33 | http.StatusForbidden: true, 34 | http.StatusUnauthorized: true, 35 | } 36 | ) 37 | 38 | // Unmarshal parses RawResponse and stores the result in Response 39 | func (rr *RawResponse) Unmarshal() (*Response, error) { 40 | if rr.StatusCode != http.StatusOK && rr.StatusCode != http.StatusCreated { 41 | return nil, handleError(rr.Body) 42 | } 43 | 44 | resp := new(Response) 45 | 46 | err := codec.NewDecoderBytes(rr.Body, new(codec.JsonHandle)).Decode(resp) 47 | 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | // attach index and term to response 53 | resp.EtcdIndex, _ = strconv.ParseUint(rr.Header.Get("X-Etcd-Index"), 10, 64) 54 | resp.RaftIndex, _ = strconv.ParseUint(rr.Header.Get("X-Raft-Index"), 10, 64) 55 | resp.RaftTerm, _ = strconv.ParseUint(rr.Header.Get("X-Raft-Term"), 10, 64) 56 | 57 | return resp, nil 58 | } 59 | 60 | type Response struct { 61 | Action string `json:"action"` 62 | Node *Node `json:"node"` 63 | PrevNode *Node `json:"prevNode,omitempty"` 64 | EtcdIndex uint64 `json:"etcdIndex"` 65 | RaftIndex uint64 `json:"raftIndex"` 66 | RaftTerm uint64 `json:"raftTerm"` 67 | } 68 | 69 | type Node struct { 70 | Key string `json:"key, omitempty"` 71 | Value string `json:"value,omitempty"` 72 | Dir bool `json:"dir,omitempty"` 73 | Expiration *time.Time `json:"expiration,omitempty"` 74 | TTL int64 `json:"ttl,omitempty"` 75 | Nodes Nodes `json:"nodes,omitempty"` 76 | ModifiedIndex uint64 `json:"modifiedIndex,omitempty"` 77 | CreatedIndex uint64 `json:"createdIndex,omitempty"` 78 | } 79 | 80 | type Nodes []*Node 81 | 82 | // interfaces for sorting 83 | func (ns Nodes) Len() int { 84 | return len(ns) 85 | } 86 | 87 | func (ns Nodes) Less(i, j int) bool { 88 | return ns[i].Key < ns[j].Key 89 | } 90 | 91 | func (ns Nodes) Swap(i, j int) { 92 | ns[i], ns[j] = ns[j], ns[i] 93 | } 94 | -------------------------------------------------------------------------------- /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/coreos/go-etcd/etcd/shuffle.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "math/rand" 5 | ) 6 | 7 | func shuffleStringSlice(cards []string) []string { 8 | size := len(cards) 9 | //Do not need to copy if nothing changed 10 | if size <= 1 { 11 | return cards 12 | } 13 | shuffled := make([]string, size) 14 | index := rand.Perm(size) 15 | for i := range cards { 16 | shuffled[index[i]] = cards[i] 17 | } 18 | return shuffled 19 | } 20 | -------------------------------------------------------------------------------- /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+git" 6 | ) 7 | -------------------------------------------------------------------------------- /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/docker/docker/pkg/signal/README.md: -------------------------------------------------------------------------------- 1 | This package provides helper functions for dealing with signals across various operating systems -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/signal.go: -------------------------------------------------------------------------------- 1 | // Package signal provides helper functions for dealing with signals across 2 | // various operating systems. 3 | package signal 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "os/signal" 9 | "strconv" 10 | "strings" 11 | "syscall" 12 | ) 13 | 14 | // CatchAll catches all signals and relays them to the specified channel. 15 | func CatchAll(sigc chan os.Signal) { 16 | handledSigs := []os.Signal{} 17 | for _, s := range SignalMap { 18 | handledSigs = append(handledSigs, s) 19 | } 20 | signal.Notify(sigc, handledSigs...) 21 | } 22 | 23 | // StopCatch stops catching the signals and closes the specified channel. 24 | func StopCatch(sigc chan os.Signal) { 25 | signal.Stop(sigc) 26 | close(sigc) 27 | } 28 | 29 | // ParseSignal translates a string to a valid syscall signal. 30 | // It returns an error if the signal map doesn't include the given signal. 31 | func ParseSignal(rawSignal string) (syscall.Signal, error) { 32 | s, err := strconv.Atoi(rawSignal) 33 | if err == nil { 34 | if s == 0 { 35 | return -1, fmt.Errorf("Invalid signal: %s", rawSignal) 36 | } 37 | return syscall.Signal(s), nil 38 | } 39 | signal, ok := SignalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")] 40 | if !ok { 41 | return -1, fmt.Errorf("Invalid signal: %s", rawSignal) 42 | } 43 | return signal, nil 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/signal_darwin.go: -------------------------------------------------------------------------------- 1 | package signal 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | // SignalMap is a map of Darwin signals. 8 | var SignalMap = map[string]syscall.Signal{ 9 | "ABRT": syscall.SIGABRT, 10 | "ALRM": syscall.SIGALRM, 11 | "BUG": syscall.SIGBUS, 12 | "CHLD": syscall.SIGCHLD, 13 | "CONT": syscall.SIGCONT, 14 | "EMT": syscall.SIGEMT, 15 | "FPE": syscall.SIGFPE, 16 | "HUP": syscall.SIGHUP, 17 | "ILL": syscall.SIGILL, 18 | "INFO": syscall.SIGINFO, 19 | "INT": syscall.SIGINT, 20 | "IO": syscall.SIGIO, 21 | "IOT": syscall.SIGIOT, 22 | "KILL": syscall.SIGKILL, 23 | "PIPE": syscall.SIGPIPE, 24 | "PROF": syscall.SIGPROF, 25 | "QUIT": syscall.SIGQUIT, 26 | "SEGV": syscall.SIGSEGV, 27 | "STOP": syscall.SIGSTOP, 28 | "SYS": syscall.SIGSYS, 29 | "TERM": syscall.SIGTERM, 30 | "TRAP": syscall.SIGTRAP, 31 | "TSTP": syscall.SIGTSTP, 32 | "TTIN": syscall.SIGTTIN, 33 | "TTOU": syscall.SIGTTOU, 34 | "URG": syscall.SIGURG, 35 | "USR1": syscall.SIGUSR1, 36 | "USR2": syscall.SIGUSR2, 37 | "VTALRM": syscall.SIGVTALRM, 38 | "WINCH": syscall.SIGWINCH, 39 | "XCPU": syscall.SIGXCPU, 40 | "XFSZ": syscall.SIGXFSZ, 41 | } 42 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/signal_freebsd.go: -------------------------------------------------------------------------------- 1 | package signal 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | // SignalMap is a map of FreeBSD signals. 8 | var SignalMap = map[string]syscall.Signal{ 9 | "ABRT": syscall.SIGABRT, 10 | "ALRM": syscall.SIGALRM, 11 | "BUF": syscall.SIGBUS, 12 | "CHLD": syscall.SIGCHLD, 13 | "CONT": syscall.SIGCONT, 14 | "EMT": syscall.SIGEMT, 15 | "FPE": syscall.SIGFPE, 16 | "HUP": syscall.SIGHUP, 17 | "ILL": syscall.SIGILL, 18 | "INFO": syscall.SIGINFO, 19 | "INT": syscall.SIGINT, 20 | "IO": syscall.SIGIO, 21 | "IOT": syscall.SIGIOT, 22 | "KILL": syscall.SIGKILL, 23 | "LWP": syscall.SIGLWP, 24 | "PIPE": syscall.SIGPIPE, 25 | "PROF": syscall.SIGPROF, 26 | "QUIT": syscall.SIGQUIT, 27 | "SEGV": syscall.SIGSEGV, 28 | "STOP": syscall.SIGSTOP, 29 | "SYS": syscall.SIGSYS, 30 | "TERM": syscall.SIGTERM, 31 | "THR": syscall.SIGTHR, 32 | "TRAP": syscall.SIGTRAP, 33 | "TSTP": syscall.SIGTSTP, 34 | "TTIN": syscall.SIGTTIN, 35 | "TTOU": syscall.SIGTTOU, 36 | "URG": syscall.SIGURG, 37 | "USR1": syscall.SIGUSR1, 38 | "USR2": syscall.SIGUSR2, 39 | "VTALRM": syscall.SIGVTALRM, 40 | "WINCH": syscall.SIGWINCH, 41 | "XCPU": syscall.SIGXCPU, 42 | "XFSZ": syscall.SIGXFSZ, 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/signal_linux.go: -------------------------------------------------------------------------------- 1 | package signal 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | // SignalMap is a map of Linux signals. 8 | var SignalMap = map[string]syscall.Signal{ 9 | "ABRT": syscall.SIGABRT, 10 | "ALRM": syscall.SIGALRM, 11 | "BUS": syscall.SIGBUS, 12 | "CHLD": syscall.SIGCHLD, 13 | "CLD": syscall.SIGCLD, 14 | "CONT": syscall.SIGCONT, 15 | "FPE": syscall.SIGFPE, 16 | "HUP": syscall.SIGHUP, 17 | "ILL": syscall.SIGILL, 18 | "INT": syscall.SIGINT, 19 | "IO": syscall.SIGIO, 20 | "IOT": syscall.SIGIOT, 21 | "KILL": syscall.SIGKILL, 22 | "PIPE": syscall.SIGPIPE, 23 | "POLL": syscall.SIGPOLL, 24 | "PROF": syscall.SIGPROF, 25 | "PWR": syscall.SIGPWR, 26 | "QUIT": syscall.SIGQUIT, 27 | "SEGV": syscall.SIGSEGV, 28 | "STKFLT": syscall.SIGSTKFLT, 29 | "STOP": syscall.SIGSTOP, 30 | "SYS": syscall.SIGSYS, 31 | "TERM": syscall.SIGTERM, 32 | "TRAP": syscall.SIGTRAP, 33 | "TSTP": syscall.SIGTSTP, 34 | "TTIN": syscall.SIGTTIN, 35 | "TTOU": syscall.SIGTTOU, 36 | "UNUSED": syscall.SIGUNUSED, 37 | "URG": syscall.SIGURG, 38 | "USR1": syscall.SIGUSR1, 39 | "USR2": syscall.SIGUSR2, 40 | "VTALRM": syscall.SIGVTALRM, 41 | "WINCH": syscall.SIGWINCH, 42 | "XCPU": syscall.SIGXCPU, 43 | "XFSZ": syscall.SIGXFSZ, 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/signal_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package signal 4 | 5 | import ( 6 | "syscall" 7 | ) 8 | 9 | // Signals used in api/client (no windows equivalent, use 10 | // invalid signals so they don't get handled) 11 | 12 | const ( 13 | // SIGCHLD is a signal sent to a process when a child process terminates, is interrupted, or resumes after being interrupted. 14 | SIGCHLD = syscall.SIGCHLD 15 | // SIGWINCH is a signal sent to a process when its controlling terminal changes its size 16 | SIGWINCH = syscall.SIGWINCH 17 | // DefaultStopSignal is the syscall signal used to stop a container in unix systems. 18 | DefaultStopSignal = "SIGTERM" 19 | ) 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/signal_unsupported.go: -------------------------------------------------------------------------------- 1 | // +build !linux,!darwin,!freebsd 2 | 3 | package signal 4 | 5 | import ( 6 | "syscall" 7 | ) 8 | 9 | // SignalMap is an empty map of signals for unsupported platform. 10 | var SignalMap = map[string]syscall.Signal{} 11 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/signal_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package signal 4 | 5 | import ( 6 | "syscall" 7 | ) 8 | 9 | // Signals used in api/client (no windows equivalent, use 10 | // invalid signals so they don't get handled) 11 | const ( 12 | SIGCHLD = syscall.Signal(0xff) 13 | SIGWINCH = syscall.Signal(0xff) 14 | // DefaultStopSignal is the syscall signal used to stop a container in windows systems. 15 | DefaultStopSignal = "15" 16 | ) 17 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/docker/pkg/signal/trap.go: -------------------------------------------------------------------------------- 1 | package signal 2 | 3 | import ( 4 | "os" 5 | gosignal "os/signal" 6 | "runtime" 7 | "sync/atomic" 8 | "syscall" 9 | 10 | "github.com/Sirupsen/logrus" 11 | ) 12 | 13 | // Trap sets up a simplified signal "trap", appropriate for common 14 | // behavior expected from a vanilla unix command-line tool in general 15 | // (and the Docker engine in particular). 16 | // 17 | // * If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated. 18 | // * If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is 19 | // skipped and the process is terminated immediately (allows force quit of stuck daemon) 20 | // * A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit. 21 | // 22 | func Trap(cleanup func()) { 23 | c := make(chan os.Signal, 1) 24 | // we will handle INT, TERM, QUIT here 25 | signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT} 26 | gosignal.Notify(c, signals...) 27 | go func() { 28 | interruptCount := uint32(0) 29 | for sig := range c { 30 | go func(sig os.Signal) { 31 | logrus.Infof("Processing signal '%v'", sig) 32 | switch sig { 33 | case os.Interrupt, syscall.SIGTERM: 34 | if atomic.LoadUint32(&interruptCount) < 3 { 35 | // Initiate the cleanup only once 36 | if atomic.AddUint32(&interruptCount, 1) == 1 { 37 | // Call the provided cleanup handler 38 | cleanup() 39 | os.Exit(0) 40 | } else { 41 | return 42 | } 43 | } else { 44 | // 3 SIGTERM/INT signals received; force exit without cleanup 45 | logrus.Infof("Forcing docker daemon shutdown without cleanup; 3 interrupts received") 46 | } 47 | case syscall.SIGQUIT: 48 | DumpStacks() 49 | logrus.Infof("Forcing docker daemon shutdown without cleanup on SIGQUIT") 50 | } 51 | //for the SIGINT/TERM, and SIGQUIT non-clean shutdown case, exit with 128 + signal # 52 | os.Exit(128 + int(sig.(syscall.Signal))) 53 | }(sig) 54 | } 55 | }() 56 | } 57 | 58 | // DumpStacks dumps the runtime stack. 59 | func DumpStacks() { 60 | var ( 61 | buf []byte 62 | stackSize int 63 | ) 64 | bufferLen := 16384 65 | for stackSize == len(buf) { 66 | buf = make([]byte, bufferLen) 67 | stackSize = runtime.Stack(buf, true) 68 | bufferLen *= 2 69 | } 70 | buf = buf[:stackSize] 71 | // Note that if the daemon is started with a less-verbose log-level than "info" (the default), the goroutine 72 | // traces won't show up in the log. 73 | logrus.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf) 74 | } 75 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.3 5 | # - 1.4 6 | # see https://github.com/moovweb/gvm/pull/116 for why Go 1.4 is currently disabled 7 | 8 | # let us have speedy Docker-based Travis workers 9 | sudo: false 10 | 11 | before_install: 12 | # Symlink below is needed for Travis CI to work correctly on personal forks of libkv 13 | - ln -s $HOME/gopath/src/github.com/${TRAVIS_REPO_SLUG///libkv/} $HOME/gopath/src/github.com/docker 14 | - go get golang.org/x/tools/cmd/vet 15 | - go get golang.org/x/tools/cmd/cover 16 | - go get github.com/mattn/goveralls 17 | - go get github.com/golang/lint/golint 18 | - go get github.com/GeertJohan/fgt 19 | 20 | before_script: 21 | - script/travis_consul.sh 0.5.2 22 | - script/travis_etcd.sh 2.0.11 23 | - script/travis_zk.sh 3.4.6 24 | 25 | script: 26 | - ./consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -config-file=./config.json 1>/dev/null & 27 | - ./etcd/etcd --listen-client-urls 'http://0.0.0.0:4001' --advertise-client-urls 'http://127.0.0.1:4001' >/dev/null 2>&1 & 28 | - ./zk/bin/zkServer.sh start ./zk/conf/zoo.cfg 1> /dev/null 29 | - script/validate-gofmt 30 | - go vet ./... 31 | - fgt golint ./... 32 | - go test -v -race ./... 33 | - script/coverage 34 | - goveralls -service=travis-ci -coverprofile=goverage.report 35 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/libkv.go: -------------------------------------------------------------------------------- 1 | // Package libkv provides a Go native library to store metadata. 2 | // 3 | // The goal of libkv is to abstract common store operations for multiple 4 | // Key/Value backends and offer the same experience no matter which one of the 5 | // backend you want to use. 6 | // 7 | // For example, you can use it to store your metadata or for service discovery to 8 | // register machines and endpoints inside your cluster. 9 | // 10 | // As of now, `libkv` offers support for `Consul`, `Etcd` and `Zookeeper`. 11 | // 12 | // ## Example of usage 13 | // 14 | // ### Create a new store and use Put/Get 15 | // 16 | // 17 | // package main 18 | // 19 | // import ( 20 | // "fmt" 21 | // "time" 22 | // 23 | // "github.com/docker/libkv" 24 | // "github.com/docker/libkv/store" 25 | // log "github.com/Sirupsen/logrus" 26 | // ) 27 | // 28 | // func main() { 29 | // client := "localhost:8500" 30 | // 31 | // // Initialize a new store with consul 32 | // kv, err := libkv.NewStore( 33 | // store.CONSUL, // or "consul" 34 | // []string{client}, 35 | // &store.Config{ 36 | // ConnectionTimeout: 10*time.Second, 37 | // }, 38 | // ) 39 | // if err != nil { 40 | // log.Fatal("Cannot create store consul") 41 | // } 42 | // 43 | // key := "foo" 44 | // err = kv.Put(key, []byte("bar"), nil) 45 | // if err != nil { 46 | // log.Error("Error trying to put value at key `", key, "`") 47 | // } 48 | // 49 | // pair, err := kv.Get(key) 50 | // if err != nil { 51 | // log.Error("Error trying accessing value at key `", key, "`") 52 | // } 53 | // 54 | // log.Info("value: ", string(pair.Value)) 55 | // } 56 | // 57 | // ##Copyright and license 58 | // 59 | // Code and documentation copyright 2015 Docker, inc. Code released under the 60 | // Apache 2.0 license. Docs released under Creative commons. 61 | // 62 | package libkv 63 | 64 | import ( 65 | "fmt" 66 | "sort" 67 | "strings" 68 | 69 | "github.com/docker/libkv/store" 70 | ) 71 | 72 | // Initialize creates a new Store object, initializing the client 73 | type Initialize func(addrs []string, options *store.Config) (store.Store, error) 74 | 75 | var ( 76 | // Backend initializers 77 | initializers = make(map[store.Backend]Initialize) 78 | 79 | supportedBackend = func() string { 80 | keys := make([]string, 0, len(initializers)) 81 | for k := range initializers { 82 | keys = append(keys, string(k)) 83 | } 84 | sort.Strings(keys) 85 | return strings.Join(keys, ", ") 86 | }() 87 | ) 88 | 89 | // NewStore creates a an instance of store 90 | func NewStore(backend store.Backend, addrs []string, options *store.Config) (store.Store, error) { 91 | if init, exists := initializers[backend]; exists { 92 | return init(addrs, options) 93 | } 94 | 95 | return nil, fmt.Errorf("%s %s", store.ErrNotSupported.Error(), supportedBackend) 96 | } 97 | 98 | // AddStore adds a new store backend to libkv 99 | func AddStore(store store.Backend, init Initialize) { 100 | initializers[store] = init 101 | } 102 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/script/.validate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$VALIDATE_UPSTREAM" ]; then 4 | # this is kind of an expensive check, so let's not do this twice if we 5 | # are running more than one validate bundlescript 6 | 7 | VALIDATE_REPO='https://github.com/docker/libkv.git' 8 | VALIDATE_BRANCH='master' 9 | 10 | if [ "$TRAVIS" = 'true' -a "$TRAVIS_PULL_REQUEST" != 'false' ]; then 11 | VALIDATE_REPO="https://github.com/${TRAVIS_REPO_SLUG}.git" 12 | VALIDATE_BRANCH="${TRAVIS_BRANCH}" 13 | fi 14 | 15 | VALIDATE_HEAD="$(git rev-parse --verify HEAD)" 16 | 17 | git fetch -q "$VALIDATE_REPO" "refs/heads/$VALIDATE_BRANCH" 18 | VALIDATE_UPSTREAM="$(git rev-parse --verify FETCH_HEAD)" 19 | 20 | VALIDATE_COMMIT_LOG="$VALIDATE_UPSTREAM..$VALIDATE_HEAD" 21 | VALIDATE_COMMIT_DIFF="$VALIDATE_UPSTREAM...$VALIDATE_HEAD" 22 | 23 | validate_diff() { 24 | if [ "$VALIDATE_UPSTREAM" != "$VALIDATE_HEAD" ]; then 25 | git diff "$VALIDATE_COMMIT_DIFF" "$@" 26 | fi 27 | } 28 | validate_log() { 29 | if [ "$VALIDATE_UPSTREAM" != "$VALIDATE_HEAD" ]; then 30 | git log "$VALIDATE_COMMIT_LOG" "$@" 31 | fi 32 | } 33 | fi 34 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/script/coverage: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MODE="mode: count" 4 | ROOT=${TRAVIS_BUILD_DIR:-.}/../../.. 5 | 6 | # Grab the list of packages. 7 | # Exclude the API and CLI from coverage as it will be covered by integration tests. 8 | PACKAGES=`go list ./...` 9 | 10 | # Create the empty coverage file. 11 | echo $MODE > goverage.report 12 | 13 | # Run coverage on every package. 14 | for package in $PACKAGES; do 15 | output="$ROOT/$package/coverage.out" 16 | 17 | go test -test.short -covermode=count -coverprofile=$output $package 18 | if [ -f "$output" ] ; then 19 | cat "$output" | grep -v "$MODE" >> goverage.report 20 | fi 21 | done 22 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/script/travis_consul.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -gt 0 ] ; then 4 | CONSUL_VERSION="$1" 5 | else 6 | CONSUL_VERSION="0.5.2" 7 | fi 8 | 9 | # install consul 10 | wget "https://dl.bintray.com/mitchellh/consul/${CONSUL_VERSION}_linux_amd64.zip" 11 | unzip "${CONSUL_VERSION}_linux_amd64.zip" 12 | 13 | # make config for minimum ttl 14 | touch config.json 15 | echo "{\"session_ttl_min\": \"1s\"}" >> config.json 16 | 17 | # check 18 | ./consul --version 19 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/script/travis_etcd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -gt 0 ] ; then 4 | ETCD_VERSION="$1" 5 | else 6 | ETCD_VERSION="2.0.11" 7 | fi 8 | 9 | curl -L https://github.com/coreos/etcd/releases/download/v$ETCD_VERSION/etcd-v$ETCD_VERSION-linux-amd64.tar.gz -o etcd-v$ETCD_VERSION-linux-amd64.tar.gz 10 | tar xzvf etcd-v$ETCD_VERSION-linux-amd64.tar.gz 11 | mv etcd-v$ETCD_VERSION-linux-amd64 etcd 12 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/script/travis_zk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -gt 0 ] ; then 4 | ZK_VERSION="$1" 5 | else 6 | ZK_VERSION="3.4.6" 7 | fi 8 | 9 | wget "http://mirrors.ukfast.co.uk/sites/ftp.apache.org/zookeeper/stable/zookeeper-${ZK_VERSION}.tar.gz" 10 | tar -xvf "zookeeper-${ZK_VERSION}.tar.gz" 11 | mv zookeeper-$ZK_VERSION zk 12 | mv ./zk/conf/zoo_sample.cfg ./zk/conf/zoo.cfg 13 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/script/validate-gofmt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "$(dirname "$BASH_SOURCE")/.validate" 4 | 5 | IFS=$'\n' 6 | files=( $(validate_diff --diff-filter=ACMR --name-only -- '*.go' | grep -v '^Godeps/' || true) ) 7 | unset IFS 8 | 9 | badFiles=() 10 | for f in "${files[@]}"; do 11 | # we use "git show" here to validate that what's committed is formatted 12 | if [ "$(git show "$VALIDATE_HEAD:$f" | gofmt -s -l)" ]; then 13 | badFiles+=( "$f" ) 14 | fi 15 | done 16 | 17 | if [ ${#badFiles[@]} -eq 0 ]; then 18 | echo 'Congratulations! All Go source files are properly formatted.' 19 | else 20 | { 21 | echo "These files are not properly gofmt'd:" 22 | for f in "${badFiles[@]}"; do 23 | echo " - $f" 24 | done 25 | echo 26 | echo 'Please reformat the above files using "gofmt -s -w" and commit the result.' 27 | echo 28 | } >&2 29 | false 30 | fi 31 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/store/helpers.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | // CreateEndpoints creates a list of endpoints given the right scheme 8 | func CreateEndpoints(addrs []string, scheme string) (entries []string) { 9 | for _, addr := range addrs { 10 | entries = append(entries, scheme+"://"+addr) 11 | } 12 | return entries 13 | } 14 | 15 | // Normalize the key for each store to the form: 16 | // 17 | // /path/to/key 18 | // 19 | func Normalize(key string) string { 20 | return "/" + join(SplitKey(key)) 21 | } 22 | 23 | // GetDirectory gets the full directory part of 24 | // the key to the form: 25 | // 26 | // /path/to/ 27 | // 28 | func GetDirectory(key string) string { 29 | parts := SplitKey(key) 30 | parts = parts[:len(parts)-1] 31 | return "/" + join(parts) 32 | } 33 | 34 | // SplitKey splits the key to extract path informations 35 | func SplitKey(key string) (path []string) { 36 | if strings.Contains(key, "/") { 37 | path = strings.Split(key, "/") 38 | } else { 39 | path = []string{key} 40 | } 41 | return path 42 | } 43 | 44 | // join the path parts with '/' 45 | func join(parts []string) string { 46 | return strings.Join(parts, "/") 47 | } 48 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/docker/libkv/store/mock/mock.go: -------------------------------------------------------------------------------- 1 | package mock 2 | 3 | import ( 4 | "github.com/docker/libkv/store" 5 | "github.com/stretchr/testify/mock" 6 | ) 7 | 8 | // Mock store. Mocks all Store functions using testify.Mock 9 | type Mock struct { 10 | mock.Mock 11 | 12 | // Endpoints passed to InitializeMock 13 | Endpoints []string 14 | 15 | // Options passed to InitializeMock 16 | Options *store.Config 17 | } 18 | 19 | // New creates a Mock store 20 | func New(endpoints []string, options *store.Config) (store.Store, error) { 21 | s := &Mock{} 22 | s.Endpoints = endpoints 23 | s.Options = options 24 | return s, nil 25 | } 26 | 27 | // Put mock 28 | func (s *Mock) Put(key string, value []byte, opts *store.WriteOptions) error { 29 | args := s.Mock.Called(key, value, opts) 30 | return args.Error(0) 31 | } 32 | 33 | // Get mock 34 | func (s *Mock) Get(key string) (*store.KVPair, error) { 35 | args := s.Mock.Called(key) 36 | return args.Get(0).(*store.KVPair), args.Error(1) 37 | } 38 | 39 | // Delete mock 40 | func (s *Mock) Delete(key string) error { 41 | args := s.Mock.Called(key) 42 | return args.Error(0) 43 | } 44 | 45 | // Exists mock 46 | func (s *Mock) Exists(key string) (bool, error) { 47 | args := s.Mock.Called(key) 48 | return args.Bool(0), args.Error(1) 49 | } 50 | 51 | // Watch mock 52 | func (s *Mock) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) { 53 | args := s.Mock.Called(key, stopCh) 54 | return args.Get(0).(<-chan *store.KVPair), args.Error(1) 55 | } 56 | 57 | // WatchTree mock 58 | func (s *Mock) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) { 59 | args := s.Mock.Called(prefix, stopCh) 60 | return args.Get(0).(chan []*store.KVPair), args.Error(1) 61 | } 62 | 63 | // NewLock mock 64 | func (s *Mock) NewLock(key string, options *store.LockOptions) (store.Locker, error) { 65 | args := s.Mock.Called(key, options) 66 | return args.Get(0).(store.Locker), args.Error(1) 67 | } 68 | 69 | // List mock 70 | func (s *Mock) List(prefix string) ([]*store.KVPair, error) { 71 | args := s.Mock.Called(prefix) 72 | return args.Get(0).([]*store.KVPair), args.Error(1) 73 | } 74 | 75 | // DeleteTree mock 76 | func (s *Mock) DeleteTree(prefix string) error { 77 | args := s.Mock.Called(prefix) 78 | return args.Error(0) 79 | } 80 | 81 | // AtomicPut mock 82 | func (s *Mock) AtomicPut(key string, value []byte, previous *store.KVPair, opts *store.WriteOptions) (bool, *store.KVPair, error) { 83 | args := s.Mock.Called(key, value, previous, opts) 84 | return args.Bool(0), args.Get(1).(*store.KVPair), args.Error(2) 85 | } 86 | 87 | // AtomicDelete mock 88 | func (s *Mock) AtomicDelete(key string, previous *store.KVPair) (bool, error) { 89 | args := s.Mock.Called(key, previous) 90 | return args.Bool(0), args.Error(1) 91 | } 92 | 93 | // Lock mock implementation of Locker 94 | type Lock struct { 95 | mock.Mock 96 | } 97 | 98 | // Lock mock 99 | func (l *Lock) Lock() (<-chan struct{}, error) { 100 | args := l.Mock.Called() 101 | return args.Get(0).(<-chan struct{}), args.Error(1) 102 | } 103 | 104 | // Unlock mock 105 | func (l *Lock) Unlock() error { 106 | args := l.Mock.Called() 107 | return args.Error(0) 108 | } 109 | 110 | // Close mock 111 | func (s *Mock) Close() { 112 | return 113 | } 114 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/.gitignore: -------------------------------------------------------------------------------- 1 | version.gen.go 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/attr.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "os" 5 | "syscall" 6 | "time" 7 | ) 8 | 9 | func (a *Attr) IsFifo() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFIFO } 10 | 11 | // IsChar reports whether the FileInfo describes a character special file. 12 | func (a *Attr) IsChar() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFCHR } 13 | 14 | // IsDir reports whether the FileInfo describes a directory. 15 | func (a *Attr) IsDir() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFDIR } 16 | 17 | // IsBlock reports whether the FileInfo describes a block special file. 18 | func (a *Attr) IsBlock() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFBLK } 19 | 20 | // IsRegular reports whether the FileInfo describes a regular file. 21 | func (a *Attr) IsRegular() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFREG } 22 | 23 | // IsSymlink reports whether the FileInfo describes a symbolic link. 24 | func (a *Attr) IsSymlink() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFLNK } 25 | 26 | // IsSocket reports whether the FileInfo describes a socket. 27 | func (a *Attr) IsSocket() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFSOCK } 28 | 29 | func (a *Attr) SetTimes(access *time.Time, mod *time.Time, chstatus *time.Time) { 30 | if access != nil { 31 | a.Atime = uint64(access.Unix()) 32 | a.Atimensec = uint32(access.Nanosecond()) 33 | } 34 | if mod != nil { 35 | a.Mtime = uint64(mod.Unix()) 36 | a.Mtimensec = uint32(mod.Nanosecond()) 37 | } 38 | if chstatus != nil { 39 | a.Ctime = uint64(chstatus.Unix()) 40 | a.Ctimensec = uint32(chstatus.Nanosecond()) 41 | } 42 | } 43 | 44 | func (a *Attr) ChangeTime() time.Time { 45 | return time.Unix(int64(a.Ctime), int64(a.Ctimensec)) 46 | } 47 | 48 | func (a *Attr) AccessTime() time.Time { 49 | return time.Unix(int64(a.Atime), int64(a.Atimensec)) 50 | } 51 | 52 | func (a *Attr) ModTime() time.Time { 53 | return time.Unix(int64(a.Mtime), int64(a.Mtimensec)) 54 | } 55 | 56 | func ToStatT(f os.FileInfo) *syscall.Stat_t { 57 | s, _ := f.Sys().(*syscall.Stat_t) 58 | if s != nil { 59 | return s 60 | } 61 | return nil 62 | } 63 | 64 | func ToAttr(f os.FileInfo) *Attr { 65 | if f == nil { 66 | return nil 67 | } 68 | s := ToStatT(f) 69 | if s != nil { 70 | a := &Attr{} 71 | a.FromStat(s) 72 | return a 73 | } 74 | return nil 75 | } 76 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/attr_darwin.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | func (a *Attr) FromStat(s *syscall.Stat_t) { 8 | a.Ino = uint64(s.Ino) 9 | a.Size = uint64(s.Size) 10 | a.Blocks = uint64(s.Blocks) 11 | a.Atime = uint64(s.Atimespec.Sec) 12 | a.Atimensec = uint32(s.Atimespec.Nsec) 13 | a.Mtime = uint64(s.Mtimespec.Sec) 14 | a.Mtimensec = uint32(s.Mtimespec.Nsec) 15 | a.Ctime = uint64(s.Ctimespec.Sec) 16 | a.Ctimensec = uint32(s.Ctimespec.Nsec) 17 | a.Mode = uint32(s.Mode) 18 | a.Nlink = uint32(s.Nlink) 19 | a.Uid = uint32(s.Uid) 20 | a.Gid = uint32(s.Gid) 21 | a.Rdev = uint32(s.Rdev) 22 | } 23 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/attr_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | func (a *Attr) FromStat(s *syscall.Stat_t) { 8 | a.Ino = uint64(s.Ino) 9 | a.Size = uint64(s.Size) 10 | a.Blocks = uint64(s.Blocks) 11 | a.Atime = uint64(s.Atim.Sec) 12 | a.Atimensec = uint32(s.Atim.Nsec) 13 | a.Mtime = uint64(s.Mtim.Sec) 14 | a.Mtimensec = uint32(s.Mtim.Nsec) 15 | a.Ctime = uint64(s.Ctim.Sec) 16 | a.Ctimensec = uint32(s.Ctim.Nsec) 17 | a.Mode = s.Mode 18 | a.Nlink = uint32(s.Nlink) 19 | a.Uid = uint32(s.Uid) 20 | a.Gid = uint32(s.Gid) 21 | a.Rdev = uint32(s.Rdev) 22 | a.Blksize = uint32(s.Blksize) 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/bufferpool.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | var paranoia bool 8 | 9 | // BufferPool implements explicit memory management. It is used for 10 | // minimizing the GC overhead of communicating with the kernel. 11 | type BufferPool interface { 12 | // AllocBuffer creates a buffer of at least the given size. After use, 13 | // it should be deallocated with FreeBuffer(). 14 | AllocBuffer(size uint32) []byte 15 | 16 | // FreeBuffer takes back a buffer if it was allocated through 17 | // AllocBuffer. It is not an error to call FreeBuffer() on a slice 18 | // obtained elsewhere. 19 | FreeBuffer(slice []byte) 20 | } 21 | 22 | type gcBufferPool struct { 23 | } 24 | 25 | // NewGcBufferPool is a fallback to the standard allocation routines. 26 | func NewGcBufferPool() BufferPool { 27 | return &gcBufferPool{} 28 | } 29 | 30 | func (p *gcBufferPool) AllocBuffer(size uint32) []byte { 31 | return make([]byte, size) 32 | } 33 | 34 | func (p *gcBufferPool) FreeBuffer(slice []byte) { 35 | } 36 | 37 | type bufferPoolImpl struct { 38 | lock sync.Mutex 39 | 40 | // For each page size multiple a list of slice pointers. 41 | buffersBySize []*sync.Pool 42 | } 43 | 44 | // NewBufferPool returns a BufferPool implementation that that returns 45 | // slices with capacity of a multiple of PAGESIZE, which have possibly 46 | // been used, and may contain random contents. When using 47 | // NewBufferPool, file system handlers may not hang on to passed-in 48 | // buffers beyond the handler's return. 49 | func NewBufferPool() BufferPool { 50 | bp := new(bufferPoolImpl) 51 | return bp 52 | } 53 | 54 | func (p *bufferPoolImpl) getPool(pageCount int) *sync.Pool { 55 | p.lock.Lock() 56 | for len(p.buffersBySize) < pageCount+1 { 57 | p.buffersBySize = append(p.buffersBySize, nil) 58 | } 59 | if p.buffersBySize[pageCount] == nil { 60 | p.buffersBySize[pageCount] = &sync.Pool{ 61 | New: func() interface{} { return make([]byte, PAGESIZE*pageCount) }, 62 | } 63 | } 64 | pool := p.buffersBySize[pageCount] 65 | p.lock.Unlock() 66 | return pool 67 | } 68 | 69 | func (p *bufferPoolImpl) AllocBuffer(size uint32) []byte { 70 | sz := int(size) 71 | if sz < PAGESIZE { 72 | sz = PAGESIZE 73 | } 74 | 75 | if sz%PAGESIZE != 0 { 76 | sz += PAGESIZE 77 | } 78 | pages := sz / PAGESIZE 79 | 80 | b := p.getPool(pages).Get().([]byte) 81 | return b[:size] 82 | } 83 | 84 | func (p *bufferPoolImpl) FreeBuffer(slice []byte) { 85 | if slice == nil { 86 | return 87 | } 88 | if cap(slice)%PAGESIZE != 0 || cap(slice) == 0 { 89 | return 90 | } 91 | pages := cap(slice) / PAGESIZE 92 | slice = slice[:cap(slice)] 93 | 94 | p.getPool(pages).Put(slice) 95 | } 96 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/constants.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "os" 5 | "syscall" 6 | ) 7 | 8 | const ( 9 | FUSE_ROOT_ID = 1 10 | 11 | FUSE_UNKNOWN_INO = 0xffffffff 12 | 13 | CUSE_UNRESTRICTED_IOCTL = (1 << 0) 14 | 15 | FUSE_LK_FLOCK = (1 << 0) 16 | 17 | FUSE_IOCTL_MAX_IOV = 256 18 | 19 | FUSE_POLL_SCHEDULE_NOTIFY = (1 << 0) 20 | 21 | CUSE_INIT_INFO_MAX = 4096 22 | 23 | S_IFDIR = syscall.S_IFDIR 24 | S_IFREG = syscall.S_IFREG 25 | S_IFLNK = syscall.S_IFLNK 26 | S_IFIFO = syscall.S_IFIFO 27 | 28 | CUSE_INIT = 4096 29 | 30 | O_ANYWRITE = uint32(os.O_WRONLY | os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_TRUNC) 31 | ) 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/constants_freebsd.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | // arbitrary values 4 | const syscall_O_LARGEFILE = 1 << 29 5 | const syscall_O_NOATIME = 1 << 30 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/constants_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | const syscall_O_LARGEFILE = syscall.O_LARGEFILE 8 | const syscall_O_NOATIME = syscall.O_NOATIME 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/direntry.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | // all of the code for DirEntryList. 4 | 5 | import ( 6 | "fmt" 7 | "unsafe" 8 | ) 9 | 10 | var eightPadding [8]byte 11 | 12 | const direntSize = int(unsafe.Sizeof(_Dirent{})) 13 | 14 | // DirEntry is a type for PathFileSystem and NodeFileSystem to return 15 | // directory contents in. 16 | type DirEntry struct { 17 | // Mode is the file's mode. Only the high bits (eg. S_IFDIR) 18 | // are considered. 19 | Mode uint32 20 | 21 | // Name is the basename of the file in the directory. 22 | Name string 23 | } 24 | 25 | func (d DirEntry) String() string { 26 | return fmt.Sprintf("%o: %q", d.Mode, d.Name) 27 | } 28 | 29 | // DirEntryList holds the return value for READDIR and READDIRPLUS 30 | // opcodes. 31 | type DirEntryList struct { 32 | buf []byte 33 | size int 34 | offset uint64 35 | } 36 | 37 | // NewDirEntryList creates a DirEntryList with the given data buffer 38 | // and offset. 39 | func NewDirEntryList(data []byte, off uint64) *DirEntryList { 40 | return &DirEntryList{ 41 | buf: data[:0], 42 | size: len(data), 43 | offset: off, 44 | } 45 | } 46 | 47 | // AddDirEntry tries to add an entry, and reports whether it 48 | // succeeded. 49 | func (l *DirEntryList) AddDirEntry(e DirEntry) (bool, uint64) { 50 | return l.Add(nil, e.Name, uint64(FUSE_UNKNOWN_INO), e.Mode) 51 | } 52 | 53 | // Add adds a direntry to the DirEntryList, returning whether it 54 | // succeeded. 55 | func (l *DirEntryList) Add(prefix []byte, name string, inode uint64, mode uint32) (bool, uint64) { 56 | padding := (8 - len(name)&7) & 7 57 | delta := padding + direntSize + len(name) + len(prefix) 58 | oldLen := len(l.buf) 59 | newLen := delta + oldLen 60 | 61 | if newLen > l.size { 62 | return false, l.offset 63 | } 64 | l.buf = l.buf[:newLen] 65 | copy(l.buf[oldLen:], prefix) 66 | oldLen += len(prefix) 67 | dirent := (*_Dirent)(unsafe.Pointer(&l.buf[oldLen])) 68 | dirent.Off = l.offset + 1 69 | dirent.Ino = inode 70 | dirent.NameLen = uint32(len(name)) 71 | dirent.Typ = (mode & 0170000) >> 12 72 | oldLen += direntSize 73 | copy(l.buf[oldLen:], name) 74 | oldLen += len(name) 75 | 76 | if padding > 0 { 77 | copy(l.buf[oldLen:], eightPadding[:padding]) 78 | } 79 | 80 | l.offset = dirent.Off 81 | return true, l.offset 82 | } 83 | 84 | // AddDirLookupEntry is used for ReadDirPlus. It serializes a DirEntry 85 | // and its corresponding lookup. Pass a zero entryOut if the lookup 86 | // data should be ignored. 87 | func (l *DirEntryList) AddDirLookupEntry(e DirEntry, entryOut *EntryOut) (bool, uint64) { 88 | ino := uint64(FUSE_UNKNOWN_INO) 89 | if entryOut.Ino > 0 { 90 | ino = entryOut.Ino 91 | } 92 | var lookup []byte 93 | toSlice(&lookup, unsafe.Pointer(entryOut), unsafe.Sizeof(EntryOut{})) 94 | 95 | return l.Add(lookup, e.Name, ino, e.Mode) 96 | } 97 | 98 | func (l *DirEntryList) bytes() []byte { 99 | return l.buf 100 | } 101 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/misc.go: -------------------------------------------------------------------------------- 1 | // Random odds and ends. 2 | 3 | package fuse 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "os" 9 | "reflect" 10 | "syscall" 11 | "unsafe" 12 | ) 13 | 14 | func (code Status) String() string { 15 | if code <= 0 { 16 | return []string{ 17 | "OK", 18 | "NOTIFY_POLL", 19 | "NOTIFY_INVAL_INODE", 20 | "NOTIFY_INVAL_ENTRY", 21 | "NOTIFY_INVAL_STORE", 22 | "NOTIFY_INVAL_RETRIEVE", 23 | "NOTIFY_INVAL_DELETE", 24 | }[-code] 25 | } 26 | return fmt.Sprintf("%d=%v", int(code), syscall.Errno(code)) 27 | } 28 | 29 | func (code Status) Ok() bool { 30 | return code == OK 31 | } 32 | 33 | // ToStatus extracts an errno number from Go error objects. If it 34 | // fails, it logs an error and returns ENOSYS. 35 | func ToStatus(err error) Status { 36 | switch err { 37 | case nil: 38 | return OK 39 | case os.ErrPermission: 40 | return EPERM 41 | case os.ErrExist: 42 | return Status(syscall.EEXIST) 43 | case os.ErrNotExist: 44 | return ENOENT 45 | case os.ErrInvalid: 46 | return EINVAL 47 | } 48 | 49 | switch t := err.(type) { 50 | case syscall.Errno: 51 | return Status(t) 52 | case *os.SyscallError: 53 | return Status(t.Err.(syscall.Errno)) 54 | case *os.PathError: 55 | return ToStatus(t.Err) 56 | case *os.LinkError: 57 | return ToStatus(t.Err) 58 | } 59 | log.Println("can't convert error type:", err) 60 | return ENOSYS 61 | } 62 | 63 | func toSlice(dest *[]byte, ptr unsafe.Pointer, byteCount uintptr) { 64 | h := (*reflect.SliceHeader)(unsafe.Pointer(dest)) 65 | *h = reflect.SliceHeader{ 66 | Data: uintptr(ptr), 67 | Len: int(byteCount), 68 | Cap: int(byteCount), 69 | } 70 | } 71 | 72 | func CurrentOwner() *Owner { 73 | return &Owner{ 74 | Uid: uint32(os.Getuid()), 75 | Gid: uint32(os.Getgid()), 76 | } 77 | } 78 | 79 | func init() { 80 | p := syscall.Getpagesize() 81 | if p != PAGESIZE { 82 | log.Panicf("page size incorrect: %d", p) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/mount_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "log" 7 | "os" 8 | "os/exec" 9 | "path/filepath" 10 | "syscall" 11 | "unsafe" 12 | ) 13 | 14 | var fusermountBinary string 15 | var umountBinary string 16 | 17 | func unixgramSocketpair() (l, r *os.File, err error) { 18 | fd, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0) 19 | if err != nil { 20 | return nil, nil, os.NewSyscallError("socketpair", 21 | err.(syscall.Errno)) 22 | } 23 | l = os.NewFile(uintptr(fd[0]), "socketpair-half1") 24 | r = os.NewFile(uintptr(fd[1]), "socketpair-half2") 25 | return 26 | } 27 | 28 | // Create a FUSE FS on the specified mount point. The returned 29 | // mount point is always absolute. 30 | func mount(mountPoint string, options string) (fd int, err error) { 31 | local, remote, err := unixgramSocketpair() 32 | if err != nil { 33 | return 34 | } 35 | 36 | defer local.Close() 37 | defer remote.Close() 38 | 39 | cmd := []string{fusermountBinary, mountPoint} 40 | if options != "" { 41 | cmd = append(cmd, "-o") 42 | cmd = append(cmd, options) 43 | } 44 | proc, err := os.StartProcess(fusermountBinary, 45 | cmd, 46 | &os.ProcAttr{ 47 | Env: []string{"_FUSE_COMMFD=3"}, 48 | Files: []*os.File{os.Stdin, os.Stdout, os.Stderr, remote}}) 49 | 50 | if err != nil { 51 | return 52 | } 53 | 54 | w, err := proc.Wait() 55 | if err != nil { 56 | return 57 | } 58 | if !w.Success() { 59 | err = fmt.Errorf("fusermount exited with code %v\n", w.Sys()) 60 | return 61 | } 62 | 63 | return getConnection(local) 64 | } 65 | 66 | func privilegedUnmount(mountPoint string) error { 67 | dir, _ := filepath.Split(mountPoint) 68 | proc, err := os.StartProcess(umountBinary, 69 | []string{umountBinary, mountPoint}, 70 | &os.ProcAttr{Dir: dir, Files: []*os.File{nil, nil, os.Stderr}}) 71 | if err != nil { 72 | return err 73 | } 74 | w, err := proc.Wait() 75 | if !w.Success() { 76 | return fmt.Errorf("umount exited with code %v\n", w.Sys()) 77 | } 78 | return err 79 | } 80 | 81 | func unmount(mountPoint string) (err error) { 82 | if os.Geteuid() == 0 { 83 | return privilegedUnmount(mountPoint) 84 | } 85 | errBuf := bytes.Buffer{} 86 | cmd := exec.Command(fusermountBinary, "-u", mountPoint) 87 | cmd.Stderr = &errBuf 88 | err = cmd.Run() 89 | if errBuf.Len() > 0 { 90 | return fmt.Errorf("%s (code %v)\n", 91 | errBuf.String(), err) 92 | } 93 | return err 94 | } 95 | 96 | func getConnection(local *os.File) (int, error) { 97 | var data [4]byte 98 | control := make([]byte, 4*256) 99 | 100 | // n, oobn, recvflags, from, errno - todo: error checking. 101 | _, oobn, _, _, 102 | err := syscall.Recvmsg( 103 | int(local.Fd()), data[:], control[:], 0) 104 | if err != nil { 105 | return 0, err 106 | } 107 | 108 | message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0])) 109 | fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr)) 110 | 111 | if message.Type != 1 { 112 | return 0, fmt.Errorf("getConnection: recvmsg returned wrong control type: %d", message.Type) 113 | } 114 | if oobn <= syscall.SizeofCmsghdr { 115 | return 0, fmt.Errorf("getConnection: too short control message. Length: %d", oobn) 116 | } 117 | if fd < 0 { 118 | return 0, fmt.Errorf("getConnection: fd < 0: %d", fd) 119 | } 120 | return int(fd), nil 121 | } 122 | 123 | func init() { 124 | var err error 125 | fusermountBinary, err = exec.LookPath("fusermount") 126 | if err != nil { 127 | log.Fatalf("Could not find fusermount binary: %v", err) 128 | } 129 | umountBinary, _ = exec.LookPath("umount") 130 | if err != nil { 131 | log.Fatalf("Could not find umount binary: %v", err) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/defaultfile.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/hanwen/go-fuse/fuse" 7 | ) 8 | 9 | type defaultFile struct{} 10 | 11 | // NewDefaultFile returns a File instance that returns ENOSYS for 12 | // every operation. 13 | func NewDefaultFile() File { 14 | return (*defaultFile)(nil) 15 | } 16 | 17 | func (f *defaultFile) SetInode(*Inode) { 18 | } 19 | 20 | func (f *defaultFile) InnerFile() File { 21 | return nil 22 | } 23 | 24 | func (f *defaultFile) String() string { 25 | return "defaultFile" 26 | } 27 | 28 | func (f *defaultFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) { 29 | return nil, fuse.ENOSYS 30 | } 31 | 32 | func (f *defaultFile) Write(data []byte, off int64) (uint32, fuse.Status) { 33 | return 0, fuse.ENOSYS 34 | } 35 | 36 | func (f *defaultFile) Flush() fuse.Status { 37 | return fuse.OK 38 | } 39 | 40 | func (f *defaultFile) Release() { 41 | 42 | } 43 | 44 | func (f *defaultFile) GetAttr(*fuse.Attr) fuse.Status { 45 | return fuse.ENOSYS 46 | } 47 | 48 | func (f *defaultFile) Fsync(flags int) (code fuse.Status) { 49 | return fuse.ENOSYS 50 | } 51 | 52 | func (f *defaultFile) Utimens(atime *time.Time, mtime *time.Time) fuse.Status { 53 | return fuse.ENOSYS 54 | } 55 | 56 | func (f *defaultFile) Truncate(size uint64) fuse.Status { 57 | return fuse.ENOSYS 58 | } 59 | 60 | func (f *defaultFile) Chown(uid uint32, gid uint32) fuse.Status { 61 | return fuse.ENOSYS 62 | } 63 | 64 | func (f *defaultFile) Chmod(perms uint32) fuse.Status { 65 | return fuse.ENOSYS 66 | } 67 | 68 | func (f *defaultFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) { 69 | return fuse.ENOSYS 70 | } 71 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/dir.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/hanwen/go-fuse/fuse" 7 | ) 8 | 9 | type connectorDir struct { 10 | node Node 11 | stream []fuse.DirEntry 12 | lastOffset uint64 13 | rawFS fuse.RawFileSystem 14 | lookups []fuse.EntryOut 15 | } 16 | 17 | func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) { 18 | if d.stream == nil { 19 | return fuse.OK 20 | } 21 | // rewinddir() should be as if reopening directory. 22 | // TODO - test this. 23 | if d.lastOffset > 0 && input.Offset == 0 { 24 | d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context)) 25 | if !code.Ok() { 26 | return code 27 | } 28 | } 29 | 30 | if input.Offset > uint64(len(d.stream)) { 31 | // This shouldn't happen, but let's not crash. 32 | return fuse.EINVAL 33 | } 34 | 35 | todo := d.stream[input.Offset:] 36 | for _, e := range todo { 37 | if e.Name == "" { 38 | log.Printf("got emtpy directory entry, mode %o.", e.Mode) 39 | continue 40 | } 41 | ok, off := out.AddDirEntry(e) 42 | d.lastOffset = off 43 | if !ok { 44 | break 45 | } 46 | } 47 | return fuse.OK 48 | } 49 | 50 | func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) { 51 | if d.stream == nil { 52 | return fuse.OK 53 | } 54 | 55 | // rewinddir() should be as if reopening directory. 56 | if d.lastOffset > 0 && input.Offset == 0 { 57 | d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context)) 58 | if !code.Ok() { 59 | return code 60 | } 61 | d.lookups = nil 62 | } 63 | 64 | if d.lookups == nil { 65 | d.lookups = make([]fuse.EntryOut, len(d.stream)) 66 | for i, n := range d.stream { 67 | if n.Name == "." || n.Name == ".." { 68 | continue 69 | } 70 | // We ignore the return value 71 | code := d.rawFS.Lookup(&input.InHeader, n.Name, &d.lookups[i]) 72 | if !code.Ok() { 73 | d.lookups[i] = fuse.EntryOut{} 74 | } 75 | } 76 | } 77 | 78 | if input.Offset > uint64(len(d.stream)) { 79 | // This shouldn't happen, but let's not crash. 80 | return fuse.EINVAL 81 | } 82 | todo := d.stream[input.Offset:] 83 | for i, e := range todo { 84 | if e.Name == "" { 85 | log.Printf("got empty directory entry, mode %o.", e.Mode) 86 | continue 87 | } 88 | ok, off := out.AddDirLookupEntry(e, &d.lookups[input.Offset+uint64(i)]) 89 | d.lastOffset = off 90 | if !ok { 91 | break 92 | } 93 | } 94 | return fuse.OK 95 | 96 | } 97 | 98 | type rawDir interface { 99 | ReadDir(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status 100 | ReadDirPlus(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status 101 | } 102 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/files_darwin.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "syscall" 5 | "time" 6 | "unsafe" 7 | 8 | "github.com/hanwen/go-fuse/fuse" 9 | ) 10 | 11 | func (f *loopbackFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status { 12 | // TODO: Handle `mode` parameter. 13 | 14 | // From `man fcntl` on OSX: 15 | // The F_PREALLOCATE command operates on the following structure: 16 | // 17 | // typedef struct fstore { 18 | // u_int32_t fst_flags; /* IN: flags word */ 19 | // int fst_posmode; /* IN: indicates offset field */ 20 | // off_t fst_offset; /* IN: start of the region */ 21 | // off_t fst_length; /* IN: size of the region */ 22 | // off_t fst_bytesalloc; /* OUT: number of bytes allocated */ 23 | // } fstore_t; 24 | // 25 | // The flags (fst_flags) for the F_PREALLOCATE command are as follows: 26 | // 27 | // F_ALLOCATECONTIG Allocate contiguous space. 28 | // 29 | // F_ALLOCATEALL Allocate all requested space or no space at all. 30 | // 31 | // The position modes (fst_posmode) for the F_PREALLOCATE command indicate how to use the offset field. The modes are as fol- 32 | // lows: 33 | // 34 | // F_PEOFPOSMODE Allocate from the physical end of file. 35 | // 36 | // F_VOLPOSMODE Allocate from the volume offset. 37 | 38 | k := struct { 39 | Flags uint32 // u_int32_t 40 | Posmode int64 // int 41 | Offset int64 // off_t 42 | Length int64 // off_t 43 | Bytesalloc int64 // off_t 44 | }{ 45 | 0, 46 | 0, 47 | int64(off), 48 | int64(sz), 49 | 0, 50 | } 51 | 52 | // Linux version for reference: 53 | // err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz)) 54 | 55 | f.lock.Lock() 56 | _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.File.Fd(), uintptr(syscall.F_PREALLOCATE), uintptr(unsafe.Pointer(&k))) 57 | f.lock.Unlock() 58 | if errno != 0 { 59 | return fuse.ToStatus(errno) 60 | } 61 | return fuse.OK 62 | } 63 | 64 | const _UTIME_NOW = ((1 << 30) - 1) 65 | const _UTIME_OMIT = ((1 << 30) - 2) 66 | 67 | func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status { 68 | tv := make([]syscall.Timeval, 2) 69 | if a == nil { 70 | tv[0].Usec = _UTIME_OMIT 71 | } else { 72 | n := a.UnixNano() 73 | tv[0] = syscall.NsecToTimeval(n) 74 | } 75 | 76 | if m == nil { 77 | tv[1].Usec = _UTIME_OMIT 78 | } else { 79 | n := m.UnixNano() 80 | tv[1] = syscall.NsecToTimeval(n) 81 | } 82 | 83 | f.lock.Lock() 84 | err := syscall.Futimes(int(f.File.Fd()), tv) 85 | f.lock.Unlock() 86 | 87 | return fuse.ToStatus(err) 88 | } 89 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/files_linux.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "syscall" 5 | "time" 6 | 7 | "github.com/hanwen/go-fuse/fuse" 8 | ) 9 | 10 | func (f *loopbackFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status { 11 | f.lock.Lock() 12 | err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz)) 13 | f.lock.Unlock() 14 | if err != nil { 15 | return fuse.ToStatus(err) 16 | } 17 | return fuse.OK 18 | } 19 | 20 | const _UTIME_NOW = ((1 << 30) - 1) 21 | const _UTIME_OMIT = ((1 << 30) - 2) 22 | 23 | func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status { 24 | tv := make([]syscall.Timeval, 2) 25 | if a == nil { 26 | tv[0].Usec = _UTIME_OMIT 27 | } else { 28 | n := a.UnixNano() 29 | tv[0] = syscall.NsecToTimeval(n) 30 | } 31 | 32 | if m == nil { 33 | tv[1].Usec = _UTIME_OMIT 34 | } else { 35 | n := a.UnixNano() 36 | tv[1] = syscall.NsecToTimeval(n) 37 | } 38 | 39 | f.lock.Lock() 40 | err := syscall.Futimes(int(f.File.Fd()), tv) 41 | f.lock.Unlock() 42 | return fuse.ToStatus(err) 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/fsmount.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "log" 5 | "sync" 6 | "unsafe" 7 | 8 | "github.com/hanwen/go-fuse/fuse" 9 | ) 10 | 11 | // openedFile stores either an open dir or an open file. 12 | type openedFile struct { 13 | handled 14 | 15 | WithFlags 16 | 17 | dir *connectorDir 18 | } 19 | 20 | type fileSystemMount struct { 21 | // Node that we were mounted on. 22 | mountInode *Inode 23 | 24 | // Parent to the mountInode. 25 | parentInode *Inode 26 | 27 | // Options for the mount. 28 | options *Options 29 | 30 | // Protects Children hashmaps within the mount. treeLock 31 | // should be acquired before openFilesLock. 32 | // 33 | // If multiple treeLocks must be acquired, the treeLocks 34 | // closer to the root must be acquired first. 35 | treeLock sync.RWMutex 36 | 37 | // Manage filehandles of open files. 38 | openFiles handleMap 39 | 40 | Debug bool 41 | 42 | connector *FileSystemConnector 43 | } 44 | 45 | // Must called with lock for parent held. 46 | func (m *fileSystemMount) mountName() string { 47 | for k, v := range m.parentInode.children { 48 | if m.mountInode == v { 49 | return k 50 | } 51 | } 52 | panic("not found") 53 | } 54 | 55 | func (m *fileSystemMount) setOwner(attr *fuse.Attr) { 56 | if m.options.Owner != nil { 57 | attr.Owner = *(*fuse.Owner)(m.options.Owner) 58 | } 59 | } 60 | 61 | func (m *fileSystemMount) fillEntry(out *fuse.EntryOut) { 62 | splitDuration(m.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec) 63 | splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec) 64 | m.setOwner(&out.Attr) 65 | if out.Mode&fuse.S_IFDIR == 0 && out.Nlink == 0 { 66 | out.Nlink = 1 67 | } 68 | } 69 | 70 | func (m *fileSystemMount) fillAttr(out *fuse.AttrOut, nodeId uint64) { 71 | splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec) 72 | m.setOwner(&out.Attr) 73 | out.Ino = nodeId 74 | } 75 | 76 | func (m *fileSystemMount) getOpenedFile(h uint64) *openedFile { 77 | var b *openedFile 78 | if h != 0 { 79 | b = (*openedFile)(unsafe.Pointer(m.openFiles.Decode(h))) 80 | } 81 | 82 | if b != nil && m.connector.debug && b.WithFlags.Description != "" { 83 | log.Printf("File %d = %q", h, b.WithFlags.Description) 84 | } 85 | return b 86 | } 87 | 88 | func (m *fileSystemMount) unregisterFileHandle(handle uint64, node *Inode) *openedFile { 89 | _, obj := m.openFiles.Forget(handle, 1) 90 | opened := (*openedFile)(unsafe.Pointer(obj)) 91 | node.openFilesMutex.Lock() 92 | idx := -1 93 | for i, v := range node.openFiles { 94 | if v == opened { 95 | idx = i 96 | break 97 | } 98 | } 99 | 100 | l := len(node.openFiles) 101 | if idx == l-1 { 102 | node.openFiles[idx] = nil 103 | } else { 104 | node.openFiles[idx] = node.openFiles[l-1] 105 | } 106 | node.openFiles = node.openFiles[:l-1] 107 | node.openFilesMutex.Unlock() 108 | 109 | return opened 110 | } 111 | 112 | func (m *fileSystemMount) registerFileHandle(node *Inode, dir *connectorDir, f File, flags uint32) (uint64, *openedFile) { 113 | node.openFilesMutex.Lock() 114 | b := &openedFile{ 115 | dir: dir, 116 | WithFlags: WithFlags{ 117 | File: f, 118 | OpenFlags: flags, 119 | }, 120 | } 121 | 122 | for { 123 | withFlags, ok := f.(*WithFlags) 124 | if !ok { 125 | break 126 | } 127 | 128 | b.WithFlags.File = withFlags.File 129 | b.WithFlags.FuseFlags |= withFlags.FuseFlags 130 | b.WithFlags.Description += withFlags.Description 131 | f = withFlags.File 132 | } 133 | 134 | if b.WithFlags.File != nil { 135 | b.WithFlags.File.SetInode(node) 136 | } 137 | node.openFiles = append(node.openFiles, b) 138 | handle, _ := m.openFiles.Register(&b.handled) 139 | node.openFilesMutex.Unlock() 140 | return handle, b 141 | } 142 | 143 | // Creates a return entry for a non-existent path. 144 | func (m *fileSystemMount) negativeEntry(out *fuse.EntryOut) bool { 145 | if m.options.NegativeTimeout > 0.0 { 146 | out.NodeId = 0 147 | splitDuration(m.options.NegativeTimeout, &out.EntryValid, &out.EntryValidNsec) 148 | return true 149 | } 150 | return false 151 | } 152 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/fuse.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "github.com/hanwen/go-fuse/fuse" 5 | ) 6 | 7 | // Mounts a filesystem with the given root node on the given directory 8 | func MountRoot(mountpoint string, root Node, opts *Options) (*fuse.Server, *FileSystemConnector, error) { 9 | conn := NewFileSystemConnector(root, opts) 10 | s, err := fuse.NewServer(conn.RawFS(), mountpoint, nil) 11 | if err != nil { 12 | return nil, nil, err 13 | } 14 | return s, conn, nil 15 | } 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/handle.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "log" 5 | "sync" 6 | ) 7 | 8 | // HandleMap translates objects in Go space to 64-bit handles that can 9 | // be given out to -say- the linux kernel. 10 | // 11 | // The 32 bits version of this is a threadsafe wrapper around a map. 12 | // 13 | // To use it, include Handled as first member of the structure 14 | // you wish to export. 15 | // 16 | // This structure is thread-safe. 17 | type handleMap interface { 18 | Register(obj *handled) (handle, generation uint64) 19 | Count() int 20 | Decode(uint64) *handled 21 | Forget(handle uint64, count int) (bool, *handled) 22 | Handle(obj *handled) uint64 23 | Has(uint64) bool 24 | } 25 | 26 | type handled struct { 27 | check uint32 28 | handle uint64 29 | count int 30 | } 31 | 32 | func (h *handled) verify() { 33 | if h.count < 0 { 34 | log.Panicf("negative lookup count %d", h.count) 35 | } 36 | if (h.count == 0) != (h.handle == 0) { 37 | log.Panicf("registration mismatch: lookup %d id %d", h.count, h.handle) 38 | } 39 | } 40 | 41 | const _ALREADY_MSG = "Object already has a handle" 42 | 43 | //////////////////////////////////////////////////////////////// 44 | // portable version using 32 bit integers. 45 | 46 | type portableHandleMap struct { 47 | sync.RWMutex 48 | generation uint64 49 | used int 50 | handles []*handled 51 | freeIds []uint64 52 | } 53 | 54 | func newPortableHandleMap() *portableHandleMap { 55 | return &portableHandleMap{ 56 | // Avoid handing out ID 0 and 1. 57 | handles: []*handled{nil, nil}, 58 | } 59 | } 60 | 61 | func (m *portableHandleMap) Register(obj *handled) (handle, generation uint64) { 62 | m.Lock() 63 | if obj.count == 0 { 64 | if obj.check != 0 { 65 | panic(_ALREADY_MSG) 66 | } 67 | 68 | if len(m.freeIds) == 0 { 69 | handle = uint64(len(m.handles)) 70 | m.handles = append(m.handles, obj) 71 | } else { 72 | handle = m.freeIds[len(m.freeIds)-1] 73 | m.freeIds = m.freeIds[:len(m.freeIds)-1] 74 | m.generation++ 75 | m.handles[handle] = obj 76 | } 77 | m.used++ 78 | obj.handle = handle 79 | } else { 80 | handle = obj.handle 81 | } 82 | obj.count++ 83 | generation = m.generation 84 | m.Unlock() 85 | return 86 | } 87 | 88 | func (m *portableHandleMap) Handle(obj *handled) (h uint64) { 89 | m.RLock() 90 | if obj.count == 0 { 91 | h = 0 92 | } else { 93 | h = obj.handle 94 | } 95 | m.RUnlock() 96 | return h 97 | } 98 | 99 | func (m *portableHandleMap) Count() int { 100 | m.RLock() 101 | c := m.used 102 | m.RUnlock() 103 | return c 104 | } 105 | 106 | func (m *portableHandleMap) Decode(h uint64) *handled { 107 | m.RLock() 108 | v := m.handles[h] 109 | m.RUnlock() 110 | return v 111 | } 112 | 113 | func (m *portableHandleMap) Forget(h uint64, count int) (forgotten bool, obj *handled) { 114 | m.Lock() 115 | obj = m.handles[h] 116 | obj.count -= count 117 | if obj.count < 0 { 118 | log.Panicf("underflow: handle %d, count %d, object %d", h, count, obj.count) 119 | } else if obj.count == 0 { 120 | m.handles[h] = nil 121 | m.freeIds = append(m.freeIds, h) 122 | m.used-- 123 | forgotten = true 124 | obj.handle = 0 125 | } 126 | m.Unlock() 127 | return forgotten, obj 128 | } 129 | 130 | func (m *portableHandleMap) Has(h uint64) bool { 131 | m.RLock() 132 | ok := m.handles[h] != nil 133 | m.RUnlock() 134 | return ok 135 | } 136 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/lockingfile.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | 8 | "github.com/hanwen/go-fuse/fuse" 9 | ) 10 | 11 | type lockingFile struct { 12 | mu *sync.Mutex 13 | file File 14 | } 15 | 16 | // NewLockingFile serializes operations an existing File. 17 | func NewLockingFile(mu *sync.Mutex, f File) File { 18 | return &lockingFile{ 19 | mu: mu, 20 | file: f, 21 | } 22 | } 23 | 24 | func (f *lockingFile) SetInode(*Inode) { 25 | } 26 | 27 | func (f *lockingFile) InnerFile() File { 28 | return f.file 29 | } 30 | 31 | func (f *lockingFile) String() string { 32 | return fmt.Sprintf("lockingFile(%s)", f.file.String()) 33 | } 34 | 35 | func (f *lockingFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) { 36 | f.mu.Lock() 37 | defer f.mu.Unlock() 38 | return f.file.Read(buf, off) 39 | } 40 | 41 | func (f *lockingFile) Write(data []byte, off int64) (uint32, fuse.Status) { 42 | f.mu.Lock() 43 | defer f.mu.Unlock() 44 | return f.file.Write(data, off) 45 | } 46 | 47 | func (f *lockingFile) Flush() fuse.Status { 48 | f.mu.Lock() 49 | defer f.mu.Unlock() 50 | return f.file.Flush() 51 | } 52 | 53 | func (f *lockingFile) Release() { 54 | f.mu.Lock() 55 | defer f.mu.Unlock() 56 | f.file.Release() 57 | } 58 | 59 | func (f *lockingFile) GetAttr(a *fuse.Attr) fuse.Status { 60 | f.mu.Lock() 61 | defer f.mu.Unlock() 62 | return f.file.GetAttr(a) 63 | } 64 | 65 | func (f *lockingFile) Fsync(flags int) (code fuse.Status) { 66 | f.mu.Lock() 67 | defer f.mu.Unlock() 68 | return f.file.Fsync(flags) 69 | } 70 | 71 | func (f *lockingFile) Utimens(atime *time.Time, mtime *time.Time) fuse.Status { 72 | f.mu.Lock() 73 | defer f.mu.Unlock() 74 | return f.file.Utimens(atime, mtime) 75 | } 76 | 77 | func (f *lockingFile) Truncate(size uint64) fuse.Status { 78 | f.mu.Lock() 79 | defer f.mu.Unlock() 80 | return f.file.Truncate(size) 81 | } 82 | 83 | func (f *lockingFile) Chown(uid uint32, gid uint32) fuse.Status { 84 | f.mu.Lock() 85 | defer f.mu.Unlock() 86 | return f.file.Chown(uid, gid) 87 | } 88 | 89 | func (f *lockingFile) Chmod(perms uint32) fuse.Status { 90 | f.mu.Lock() 91 | defer f.mu.Unlock() 92 | return f.file.Chmod(perms) 93 | } 94 | 95 | func (f *lockingFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) { 96 | f.mu.Lock() 97 | defer f.mu.Unlock() 98 | return f.file.Allocate(off, size, mode) 99 | } 100 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/nodefs.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import "time" 4 | 5 | func splitDuration(dt time.Duration, secs *uint64, nsecs *uint32) { 6 | ns := int64(dt) 7 | *nsecs = uint32(ns % 1e9) 8 | *secs = uint64(ns / 1e9) 9 | } 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/nodefs/print.go: -------------------------------------------------------------------------------- 1 | package nodefs 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/hanwen/go-fuse/fuse" 7 | ) 8 | 9 | // String provides a debug string for the given file. 10 | func (f *WithFlags) String() string { 11 | return fmt.Sprintf("File %s (%s) %s %s", 12 | f.File, f.Description, fuse.FlagString(fuse.OpenFlagNames, int64(f.OpenFlags), "O_RDONLY"), 13 | fuse.FlagString(fuse.FuseOpenFlagNames, int64(f.FuseFlags), "")) 14 | } 15 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/pathfs/api.go: -------------------------------------------------------------------------------- 1 | package pathfs 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/hanwen/go-fuse/fuse" 7 | "github.com/hanwen/go-fuse/fuse/nodefs" 8 | ) 9 | 10 | // A filesystem API that uses paths rather than inodes. A minimal 11 | // file system should have at least a functional GetAttr method. 12 | // Typically, each call happens in its own goroutine, so take care to 13 | // make the file system thread-safe. 14 | // 15 | // NewDefaultFileSystem provides a null implementation of required 16 | // methods. 17 | type FileSystem interface { 18 | // Used for pretty printing. 19 | String() string 20 | 21 | // If called, provide debug output through the log package. 22 | SetDebug(debug bool) 23 | 24 | // Attributes. This function is the main entry point, through 25 | // which FUSE discovers which files and directories exist. 26 | // 27 | // If the filesystem wants to implement hard-links, it should 28 | // return consistent non-zero FileInfo.Ino data. Using 29 | // hardlinks incurs a performance hit. 30 | GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) 31 | 32 | // These should update the file's ctime too. 33 | Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) 34 | Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) 35 | Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) 36 | 37 | Truncate(name string, size uint64, context *fuse.Context) (code fuse.Status) 38 | 39 | Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) 40 | 41 | // Tree structure 42 | Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) 43 | Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status 44 | Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status 45 | Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) 46 | Rmdir(name string, context *fuse.Context) (code fuse.Status) 47 | Unlink(name string, context *fuse.Context) (code fuse.Status) 48 | 49 | // Extended attributes. 50 | GetXAttr(name string, attribute string, context *fuse.Context) (data []byte, code fuse.Status) 51 | ListXAttr(name string, context *fuse.Context) (attributes []string, code fuse.Status) 52 | RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status 53 | SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status 54 | 55 | // Called after mount. 56 | OnMount(nodeFs *PathNodeFs) 57 | OnUnmount() 58 | 59 | // File handling. If opening for writing, the file's mtime 60 | // should be updated too. 61 | Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) 62 | Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) 63 | 64 | // Directory handling 65 | OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, code fuse.Status) 66 | 67 | // Symlinks. 68 | Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) 69 | Readlink(name string, context *fuse.Context) (string, fuse.Status) 70 | 71 | StatFs(name string) *fuse.StatfsOut 72 | } 73 | 74 | type PathNodeFsOptions struct { 75 | // If ClientInodes is set, use Inode returned from GetAttr to 76 | // find hard-linked files. 77 | ClientInodes bool 78 | } 79 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/pathfs/copy.go: -------------------------------------------------------------------------------- 1 | package pathfs 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/hanwen/go-fuse/fuse" 7 | ) 8 | 9 | func CopyFile(srcFs, destFs FileSystem, srcFile, destFile string, context *fuse.Context) fuse.Status { 10 | src, code := srcFs.Open(srcFile, uint32(os.O_RDONLY), context) 11 | if !code.Ok() { 12 | return code 13 | } 14 | defer src.Release() 15 | defer src.Flush() 16 | 17 | attr, code := srcFs.GetAttr(srcFile, context) 18 | if !code.Ok() { 19 | return code 20 | } 21 | 22 | dst, code := destFs.Create(destFile, uint32(os.O_WRONLY|os.O_CREATE|os.O_TRUNC), attr.Mode, context) 23 | if !code.Ok() { 24 | return code 25 | } 26 | defer dst.Release() 27 | defer dst.Flush() 28 | 29 | buf := make([]byte, 128*(1<<10)) 30 | off := int64(0) 31 | for { 32 | res, code := src.Read(buf, off) 33 | if !code.Ok() { 34 | return code 35 | } 36 | data, code := res.Bytes(buf) 37 | if !code.Ok() { 38 | return code 39 | } 40 | 41 | if len(data) == 0 { 42 | break 43 | } 44 | n, code := dst.Write(data, off) 45 | if !code.Ok() { 46 | return code 47 | } 48 | if int(n) < len(data) { 49 | return fuse.EIO 50 | } 51 | if len(data) < len(buf) { 52 | break 53 | } 54 | off += int64(len(data)) 55 | } 56 | return fuse.OK 57 | } 58 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/pathfs/loopback_darwin.go: -------------------------------------------------------------------------------- 1 | package pathfs 2 | 3 | import ( 4 | "syscall" 5 | 6 | "github.com/hanwen/go-fuse/fuse" 7 | ) 8 | 9 | func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut { 10 | s := syscall.Statfs_t{} 11 | err := syscall.Statfs(fs.GetPath(name), &s) 12 | if err == nil { 13 | return &fuse.StatfsOut{ 14 | Blocks: s.Blocks, 15 | Bsize: uint32(s.Bsize), 16 | Bfree: s.Bfree, 17 | Bavail: s.Bavail, 18 | Files: s.Files, 19 | Ffree: s.Ffree, 20 | } 21 | } 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/pathfs/loopback_linux.go: -------------------------------------------------------------------------------- 1 | package pathfs 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | 7 | "github.com/hanwen/go-fuse/fuse" 8 | ) 9 | 10 | func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut { 11 | s := syscall.Statfs_t{} 12 | err := syscall.Statfs(fs.GetPath(name), &s) 13 | if err == nil { 14 | return &fuse.StatfsOut{ 15 | Blocks: s.Blocks, 16 | Bsize: uint32(s.Bsize), 17 | Bfree: s.Bfree, 18 | Bavail: s.Bavail, 19 | Files: s.Files, 20 | Ffree: s.Ffree, 21 | Frsize: uint32(s.Frsize), 22 | NameLen: uint32(s.Namelen), 23 | } 24 | } 25 | return nil 26 | } 27 | 28 | func (fs *loopbackFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) { 29 | data, err := listXAttr(fs.GetPath(name)) 30 | 31 | return data, fuse.ToStatus(err) 32 | } 33 | 34 | func (fs *loopbackFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status { 35 | err := sysRemovexattr(fs.GetPath(name), attr) 36 | return fuse.ToStatus(err) 37 | } 38 | 39 | func (fs *loopbackFileSystem) String() string { 40 | return fmt.Sprintf("LoopbackFs(%s)", fs.Root) 41 | } 42 | 43 | func (fs *loopbackFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) { 44 | data := make([]byte, 1024) 45 | data, err := getXAttr(fs.GetPath(name), attr, data) 46 | 47 | return data, fuse.ToStatus(err) 48 | } 49 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/pathfs/syscall_linux.go: -------------------------------------------------------------------------------- 1 | package pathfs 2 | 3 | import ( 4 | "bytes" 5 | "syscall" 6 | "unsafe" 7 | ) 8 | 9 | var _zero uintptr 10 | 11 | func getXAttr(path string, attr string, dest []byte) (value []byte, err error) { 12 | sz, err := sysGetxattr(path, attr, dest) 13 | for sz > cap(dest) && err == nil { 14 | dest = make([]byte, sz) 15 | sz, err = sysGetxattr(path, attr, dest) 16 | } 17 | 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | return dest[:sz], err 23 | } 24 | 25 | func listXAttr(path string) (attributes []string, err error) { 26 | dest := make([]byte, 0) 27 | sz, err := sysListxattr(path, dest) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | for sz > cap(dest) && err == nil { 33 | dest = make([]byte, sz) 34 | sz, err = sysListxattr(path, dest) 35 | } 36 | 37 | // -1 to drop the final empty slice. 38 | dest = dest[:sz-1] 39 | attributesBytes := bytes.Split(dest, []byte{0}) 40 | attributes = make([]string, len(attributesBytes)) 41 | for i, v := range attributesBytes { 42 | attributes[i] = string(v) 43 | } 44 | return attributes, err 45 | } 46 | 47 | // Below is cut & paste from std lib syscall, so gccgo 4.8.1 can 48 | // compile this too. 49 | func sysGetxattr(path string, attr string, dest []byte) (sz int, err error) { 50 | var _p0 *byte 51 | _p0, err = syscall.BytePtrFromString(path) 52 | if err != nil { 53 | return 54 | } 55 | var _p1 *byte 56 | _p1, err = syscall.BytePtrFromString(attr) 57 | if err != nil { 58 | return 59 | } 60 | var _p2 unsafe.Pointer 61 | if len(dest) > 0 { 62 | _p2 = unsafe.Pointer(&dest[0]) 63 | } else { 64 | _p2 = unsafe.Pointer(&_zero) 65 | } 66 | r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0) 67 | sz = int(r0) 68 | if e1 != 0 { 69 | err = e1 70 | } 71 | return 72 | } 73 | 74 | func sysRemovexattr(path string, attr string) (err error) { 75 | var _p0 *byte 76 | _p0, err = syscall.BytePtrFromString(path) 77 | if err != nil { 78 | return 79 | } 80 | var _p1 *byte 81 | _p1, err = syscall.BytePtrFromString(attr) 82 | if err != nil { 83 | return 84 | } 85 | _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) 86 | if e1 != 0 { 87 | err = e1 88 | } 89 | return 90 | } 91 | 92 | func sysListxattr(path string, dest []byte) (sz int, err error) { 93 | var _p0 *byte 94 | _p0, err = syscall.BytePtrFromString(path) 95 | if err != nil { 96 | return 97 | } 98 | var _p1 unsafe.Pointer 99 | if len(dest) > 0 { 100 | _p1 = unsafe.Pointer(&dest[0]) 101 | } else { 102 | _p1 = unsafe.Pointer(&_zero) 103 | } 104 | r0, _, e1 := syscall.Syscall(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) 105 | sz = int(r0) 106 | if e1 != 0 { 107 | err = e1 108 | } 109 | return 110 | } 111 | 112 | func sysSetxattr(path string, attr string, val []byte, flag int) error { 113 | return syscall.Setxattr(path, attr, val, flag) 114 | } 115 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/print_darwin.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func init() { 8 | initFlagNames[CAP_XTIMES] = "XTIMES" 9 | initFlagNames[CAP_VOL_RENAME] = "VOL_RENAME" 10 | initFlagNames[CAP_CASE_INSENSITIVE] = "CASE_INSENSITIVE" 11 | } 12 | 13 | func (a *Attr) string() string { 14 | return fmt.Sprintf( 15 | "{M0%o SZ=%d L=%d "+ 16 | "%d:%d "+ 17 | "%d %d:%d "+ 18 | "A %d.%09d "+ 19 | "M %d.%09d "+ 20 | "C %d.%09d}", 21 | a.Mode, a.Size, a.Nlink, 22 | a.Uid, a.Gid, 23 | a.Blocks, 24 | a.Rdev, a.Ino, a.Atime, a.Atimensec, a.Mtime, a.Mtimensec, 25 | a.Ctime, a.Ctimensec) 26 | } 27 | 28 | func (me *CreateIn) string() string { 29 | return fmt.Sprintf( 30 | "{0%o [%s]}", me.Mode, 31 | FlagString(OpenFlagNames, int64(me.Flags), "O_RDONLY")) 32 | } 33 | 34 | func (me *GetAttrIn) string() string { return "" } 35 | 36 | func (me *MknodIn) string() string { 37 | return fmt.Sprintf("{0%o, %d}", me.Mode, me.Rdev) 38 | } 39 | 40 | func (me *ReadIn) string() string { 41 | return fmt.Sprintf("{Fh %d off %d sz %d %s L %d %s}", 42 | me.Fh, me.Offset, me.Size, 43 | FlagString(readFlagNames, int64(me.ReadFlags), "")) 44 | } 45 | 46 | func (me *WriteIn) string() string { 47 | return fmt.Sprintf("{Fh %d off %d sz %d %s}", 48 | me.Fh, me.Offset, me.Size, 49 | FlagString(writeFlagNames, int64(me.WriteFlags), "")) 50 | } 51 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/print_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | ) 7 | 8 | func init() { 9 | OpenFlagNames[syscall.O_DIRECT] = "DIRECT" 10 | OpenFlagNames[syscall.O_LARGEFILE] = "LARGEFILE" 11 | OpenFlagNames[syscall_O_NOATIME] = "NOATIME" 12 | 13 | } 14 | 15 | func (a *Attr) string() string { 16 | return fmt.Sprintf( 17 | "{M0%o SZ=%d L=%d "+ 18 | "%d:%d "+ 19 | "B%d*%d i%d:%d "+ 20 | "A %d.%09d "+ 21 | "M %d.%09d "+ 22 | "C %d.%09d}", 23 | a.Mode, a.Size, a.Nlink, 24 | a.Uid, a.Gid, 25 | a.Blocks, a.Blksize, 26 | a.Rdev, a.Ino, a.Atime, a.Atimensec, a.Mtime, a.Mtimensec, 27 | a.Ctime, a.Ctimensec) 28 | } 29 | 30 | func (me *CreateIn) string() string { 31 | return fmt.Sprintf( 32 | "{0%o [%s] (0%o)}", me.Mode, 33 | FlagString(OpenFlagNames, int64(me.Flags), "O_RDONLY"), me.Umask) 34 | } 35 | 36 | func (me *GetAttrIn) string() string { 37 | return fmt.Sprintf("{Fh %d}", me.Fh_) 38 | } 39 | 40 | func (me *MknodIn) string() string { 41 | return fmt.Sprintf("{0%o (0%o), %d}", me.Mode, me.Umask, me.Rdev) 42 | } 43 | 44 | func (me *ReadIn) string() string { 45 | return fmt.Sprintf("{Fh %d off %d sz %d %s L %d %s}", 46 | me.Fh, me.Offset, me.Size, 47 | FlagString(readFlagNames, int64(me.ReadFlags), ""), 48 | me.LockOwner, 49 | FlagString(OpenFlagNames, int64(me.Flags), "RDONLY")) 50 | } 51 | 52 | func (me *WriteIn) string() string { 53 | return fmt.Sprintf("{Fh %d off %d sz %d %s L %d %s}", 54 | me.Fh, me.Offset, me.Size, 55 | FlagString(writeFlagNames, int64(me.WriteFlags), ""), 56 | me.LockOwner, 57 | FlagString(OpenFlagNames, int64(me.Flags), "RDONLY")) 58 | } 59 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/read.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "io" 5 | "syscall" 6 | ) 7 | 8 | // ReadResultData is the read return for returning bytes directly. 9 | type readResultData struct { 10 | // Raw bytes for the read. 11 | Data []byte 12 | } 13 | 14 | func (r *readResultData) Size() int { 15 | return len(r.Data) 16 | } 17 | 18 | func (r *readResultData) Done() { 19 | } 20 | 21 | func (r *readResultData) Bytes(buf []byte) ([]byte, Status) { 22 | return r.Data, OK 23 | } 24 | 25 | func ReadResultData(b []byte) ReadResult { 26 | return &readResultData{b} 27 | } 28 | 29 | func ReadResultFd(fd uintptr, off int64, sz int) ReadResult { 30 | return &readResultFd{fd, off, sz} 31 | } 32 | 33 | // ReadResultFd is the read return for zero-copy file data. 34 | type readResultFd struct { 35 | // Splice from the following file. 36 | Fd uintptr 37 | 38 | // Offset within Fd, or -1 to use current offset. 39 | Off int64 40 | 41 | // Size of data to be loaded. Actual data available may be 42 | // less at the EOF. 43 | Sz int 44 | } 45 | 46 | // Reads raw bytes from file descriptor if necessary, using the passed 47 | // buffer as storage. 48 | func (r *readResultFd) Bytes(buf []byte) ([]byte, Status) { 49 | sz := r.Sz 50 | if len(buf) < sz { 51 | sz = len(buf) 52 | } 53 | 54 | n, err := syscall.Pread(int(r.Fd), buf[:sz], r.Off) 55 | if err == io.EOF { 56 | err = nil 57 | } 58 | 59 | if n < 0 { 60 | n = 0 61 | } 62 | 63 | return buf[:n], ToStatus(err) 64 | } 65 | 66 | func (r *readResultFd) Size() int { 67 | return r.Sz 68 | } 69 | 70 | func (r *readResultFd) Done() { 71 | } 72 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/request_darwin.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | const outputHeaderSize = 200 4 | 5 | const ( 6 | _FUSE_KERNEL_VERSION = 7 7 | _MINIMUM_MINOR_VERSION = 8 8 | _OUR_MINOR_VERSION = 8 9 | ) 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/request_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | const outputHeaderSize = 160 4 | 5 | const ( 6 | _FUSE_KERNEL_VERSION = 7 7 | _MINIMUM_MINOR_VERSION = 12 8 | _OUR_MINOR_VERSION = 21 9 | ) 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/server_darwin.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | func (ms *Server) systemWrite(req *request, header []byte) Status { 8 | if req.flatDataSize() == 0 { 9 | err := handleEINTR(func() error { 10 | _, err := syscall.Write(ms.mountFd, header) 11 | return err 12 | }) 13 | return ToStatus(err) 14 | } 15 | 16 | if req.fdData != nil { 17 | sz := req.flatDataSize() 18 | buf := ms.allocOut(req, uint32(sz)) 19 | req.flatData, req.status = req.fdData.Bytes(buf) 20 | header = req.serializeHeader(len(req.flatData)) 21 | } 22 | 23 | _, err := writev(int(ms.mountFd), [][]byte{header, req.flatData}) 24 | if req.readResult != nil { 25 | req.readResult.Done() 26 | } 27 | return ToStatus(err) 28 | } 29 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/server_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "log" 5 | "syscall" 6 | ) 7 | 8 | func (ms *Server) systemWrite(req *request, header []byte) Status { 9 | if req.flatDataSize() == 0 { 10 | err := handleEINTR(func() error { 11 | _, err := syscall.Write(ms.mountFd, header) 12 | return err 13 | }) 14 | return ToStatus(err) 15 | } 16 | 17 | if req.fdData != nil { 18 | if ms.canSplice { 19 | err := ms.trySplice(header, req, req.fdData) 20 | if err == nil { 21 | req.readResult.Done() 22 | return OK 23 | } 24 | log.Println("trySplice:", err) 25 | } 26 | 27 | sz := req.flatDataSize() 28 | buf := ms.allocOut(req, uint32(sz)) 29 | req.flatData, req.status = req.fdData.Bytes(buf) 30 | header = req.serializeHeader(len(req.flatData)) 31 | } 32 | 33 | _, err := writev(ms.mountFd, [][]byte{header, req.flatData}) 34 | if req.readResult != nil { 35 | req.readResult.Done() 36 | } 37 | return ToStatus(err) 38 | } 39 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/splice_darwin.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func (s *Server) setSplice() { 8 | panic("darwin has no splice.") 9 | } 10 | 11 | func (ms *Server) trySplice(header []byte, req *request, fdData *readResultFd) error { 12 | return fmt.Errorf("unimplemented") 13 | } 14 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/splice_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | 7 | "github.com/hanwen/go-fuse/splice" 8 | ) 9 | 10 | func (s *Server) setSplice() { 11 | s.canSplice = splice.Resizable() 12 | } 13 | 14 | func (ms *Server) trySplice(header []byte, req *request, fdData *readResultFd) error { 15 | pair, err := splice.Get() 16 | if err != nil { 17 | return err 18 | } 19 | defer splice.Done(pair) 20 | 21 | total := len(header) + fdData.Size() 22 | if err := pair.Grow(total); err != nil { 23 | return err 24 | } 25 | 26 | _, err = pair.Write(header) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | var n int 32 | if fdData.Off < 0 { 33 | n, err = pair.LoadFrom(fdData.Fd, fdData.Size()) 34 | } else { 35 | n, err = pair.LoadFromAt(fdData.Fd, fdData.Size(), fdData.Off) 36 | } 37 | if err == io.EOF || (err == nil && n < fdData.Size()) { 38 | discard := make([]byte, len(header)) 39 | _, err = pair.Read(discard) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | header = req.serializeHeader(n) 45 | 46 | newFd := readResultFd{ 47 | Fd: pair.ReadFd(), 48 | Off: -1, 49 | Sz: n, 50 | } 51 | return ms.trySplice(header, req, &newFd) 52 | } 53 | 54 | if err != nil { 55 | // TODO - extract the data from splice. 56 | return err 57 | } 58 | 59 | if n != fdData.Size() { 60 | return fmt.Errorf("wrote %d, want %d", n, fdData.Size()) 61 | } 62 | 63 | _, err = pair.WriteTo(uintptr(ms.mountFd), total) 64 | if err != nil { 65 | return err 66 | } 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/syscall_darwin.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "bytes" 5 | "os" 6 | "syscall" 7 | "unsafe" 8 | ) 9 | 10 | // TODO - move these into Go's syscall package. 11 | 12 | func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, err error) { 13 | n1, _, e1 := syscall.Syscall( 14 | syscall.SYS_WRITEV, 15 | uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt)) 16 | n = int(n1) 17 | if e1 != 0 { 18 | err = syscall.Errno(e1) 19 | } 20 | return 21 | } 22 | 23 | func writev(fd int, packet [][]byte) (n int, err error) { 24 | iovecs := make([]syscall.Iovec, 0, len(packet)) 25 | 26 | for _, v := range packet { 27 | if len(v) == 0 { 28 | continue 29 | } 30 | vec := syscall.Iovec{ 31 | Base: &v[0], 32 | } 33 | vec.SetLen(len(v)) 34 | iovecs = append(iovecs, vec) 35 | } 36 | 37 | sysErr := handleEINTR(func() error { 38 | var err error 39 | n, err = sys_writev(fd, &iovecs[0], len(iovecs)) 40 | return err 41 | }) 42 | if sysErr != nil { 43 | err = os.NewSyscallError("writev", sysErr) 44 | } 45 | return n, err 46 | } 47 | 48 | func getxattr(path string, attr string, dest []byte) (sz int, errno int) { 49 | pathBs := syscall.StringBytePtr(path) 50 | attrBs := syscall.StringBytePtr(attr) 51 | size, _, errNo := syscall.Syscall6( 52 | syscall.SYS_GETXATTR, 53 | uintptr(unsafe.Pointer(pathBs)), 54 | uintptr(unsafe.Pointer(attrBs)), 55 | uintptr(unsafe.Pointer(&dest[0])), 56 | uintptr(len(dest)), 57 | 0, 0) 58 | return int(size), int(errNo) 59 | } 60 | 61 | func GetXAttr(path string, attr string, dest []byte) (value []byte, errno int) { 62 | sz, errno := getxattr(path, attr, dest) 63 | 64 | for sz > cap(dest) && errno == 0 { 65 | dest = make([]byte, sz) 66 | sz, errno = getxattr(path, attr, dest) 67 | } 68 | 69 | if errno != 0 { 70 | return nil, errno 71 | } 72 | 73 | return dest[:sz], errno 74 | } 75 | 76 | func listxattr(path string, dest []byte) (sz int, errno int) { 77 | pathbs := syscall.StringBytePtr(path) 78 | var destPointer unsafe.Pointer 79 | if len(dest) > 0 { 80 | destPointer = unsafe.Pointer(&dest[0]) 81 | } 82 | size, _, errNo := syscall.Syscall( 83 | syscall.SYS_LISTXATTR, 84 | uintptr(unsafe.Pointer(pathbs)), 85 | uintptr(destPointer), 86 | uintptr(len(dest))) 87 | 88 | return int(size), int(errNo) 89 | } 90 | 91 | func ListXAttr(path string) (attributes []string, errno int) { 92 | dest := make([]byte, 0) 93 | sz, errno := listxattr(path, dest) 94 | if errno != 0 { 95 | return nil, errno 96 | } 97 | 98 | for sz > cap(dest) && errno == 0 { 99 | dest = make([]byte, sz) 100 | sz, errno = listxattr(path, dest) 101 | } 102 | 103 | // -1 to drop the final empty slice. 104 | dest = dest[:sz-1] 105 | attributesBytes := bytes.Split(dest, []byte{0}) 106 | attributes = make([]string, len(attributesBytes)) 107 | for i, v := range attributesBytes { 108 | attributes[i] = string(v) 109 | } 110 | return attributes, errno 111 | } 112 | 113 | func Setxattr(path string, attr string, data []byte, flags int) (errno int) { 114 | pathbs := syscall.StringBytePtr(path) 115 | attrbs := syscall.StringBytePtr(attr) 116 | _, _, errNo := syscall.Syscall6( 117 | syscall.SYS_SETXATTR, 118 | uintptr(unsafe.Pointer(pathbs)), 119 | uintptr(unsafe.Pointer(attrbs)), 120 | uintptr(unsafe.Pointer(&data[0])), 121 | uintptr(len(data)), 122 | uintptr(flags), 0) 123 | 124 | return int(errNo) 125 | } 126 | 127 | func Removexattr(path string, attr string) (errno int) { 128 | pathbs := syscall.StringBytePtr(path) 129 | attrbs := syscall.StringBytePtr(attr) 130 | _, _, errNo := syscall.Syscall( 131 | syscall.SYS_REMOVEXATTR, 132 | uintptr(unsafe.Pointer(pathbs)), 133 | uintptr(unsafe.Pointer(attrbs)), 0) 134 | return int(errNo) 135 | } 136 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/syscall_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | import ( 4 | "os" 5 | "syscall" 6 | "unsafe" 7 | ) 8 | 9 | // TODO - move these into Go's syscall package. 10 | 11 | func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, err error) { 12 | n1, _, e1 := syscall.Syscall( 13 | syscall.SYS_WRITEV, 14 | uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt)) 15 | n = int(n1) 16 | if e1 != 0 { 17 | err = syscall.Errno(e1) 18 | } 19 | return n, err 20 | } 21 | 22 | func writev(fd int, packet [][]byte) (n int, err error) { 23 | iovecs := make([]syscall.Iovec, 0, len(packet)) 24 | 25 | for _, v := range packet { 26 | if len(v) == 0 { 27 | continue 28 | } 29 | vec := syscall.Iovec{ 30 | Base: &v[0], 31 | } 32 | vec.SetLen(len(v)) 33 | iovecs = append(iovecs, vec) 34 | } 35 | 36 | sysErr := handleEINTR(func() error { 37 | var err error 38 | n, err = sys_writev(fd, &iovecs[0], len(iovecs)) 39 | return err 40 | }) 41 | if sysErr != nil { 42 | err = os.NewSyscallError("writev", sysErr) 43 | } 44 | return n, err 45 | } 46 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/test/verbose.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import "flag" 4 | 5 | // VerboseTest returns true if the testing framework is run with -v. 6 | func VerboseTest() bool { 7 | flag := flag.Lookup("test.v") 8 | return flag != nil && flag.Value.String() == "true" 9 | } 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/typeprint.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | func (a *Attr) String() string { 4 | return Print((*Attr)(a)) 5 | } 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/types_darwin.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | type Attr struct { 4 | Ino uint64 5 | Size uint64 6 | Blocks uint64 7 | Atime uint64 8 | Mtime uint64 9 | Ctime uint64 10 | Crtime_ uint64 // OS X 11 | Atimensec uint32 12 | Mtimensec uint32 13 | Ctimensec uint32 14 | Crtimensec_ uint32 // OS X 15 | Mode uint32 16 | Nlink uint32 17 | Owner 18 | Rdev uint32 19 | Flags_ uint32 // OS X 20 | } 21 | 22 | const ( 23 | FATTR_CRTIME = (1 << 28) 24 | FATTR_CHGTIME = (1 << 29) 25 | FATTR_BKUPTIME = (1 << 30) 26 | FATTR_FLAGS = (1 << 31) 27 | ) 28 | 29 | type SetAttrIn struct { 30 | SetAttrInCommon 31 | 32 | // OS X only 33 | Bkuptime_ uint64 34 | Chgtime_ uint64 35 | Crtime uint64 36 | BkuptimeNsec uint32 37 | ChgtimeNsec uint32 38 | CrtimeNsec uint32 39 | Flags_ uint32 // see chflags(2) 40 | } 41 | 42 | const ( 43 | FOPEN_PURGE_ATTR = (1 << 30) 44 | FOPEN_PURGE_UBC = (1 << 31) 45 | ) 46 | 47 | // compat with linux. 48 | const ( 49 | // Mask for GetAttrIn.Flags. If set, GetAttrIn has a file handle set. 50 | FUSE_GETATTR_FH = (1 << 0) 51 | ) 52 | 53 | type GetAttrIn struct { 54 | InHeader 55 | } 56 | 57 | func (g *GetAttrIn) Flags() uint32 { 58 | return 0 59 | } 60 | 61 | func (g *GetAttrIn) Fh() uint64 { 62 | return 0 63 | } 64 | 65 | // Uses OpenIn struct for create. 66 | type CreateIn struct { 67 | InHeader 68 | 69 | Flags uint32 70 | Mode uint32 71 | } 72 | 73 | type MknodIn struct { 74 | InHeader 75 | 76 | Mode uint32 77 | Rdev uint32 78 | } 79 | 80 | type ReadIn struct { 81 | InHeader 82 | 83 | Fh uint64 84 | Offset uint64 85 | Size uint32 86 | ReadFlags uint32 87 | } 88 | 89 | type WriteIn struct { 90 | InHeader 91 | Fh uint64 92 | Offset uint64 93 | Size uint32 94 | WriteFlags uint32 95 | } 96 | 97 | type SetXAttrIn struct { 98 | InHeader 99 | Size uint32 100 | Flags uint32 101 | Position uint32 102 | Padding uint32 103 | } 104 | 105 | type GetXAttrIn struct { 106 | InHeader 107 | Size uint32 108 | Padding uint32 109 | Position uint32 110 | Padding2 uint32 111 | } 112 | 113 | const ( 114 | CAP_CASE_INSENSITIVE = (1 << 29) 115 | CAP_VOL_RENAME = (1 << 30) 116 | CAP_XTIMES = (1 << 31) 117 | ) 118 | 119 | type GetxtimesOut struct { 120 | Bkuptime uint64 121 | Crtime uint64 122 | Bkuptimensec uint32 123 | Crtimensec uint32 124 | } 125 | 126 | type ExchangeIn struct { 127 | InHeader 128 | Olddir uint64 129 | Newdir uint64 130 | Options uint64 131 | } 132 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/fuse/types_linux.go: -------------------------------------------------------------------------------- 1 | package fuse 2 | 3 | type Attr struct { 4 | Ino uint64 5 | Size uint64 6 | Blocks uint64 7 | Atime uint64 8 | Mtime uint64 9 | Ctime uint64 10 | Atimensec uint32 11 | Mtimensec uint32 12 | Ctimensec uint32 13 | Mode uint32 14 | Nlink uint32 15 | Owner 16 | Rdev uint32 17 | Blksize uint32 18 | Padding uint32 19 | } 20 | 21 | type SetAttrIn struct { 22 | SetAttrInCommon 23 | } 24 | 25 | const ( 26 | // Mask for GetAttrIn.Flags. If set, GetAttrIn has a file handle set. 27 | FUSE_GETATTR_FH = (1 << 0) 28 | ) 29 | 30 | type GetAttrIn struct { 31 | InHeader 32 | 33 | Flags_ uint32 34 | Dummy uint32 35 | Fh_ uint64 36 | } 37 | 38 | // Flags accesses the flags. This is a method, because OSXFuse does not 39 | // have GetAttrIn flags. 40 | func (g *GetAttrIn) Flags() uint32 { 41 | return g.Flags_ 42 | } 43 | 44 | // Fh accesses the file handle. This is a method, because OSXFuse does not 45 | // have GetAttrIn flags. 46 | func (g *GetAttrIn) Fh() uint64 { 47 | return g.Fh_ 48 | } 49 | 50 | type CreateIn struct { 51 | InHeader 52 | Flags uint32 53 | Mode uint32 54 | Umask uint32 55 | Pading uint32 56 | } 57 | 58 | type MknodIn struct { 59 | InHeader 60 | Mode uint32 61 | Rdev uint32 62 | Umask uint32 63 | Padding uint32 64 | } 65 | 66 | type ReadIn struct { 67 | InHeader 68 | Fh uint64 69 | Offset uint64 70 | Size uint32 71 | ReadFlags uint32 72 | LockOwner uint64 73 | Flags uint32 74 | Padding uint32 75 | } 76 | 77 | type WriteIn struct { 78 | InHeader 79 | Fh uint64 80 | Offset uint64 81 | Size uint32 82 | WriteFlags uint32 83 | LockOwner uint64 84 | Flags uint32 85 | Padding uint32 86 | } 87 | 88 | type SetXAttrIn struct { 89 | InHeader 90 | Size uint32 91 | Flags uint32 92 | } 93 | 94 | type GetXAttrIn struct { 95 | InHeader 96 | Size uint32 97 | Padding uint32 98 | } 99 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/splice/copy.go: -------------------------------------------------------------------------------- 1 | package splice 2 | 3 | import ( 4 | "io" 5 | "os" 6 | ) 7 | 8 | func SpliceCopy(dst *os.File, src *os.File, p *Pair) (int64, error) { 9 | total := int64(0) 10 | 11 | for { 12 | n, err := p.LoadFrom(src.Fd(), p.size) 13 | if err != nil { 14 | return total, err 15 | } 16 | if n == 0 { 17 | break 18 | } 19 | m, err := p.WriteTo(dst.Fd(), n) 20 | total += int64(m) 21 | if err != nil { 22 | return total, err 23 | } 24 | if m < n { 25 | return total, err 26 | } 27 | if int(n) < p.size { 28 | break 29 | } 30 | } 31 | 32 | return total, nil 33 | } 34 | 35 | // Argument ordering follows io.Copy. 36 | func CopyFile(dstName string, srcName string, mode int) error { 37 | src, err := os.Open(srcName) 38 | if err != nil { 39 | return err 40 | } 41 | defer src.Close() 42 | 43 | dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(mode)) 44 | if err != nil { 45 | return err 46 | } 47 | defer dst.Close() 48 | 49 | return CopyFds(dst, src) 50 | } 51 | 52 | func CopyFds(dst *os.File, src *os.File) (err error) { 53 | p, err := splicePool.get() 54 | if p != nil { 55 | p.Grow(256 * 1024) 56 | _, err := SpliceCopy(dst, src, p) 57 | splicePool.done(p) 58 | return err 59 | } else { 60 | _, err = io.Copy(dst, src) 61 | } 62 | if err == io.EOF { 63 | err = nil 64 | } 65 | return err 66 | } 67 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/splice/pair.go: -------------------------------------------------------------------------------- 1 | package splice 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | type Pair struct { 9 | r, w *os.File 10 | size int 11 | } 12 | 13 | func (p *Pair) MaxGrow() { 14 | for p.Grow(2*p.size) == nil { 15 | } 16 | } 17 | 18 | func (p *Pair) Grow(n int) error { 19 | if n <= p.size { 20 | return nil 21 | } 22 | if !resizable { 23 | return fmt.Errorf("splice: want %d bytes, but not resizable", n) 24 | } 25 | if n > maxPipeSize { 26 | return fmt.Errorf("splice: want %d bytes, max pipe size %d", n, maxPipeSize) 27 | } 28 | 29 | newsize, errNo := fcntl(p.r.Fd(), F_SETPIPE_SZ, n) 30 | if errNo != 0 { 31 | return fmt.Errorf("splice: fcntl returned %v", errNo) 32 | } 33 | p.size = newsize 34 | return nil 35 | } 36 | 37 | func (p *Pair) Cap() int { 38 | return p.size 39 | } 40 | 41 | func (p *Pair) Close() error { 42 | err1 := p.r.Close() 43 | err2 := p.w.Close() 44 | if err1 != nil { 45 | return err1 46 | } 47 | return err2 48 | } 49 | 50 | func (p *Pair) Read(d []byte) (n int, err error) { 51 | return p.r.Read(d) 52 | } 53 | 54 | func (p *Pair) ReadFd() uintptr { 55 | return p.r.Fd() 56 | } 57 | 58 | func (p *Pair) WriteFd() uintptr { 59 | return p.w.Fd() 60 | } 61 | 62 | func (p *Pair) Write(d []byte) (n int, err error) { 63 | return p.w.Write(d) 64 | } 65 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/splice/pair_darwin.go: -------------------------------------------------------------------------------- 1 | package splice 2 | 3 | import () 4 | 5 | func (p *Pair) LoadFromAt(fd uintptr, sz int, off int64) (int, error) { 6 | panic("not implemented") 7 | return 0, nil 8 | } 9 | 10 | func (p *Pair) LoadFrom(fd uintptr, sz int) (int, error) { 11 | panic("not implemented") 12 | return 0, nil 13 | } 14 | 15 | func (p *Pair) WriteTo(fd uintptr, n int) (int, error) { 16 | panic("not implemented") 17 | return 0, nil 18 | } 19 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/splice/pair_linux.go: -------------------------------------------------------------------------------- 1 | package splice 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | ) 8 | 9 | func (p *Pair) LoadFromAt(fd uintptr, sz int, off int64) (int, error) { 10 | n, err := syscall.Splice(int(fd), &off, int(p.w.Fd()), nil, sz, 0) 11 | return int(n), err 12 | } 13 | 14 | func (p *Pair) LoadFrom(fd uintptr, sz int) (int, error) { 15 | if sz > p.size { 16 | return 0, fmt.Errorf("LoadFrom: not enough space %d, %d", 17 | sz, p.size) 18 | } 19 | 20 | n, err := syscall.Splice(int(fd), nil, int(p.w.Fd()), nil, sz, 0) 21 | if err != nil { 22 | err = os.NewSyscallError("Splice load from", err) 23 | } 24 | return int(n), err 25 | } 26 | 27 | func (p *Pair) WriteTo(fd uintptr, n int) (int, error) { 28 | m, err := syscall.Splice(int(p.r.Fd()), nil, int(fd), nil, int(n), 0) 29 | if err != nil { 30 | err = os.NewSyscallError("Splice write", err) 31 | } 32 | return int(m), err 33 | } 34 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/splice/pool.go: -------------------------------------------------------------------------------- 1 | package splice 2 | 3 | import ( 4 | "io" 5 | "sync" 6 | ) 7 | 8 | var splicePool *pairPool 9 | 10 | type pairPool struct { 11 | sync.Mutex 12 | unused []*Pair 13 | usedCount int 14 | } 15 | 16 | func ClearSplicePool() { 17 | splicePool.clear() 18 | } 19 | 20 | func Get() (*Pair, error) { 21 | return splicePool.get() 22 | } 23 | 24 | func Total() int { 25 | return splicePool.total() 26 | } 27 | 28 | func Used() int { 29 | return splicePool.used() 30 | } 31 | 32 | // Return pipe pair to pool 33 | func Done(p *Pair) { 34 | splicePool.done(p) 35 | } 36 | 37 | // Closes and discards pipe pair. 38 | func Drop(p *Pair) { 39 | splicePool.drop(p) 40 | } 41 | 42 | func newSplicePairPool() *pairPool { 43 | return &pairPool{} 44 | } 45 | 46 | func (me *pairPool) clear() { 47 | me.Lock() 48 | for _, p := range me.unused { 49 | p.Close() 50 | } 51 | me.unused = me.unused[:0] 52 | me.Unlock() 53 | } 54 | 55 | func (me *pairPool) used() (n int) { 56 | me.Lock() 57 | n = me.usedCount 58 | me.Unlock() 59 | 60 | return n 61 | } 62 | 63 | func (me *pairPool) total() int { 64 | me.Lock() 65 | n := me.usedCount + len(me.unused) 66 | me.Unlock() 67 | return n 68 | } 69 | 70 | func (me *pairPool) drop(p *Pair) { 71 | p.Close() 72 | me.Lock() 73 | me.usedCount-- 74 | me.Unlock() 75 | } 76 | 77 | func (me *pairPool) get() (p *Pair, err error) { 78 | me.Lock() 79 | defer me.Unlock() 80 | 81 | me.usedCount++ 82 | l := len(me.unused) 83 | if l > 0 { 84 | p := me.unused[l-1] 85 | me.unused = me.unused[:l-1] 86 | return p, nil 87 | } 88 | 89 | return newSplicePair() 90 | } 91 | 92 | var discardBuffer [32 * 1024]byte 93 | 94 | func DiscardAll(r io.Reader) { 95 | buf := discardBuffer[:] 96 | for { 97 | n, _ := r.Read(buf) 98 | if n < len(buf) { 99 | break 100 | } 101 | } 102 | } 103 | 104 | func (me *pairPool) done(p *Pair) { 105 | DiscardAll(p.r) 106 | 107 | me.Lock() 108 | me.usedCount-- 109 | me.unused = append(me.unused, p) 110 | me.Unlock() 111 | } 112 | 113 | func init() { 114 | splicePool = newSplicePairPool() 115 | } 116 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hanwen/go-fuse/splice/splice.go: -------------------------------------------------------------------------------- 1 | package splice 2 | 3 | // Routines for efficient file to file copying. 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "syscall" 11 | ) 12 | 13 | var maxPipeSize int 14 | var resizable bool 15 | 16 | func Resizable() bool { 17 | return resizable 18 | } 19 | 20 | func MaxPipeSize() int { 21 | return maxPipeSize 22 | } 23 | 24 | // From manpage on ubuntu Lucid: 25 | // 26 | // Since Linux 2.6.11, the pipe capacity is 65536 bytes. 27 | const DefaultPipeSize = 16 * 4096 28 | 29 | func init() { 30 | content, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size") 31 | if err != nil { 32 | maxPipeSize = DefaultPipeSize 33 | } else { 34 | fmt.Sscan(string(content), &maxPipeSize) 35 | } 36 | 37 | r, w, err := os.Pipe() 38 | if err != nil { 39 | log.Panicf("cannot create pipe: %v", err) 40 | } 41 | sz, errNo := fcntl(r.Fd(), F_GETPIPE_SZ, 0) 42 | resizable = (errNo == 0) 43 | _, errNo = fcntl(r.Fd(), F_SETPIPE_SZ, 2*sz) 44 | resizable = resizable && (errNo == 0) 45 | r.Close() 46 | w.Close() 47 | } 48 | 49 | // copy & paste from syscall. 50 | func fcntl(fd uintptr, cmd int, arg int) (val int, errno syscall.Errno) { 51 | r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, fd, uintptr(cmd), uintptr(arg)) 52 | val = int(r0) 53 | errno = syscall.Errno(e1) 54 | return 55 | } 56 | 57 | const F_SETPIPE_SZ = 1031 58 | const F_GETPIPE_SZ = 1032 59 | 60 | func newSplicePair() (p *Pair, err error) { 61 | p = &Pair{} 62 | p.r, p.w, err = os.Pipe() 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | errNo := syscall.Errno(0) 68 | for _, f := range []*os.File{p.r, p.w} { 69 | _, errNo = fcntl(f.Fd(), syscall.F_SETFL, syscall.O_NONBLOCK) 70 | if errNo != 0 { 71 | p.Close() 72 | return nil, os.NewSyscallError("fcntl setfl", errNo) 73 | } 74 | } 75 | 76 | p.size, errNo = fcntl(p.r.Fd(), F_GETPIPE_SZ, 0) 77 | if errNo == syscall.EINVAL { 78 | p.size = DefaultPipeSize 79 | return p, nil 80 | } 81 | if errNo != 0 { 82 | p.Close() 83 | return nil, os.NewSyscallError("fcntl getsize", errNo) 84 | } 85 | return p, nil 86 | } 87 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hashicorp/consul/api/README.md: -------------------------------------------------------------------------------- 1 | Consul API client 2 | ================= 3 | 4 | This package provides the `api` package which attempts to 5 | provide programmatic access to the full Consul API. 6 | 7 | Currently, all of the Consul APIs included in version 0.3 are supported. 8 | 9 | Documentation 10 | ============= 11 | 12 | The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/consul/api) 13 | 14 | Usage 15 | ===== 16 | 17 | Below is an example of using the Consul client: 18 | 19 | ```go 20 | // Get a new client, with KV endpoints 21 | client, _ := api.NewClient(api.DefaultConfig()) 22 | kv := client.KV() 23 | 24 | // PUT a new KV pair 25 | p := &api.KVPair{Key: "foo", Value: []byte("test")} 26 | _, err := kv.Put(p, nil) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | // Lookup the pair 32 | pair, _, err := kv.Get("foo", nil) 33 | if err != nil { 34 | panic(err) 35 | } 36 | fmt.Printf("KV: %v", pair) 37 | 38 | ``` 39 | 40 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hashicorp/consul/api/acl.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | const ( 4 | // ACLCLientType is the client type token 5 | ACLClientType = "client" 6 | 7 | // ACLManagementType is the management type token 8 | ACLManagementType = "management" 9 | ) 10 | 11 | // ACLEntry is used to represent an ACL entry 12 | type ACLEntry struct { 13 | CreateIndex uint64 14 | ModifyIndex uint64 15 | ID string 16 | Name string 17 | Type string 18 | Rules string 19 | } 20 | 21 | // ACL can be used to query the ACL endpoints 22 | type ACL struct { 23 | c *Client 24 | } 25 | 26 | // ACL returns a handle to the ACL endpoints 27 | func (c *Client) ACL() *ACL { 28 | return &ACL{c} 29 | } 30 | 31 | // Create is used to generate a new token with the given parameters 32 | func (a *ACL) Create(acl *ACLEntry, q *WriteOptions) (string, *WriteMeta, error) { 33 | r := a.c.newRequest("PUT", "/v1/acl/create") 34 | r.setWriteOptions(q) 35 | r.obj = acl 36 | rtt, resp, err := requireOK(a.c.doRequest(r)) 37 | if err != nil { 38 | return "", nil, err 39 | } 40 | defer resp.Body.Close() 41 | 42 | wm := &WriteMeta{RequestTime: rtt} 43 | var out struct{ ID string } 44 | if err := decodeBody(resp, &out); err != nil { 45 | return "", nil, err 46 | } 47 | return out.ID, wm, nil 48 | } 49 | 50 | // Update is used to update the rules of an existing token 51 | func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) { 52 | r := a.c.newRequest("PUT", "/v1/acl/update") 53 | r.setWriteOptions(q) 54 | r.obj = acl 55 | rtt, resp, err := requireOK(a.c.doRequest(r)) 56 | if err != nil { 57 | return nil, err 58 | } 59 | defer resp.Body.Close() 60 | 61 | wm := &WriteMeta{RequestTime: rtt} 62 | return wm, nil 63 | } 64 | 65 | // Destroy is used to destroy a given ACL token ID 66 | func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { 67 | r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id) 68 | r.setWriteOptions(q) 69 | rtt, resp, err := requireOK(a.c.doRequest(r)) 70 | if err != nil { 71 | return nil, err 72 | } 73 | resp.Body.Close() 74 | 75 | wm := &WriteMeta{RequestTime: rtt} 76 | return wm, nil 77 | } 78 | 79 | // Clone is used to return a new token cloned from an existing one 80 | func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { 81 | r := a.c.newRequest("PUT", "/v1/acl/clone/"+id) 82 | r.setWriteOptions(q) 83 | rtt, resp, err := requireOK(a.c.doRequest(r)) 84 | if err != nil { 85 | return "", nil, err 86 | } 87 | defer resp.Body.Close() 88 | 89 | wm := &WriteMeta{RequestTime: rtt} 90 | var out struct{ ID string } 91 | if err := decodeBody(resp, &out); err != nil { 92 | return "", nil, err 93 | } 94 | return out.ID, wm, nil 95 | } 96 | 97 | // Info is used to query for information about an ACL token 98 | func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) { 99 | r := a.c.newRequest("GET", "/v1/acl/info/"+id) 100 | r.setQueryOptions(q) 101 | rtt, resp, err := requireOK(a.c.doRequest(r)) 102 | if err != nil { 103 | return nil, nil, err 104 | } 105 | defer resp.Body.Close() 106 | 107 | qm := &QueryMeta{} 108 | parseQueryMeta(resp, qm) 109 | qm.RequestTime = rtt 110 | 111 | var entries []*ACLEntry 112 | if err := decodeBody(resp, &entries); err != nil { 113 | return nil, nil, err 114 | } 115 | if len(entries) > 0 { 116 | return entries[0], qm, nil 117 | } 118 | return nil, qm, nil 119 | } 120 | 121 | // List is used to get all the ACL tokens 122 | func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) { 123 | r := a.c.newRequest("GET", "/v1/acl/list") 124 | r.setQueryOptions(q) 125 | rtt, resp, err := requireOK(a.c.doRequest(r)) 126 | if err != nil { 127 | return nil, nil, err 128 | } 129 | defer resp.Body.Close() 130 | 131 | qm := &QueryMeta{} 132 | parseQueryMeta(resp, qm) 133 | qm.RequestTime = rtt 134 | 135 | var entries []*ACLEntry 136 | if err := decodeBody(resp, &entries); err != nil { 137 | return nil, nil, err 138 | } 139 | return entries, qm, nil 140 | } 141 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hashicorp/consul/api/event.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "bytes" 5 | "strconv" 6 | ) 7 | 8 | // Event can be used to query the Event endpoints 9 | type Event struct { 10 | c *Client 11 | } 12 | 13 | // UserEvent represents an event that was fired by the user 14 | type UserEvent struct { 15 | ID string 16 | Name string 17 | Payload []byte 18 | NodeFilter string 19 | ServiceFilter string 20 | TagFilter string 21 | Version int 22 | LTime uint64 23 | } 24 | 25 | // Event returns a handle to the event endpoints 26 | func (c *Client) Event() *Event { 27 | return &Event{c} 28 | } 29 | 30 | // Fire is used to fire a new user event. Only the Name, Payload and Filters 31 | // are respected. This returns the ID or an associated error. Cross DC requests 32 | // are supported. 33 | func (e *Event) Fire(params *UserEvent, q *WriteOptions) (string, *WriteMeta, error) { 34 | r := e.c.newRequest("PUT", "/v1/event/fire/"+params.Name) 35 | r.setWriteOptions(q) 36 | if params.NodeFilter != "" { 37 | r.params.Set("node", params.NodeFilter) 38 | } 39 | if params.ServiceFilter != "" { 40 | r.params.Set("service", params.ServiceFilter) 41 | } 42 | if params.TagFilter != "" { 43 | r.params.Set("tag", params.TagFilter) 44 | } 45 | if params.Payload != nil { 46 | r.body = bytes.NewReader(params.Payload) 47 | } 48 | 49 | rtt, resp, err := requireOK(e.c.doRequest(r)) 50 | if err != nil { 51 | return "", nil, err 52 | } 53 | defer resp.Body.Close() 54 | 55 | wm := &WriteMeta{RequestTime: rtt} 56 | var out UserEvent 57 | if err := decodeBody(resp, &out); err != nil { 58 | return "", nil, err 59 | } 60 | return out.ID, wm, nil 61 | } 62 | 63 | // List is used to get the most recent events an agent has received. 64 | // This list can be optionally filtered by the name. This endpoint supports 65 | // quasi-blocking queries. The index is not monotonic, nor does it provide provide 66 | // LastContact or KnownLeader. 67 | func (e *Event) List(name string, q *QueryOptions) ([]*UserEvent, *QueryMeta, error) { 68 | r := e.c.newRequest("GET", "/v1/event/list") 69 | r.setQueryOptions(q) 70 | if name != "" { 71 | r.params.Set("name", name) 72 | } 73 | rtt, resp, err := requireOK(e.c.doRequest(r)) 74 | if err != nil { 75 | return nil, nil, err 76 | } 77 | defer resp.Body.Close() 78 | 79 | qm := &QueryMeta{} 80 | parseQueryMeta(resp, qm) 81 | qm.RequestTime = rtt 82 | 83 | var entries []*UserEvent 84 | if err := decodeBody(resp, &entries); err != nil { 85 | return nil, nil, err 86 | } 87 | return entries, qm, nil 88 | } 89 | 90 | // IDToIndex is a bit of a hack. This simulates the index generation to 91 | // convert an event ID into a WaitIndex. 92 | func (e *Event) IDToIndex(uuid string) uint64 { 93 | lower := uuid[0:8] + uuid[9:13] + uuid[14:18] 94 | upper := uuid[19:23] + uuid[24:36] 95 | lowVal, err := strconv.ParseUint(lower, 16, 64) 96 | if err != nil { 97 | panic("Failed to convert " + lower) 98 | } 99 | highVal, err := strconv.ParseUint(upper, 16, 64) 100 | if err != nil { 101 | panic("Failed to convert " + upper) 102 | } 103 | return lowVal ^ highVal 104 | } 105 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hashicorp/consul/api/health.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // HealthCheck is used to represent a single check 8 | type HealthCheck struct { 9 | Node string 10 | CheckID string 11 | Name string 12 | Status string 13 | Notes string 14 | Output string 15 | ServiceID string 16 | ServiceName string 17 | } 18 | 19 | // ServiceEntry is used for the health service endpoint 20 | type ServiceEntry struct { 21 | Node *Node 22 | Service *AgentService 23 | Checks []*HealthCheck 24 | } 25 | 26 | // Health can be used to query the Health endpoints 27 | type Health struct { 28 | c *Client 29 | } 30 | 31 | // Health returns a handle to the health endpoints 32 | func (c *Client) Health() *Health { 33 | return &Health{c} 34 | } 35 | 36 | // Node is used to query for checks belonging to a given node 37 | func (h *Health) Node(node string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { 38 | r := h.c.newRequest("GET", "/v1/health/node/"+node) 39 | r.setQueryOptions(q) 40 | rtt, resp, err := requireOK(h.c.doRequest(r)) 41 | if err != nil { 42 | return nil, nil, err 43 | } 44 | defer resp.Body.Close() 45 | 46 | qm := &QueryMeta{} 47 | parseQueryMeta(resp, qm) 48 | qm.RequestTime = rtt 49 | 50 | var out []*HealthCheck 51 | if err := decodeBody(resp, &out); err != nil { 52 | return nil, nil, err 53 | } 54 | return out, qm, nil 55 | } 56 | 57 | // Checks is used to return the checks associated with a service 58 | func (h *Health) Checks(service string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { 59 | r := h.c.newRequest("GET", "/v1/health/checks/"+service) 60 | r.setQueryOptions(q) 61 | rtt, resp, err := requireOK(h.c.doRequest(r)) 62 | if err != nil { 63 | return nil, nil, err 64 | } 65 | defer resp.Body.Close() 66 | 67 | qm := &QueryMeta{} 68 | parseQueryMeta(resp, qm) 69 | qm.RequestTime = rtt 70 | 71 | var out []*HealthCheck 72 | if err := decodeBody(resp, &out); err != nil { 73 | return nil, nil, err 74 | } 75 | return out, qm, nil 76 | } 77 | 78 | // Service is used to query health information along with service info 79 | // for a given service. It can optionally do server-side filtering on a tag 80 | // or nodes with passing health checks only. 81 | func (h *Health) Service(service, tag string, passingOnly bool, q *QueryOptions) ([]*ServiceEntry, *QueryMeta, error) { 82 | r := h.c.newRequest("GET", "/v1/health/service/"+service) 83 | r.setQueryOptions(q) 84 | if tag != "" { 85 | r.params.Set("tag", tag) 86 | } 87 | if passingOnly { 88 | r.params.Set("passing", "1") 89 | } 90 | rtt, resp, err := requireOK(h.c.doRequest(r)) 91 | if err != nil { 92 | return nil, nil, err 93 | } 94 | defer resp.Body.Close() 95 | 96 | qm := &QueryMeta{} 97 | parseQueryMeta(resp, qm) 98 | qm.RequestTime = rtt 99 | 100 | var out []*ServiceEntry 101 | if err := decodeBody(resp, &out); err != nil { 102 | return nil, nil, err 103 | } 104 | return out, qm, nil 105 | } 106 | 107 | // State is used to retrieve all the checks in a given state. 108 | // The wildcard "any" state can also be used for all checks. 109 | func (h *Health) State(state string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { 110 | switch state { 111 | case "any": 112 | case "warning": 113 | case "critical": 114 | case "passing": 115 | case "unknown": 116 | default: 117 | return nil, nil, fmt.Errorf("Unsupported state: %v", state) 118 | } 119 | r := h.c.newRequest("GET", "/v1/health/state/"+state) 120 | r.setQueryOptions(q) 121 | rtt, resp, err := requireOK(h.c.doRequest(r)) 122 | if err != nil { 123 | return nil, nil, err 124 | } 125 | defer resp.Body.Close() 126 | 127 | qm := &QueryMeta{} 128 | parseQueryMeta(resp, qm) 129 | qm.RequestTime = rtt 130 | 131 | var out []*HealthCheck 132 | if err := decodeBody(resp, &out); err != nil { 133 | return nil, nil, err 134 | } 135 | return out, qm, nil 136 | } 137 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hashicorp/consul/api/raw.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // Raw can be used to do raw queries against custom endpoints 4 | type Raw struct { 5 | c *Client 6 | } 7 | 8 | // Raw returns a handle to query endpoints 9 | func (c *Client) Raw() *Raw { 10 | return &Raw{c} 11 | } 12 | 13 | // Query is used to do a GET request against an endpoint 14 | // and deserialize the response into an interface using 15 | // standard Consul conventions. 16 | func (raw *Raw) Query(endpoint string, out interface{}, q *QueryOptions) (*QueryMeta, error) { 17 | return raw.c.query(endpoint, out, q) 18 | } 19 | 20 | // Write is used to do a PUT request against an endpoint 21 | // and serialize/deserialized using the standard Consul conventions. 22 | func (raw *Raw) Write(endpoint string, in, out interface{}, q *WriteOptions) (*WriteMeta, error) { 23 | return raw.c.write(endpoint, in, out, q) 24 | } 25 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/hashicorp/consul/api/status.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // Status can be used to query the Status endpoints 4 | type Status struct { 5 | c *Client 6 | } 7 | 8 | // Status returns a handle to the status endpoints 9 | func (c *Client) Status() *Status { 10 | return &Status{c} 11 | } 12 | 13 | // Leader is used to query for a known leader 14 | func (s *Status) Leader() (string, error) { 15 | r := s.c.newRequest("GET", "/v1/status/leader") 16 | _, resp, err := requireOK(s.c.doRequest(r)) 17 | if err != nil { 18 | return "", err 19 | } 20 | defer resp.Body.Close() 21 | 22 | var leader string 23 | if err := decodeBody(resp, &leader); err != nil { 24 | return "", err 25 | } 26 | return leader, nil 27 | } 28 | 29 | // Peers is used to query for a known raft peers 30 | func (s *Status) Peers() ([]string, error) { 31 | r := s.c.newRequest("GET", "/v1/status/peers") 32 | _, resp, err := requireOK(s.c.doRequest(r)) 33 | if err != nil { 34 | return nil, err 35 | } 36 | defer resp.Body.Close() 37 | 38 | var peers []string 39 | if err := decodeBody(resp, &peers); err != nil { 40 | return nil, err 41 | } 42 | return peers, nil 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/lock.go: -------------------------------------------------------------------------------- 1 | package zk 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | // ErrDeadlock is returned by Lock when trying to lock twice without unlocking first 12 | ErrDeadlock = errors.New("zk: trying to acquire a lock twice") 13 | // ErrNotLocked is returned by Unlock when trying to release a lock that has not first be acquired. 14 | ErrNotLocked = errors.New("zk: not locked") 15 | ) 16 | 17 | // Lock is a mutual exclusion lock. 18 | type Lock struct { 19 | c *Conn 20 | path string 21 | acl []ACL 22 | lockPath string 23 | seq int 24 | } 25 | 26 | // NewLock creates a new lock instance using the provided connection, path, and acl. 27 | // The path must be a node that is only used by this lock. A lock instances starts 28 | // unlocked until Lock() is called. 29 | func NewLock(c *Conn, path string, acl []ACL) *Lock { 30 | return &Lock{ 31 | c: c, 32 | path: path, 33 | acl: acl, 34 | } 35 | } 36 | 37 | func parseSeq(path string) (int, error) { 38 | parts := strings.Split(path, "-") 39 | return strconv.Atoi(parts[len(parts)-1]) 40 | } 41 | 42 | // Lock attempts to acquire the lock. It will wait to return until the lock 43 | // is acquired or an error occurs. If this instance already has the lock 44 | // then ErrDeadlock is returned. 45 | func (l *Lock) Lock() error { 46 | if l.lockPath != "" { 47 | return ErrDeadlock 48 | } 49 | 50 | prefix := fmt.Sprintf("%s/lock-", l.path) 51 | 52 | path := "" 53 | var err error 54 | for i := 0; i < 3; i++ { 55 | path, err = l.c.CreateProtectedEphemeralSequential(prefix, []byte{}, l.acl) 56 | if err == ErrNoNode { 57 | // Create parent node. 58 | parts := strings.Split(l.path, "/") 59 | pth := "" 60 | for _, p := range parts[1:] { 61 | pth += "/" + p 62 | _, err := l.c.Create(pth, []byte{}, 0, l.acl) 63 | if err != nil && err != ErrNodeExists { 64 | return err 65 | } 66 | } 67 | } else if err == nil { 68 | break 69 | } else { 70 | return err 71 | } 72 | } 73 | if err != nil { 74 | return err 75 | } 76 | 77 | seq, err := parseSeq(path) 78 | if err != nil { 79 | return err 80 | } 81 | 82 | for { 83 | children, _, err := l.c.Children(l.path) 84 | if err != nil { 85 | return err 86 | } 87 | 88 | lowestSeq := seq 89 | prevSeq := 0 90 | prevSeqPath := "" 91 | for _, p := range children { 92 | s, err := parseSeq(p) 93 | if err != nil { 94 | return err 95 | } 96 | if s < lowestSeq { 97 | lowestSeq = s 98 | } 99 | if s < seq && s > prevSeq { 100 | prevSeq = s 101 | prevSeqPath = p 102 | } 103 | } 104 | 105 | if seq == lowestSeq { 106 | // Acquired the lock 107 | break 108 | } 109 | 110 | // Wait on the node next in line for the lock 111 | _, _, ch, err := l.c.GetW(l.path + "/" + prevSeqPath) 112 | if err != nil && err != ErrNoNode { 113 | return err 114 | } else if err != nil && err == ErrNoNode { 115 | // try again 116 | continue 117 | } 118 | 119 | ev := <-ch 120 | if ev.Err != nil { 121 | return ev.Err 122 | } 123 | } 124 | 125 | l.seq = seq 126 | l.lockPath = path 127 | return nil 128 | } 129 | 130 | // Unlock releases an acquired lock. If the lock is not currently acquired by 131 | // this Lock instance than ErrNotLocked is returned. 132 | func (l *Lock) Unlock() error { 133 | if l.lockPath == "" { 134 | return ErrNotLocked 135 | } 136 | if err := l.c.Delete(l.lockPath, -1); err != nil { 137 | return err 138 | } 139 | l.lockPath = "" 140 | l.seq = 0 141 | return nil 142 | } 143 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/server_help.go: -------------------------------------------------------------------------------- 1 | package zk 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "math/rand" 8 | "os" 9 | "path/filepath" 10 | "time" 11 | ) 12 | 13 | type TestServer struct { 14 | Port int 15 | Path string 16 | Srv *Server 17 | } 18 | 19 | type TestCluster struct { 20 | Path string 21 | Servers []TestServer 22 | } 23 | 24 | func StartTestCluster(size int, stdout, stderr io.Writer) (*TestCluster, error) { 25 | tmpPath, err := ioutil.TempDir("", "gozk") 26 | if err != nil { 27 | return nil, err 28 | } 29 | success := false 30 | startPort := int(rand.Int31n(6000) + 10000) 31 | cluster := &TestCluster{Path: tmpPath} 32 | defer func() { 33 | if !success { 34 | cluster.Stop() 35 | } 36 | }() 37 | for serverN := 0; serverN < size; serverN++ { 38 | srvPath := filepath.Join(tmpPath, fmt.Sprintf("srv%d", serverN)) 39 | if err := os.Mkdir(srvPath, 0700); err != nil { 40 | return nil, err 41 | } 42 | port := startPort + serverN*3 43 | cfg := ServerConfig{ 44 | ClientPort: port, 45 | DataDir: srvPath, 46 | } 47 | for i := 0; i < size; i++ { 48 | cfg.Servers = append(cfg.Servers, ServerConfigServer{ 49 | ID: i + 1, 50 | Host: "127.0.0.1", 51 | PeerPort: startPort + i*3 + 1, 52 | LeaderElectionPort: startPort + i*3 + 2, 53 | }) 54 | } 55 | cfgPath := filepath.Join(srvPath, "zoo.cfg") 56 | fi, err := os.Create(cfgPath) 57 | if err != nil { 58 | return nil, err 59 | } 60 | err = cfg.Marshall(fi) 61 | fi.Close() 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | fi, err = os.Create(filepath.Join(srvPath, "myid")) 67 | if err != nil { 68 | return nil, err 69 | } 70 | _, err = fmt.Fprintf(fi, "%d\n", serverN+1) 71 | fi.Close() 72 | if err != nil { 73 | return nil, err 74 | } 75 | 76 | srv := &Server{ 77 | ConfigPath: cfgPath, 78 | Stdout: stdout, 79 | Stderr: stderr, 80 | } 81 | if err := srv.Start(); err != nil { 82 | return nil, err 83 | } 84 | cluster.Servers = append(cluster.Servers, TestServer{ 85 | Path: srvPath, 86 | Port: cfg.ClientPort, 87 | Srv: srv, 88 | }) 89 | } 90 | success = true 91 | time.Sleep(time.Second) // Give the server time to become active. Should probably actually attempt to connect to verify. 92 | return cluster, nil 93 | } 94 | 95 | func (ts *TestCluster) Connect(idx int) (*Conn, error) { 96 | zk, _, err := Connect([]string{fmt.Sprintf("127.0.0.1:%d", ts.Servers[idx].Port)}, time.Second*15) 97 | return zk, err 98 | } 99 | 100 | func (ts *TestCluster) ConnectAll() (*Conn, <-chan Event, error) { 101 | return ts.ConnectAllTimeout(time.Second * 15) 102 | } 103 | 104 | func (ts *TestCluster) ConnectAllTimeout(sessionTimeout time.Duration) (*Conn, <-chan Event, error) { 105 | hosts := make([]string, len(ts.Servers)) 106 | for i, srv := range ts.Servers { 107 | hosts[i] = fmt.Sprintf("127.0.0.1:%d", srv.Port) 108 | } 109 | zk, ch, err := Connect(hosts, sessionTimeout) 110 | return zk, ch, err 111 | } 112 | 113 | func (ts *TestCluster) Stop() error { 114 | for _, srv := range ts.Servers { 115 | srv.Srv.Stop() 116 | } 117 | defer os.RemoveAll(ts.Path) 118 | return nil 119 | } 120 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/tracer.go: -------------------------------------------------------------------------------- 1 | package zk 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | "io" 7 | "net" 8 | "sync" 9 | ) 10 | 11 | var ( 12 | requests = make(map[int32]int32) // Map of Xid -> Opcode 13 | requestsLock = &sync.Mutex{} 14 | ) 15 | 16 | func trace(conn1, conn2 net.Conn, client bool) { 17 | defer conn1.Close() 18 | defer conn2.Close() 19 | buf := make([]byte, 10*1024) 20 | init := true 21 | for { 22 | _, err := io.ReadFull(conn1, buf[:4]) 23 | if err != nil { 24 | fmt.Println("1>", client, err) 25 | return 26 | } 27 | 28 | blen := int(binary.BigEndian.Uint32(buf[:4])) 29 | 30 | _, err = io.ReadFull(conn1, buf[4:4+blen]) 31 | if err != nil { 32 | fmt.Println("2>", client, err) 33 | return 34 | } 35 | 36 | var cr interface{} 37 | opcode := int32(-1) 38 | readHeader := true 39 | if client { 40 | if init { 41 | cr = &connectRequest{} 42 | readHeader = false 43 | } else { 44 | xid := int32(binary.BigEndian.Uint32(buf[4:8])) 45 | opcode = int32(binary.BigEndian.Uint32(buf[8:12])) 46 | requestsLock.Lock() 47 | requests[xid] = opcode 48 | requestsLock.Unlock() 49 | cr = requestStructForOp(opcode) 50 | if cr == nil { 51 | fmt.Printf("Unknown opcode %d\n", opcode) 52 | } 53 | } 54 | } else { 55 | if init { 56 | cr = &connectResponse{} 57 | readHeader = false 58 | } else { 59 | xid := int32(binary.BigEndian.Uint32(buf[4:8])) 60 | zxid := int64(binary.BigEndian.Uint64(buf[8:16])) 61 | errnum := int32(binary.BigEndian.Uint32(buf[16:20])) 62 | if xid != -1 || zxid != -1 { 63 | requestsLock.Lock() 64 | found := false 65 | opcode, found = requests[xid] 66 | if !found { 67 | opcode = 0 68 | } 69 | delete(requests, xid) 70 | requestsLock.Unlock() 71 | } else { 72 | opcode = opWatcherEvent 73 | } 74 | cr = responseStructForOp(opcode) 75 | if cr == nil { 76 | fmt.Printf("Unknown opcode %d\n", opcode) 77 | } 78 | if errnum != 0 { 79 | cr = &struct{}{} 80 | } 81 | } 82 | } 83 | opname := "." 84 | if opcode != -1 { 85 | opname = opNames[opcode] 86 | } 87 | if cr == nil { 88 | fmt.Printf("%+v %s %+v\n", client, opname, buf[4:4+blen]) 89 | } else { 90 | n := 4 91 | hdrStr := "" 92 | if readHeader { 93 | var hdr interface{} 94 | if client { 95 | hdr = &requestHeader{} 96 | } else { 97 | hdr = &responseHeader{} 98 | } 99 | if n2, err := decodePacket(buf[n:n+blen], hdr); err != nil { 100 | fmt.Println(err) 101 | } else { 102 | n += n2 103 | } 104 | hdrStr = fmt.Sprintf(" %+v", hdr) 105 | } 106 | if _, err := decodePacket(buf[n:n+blen], cr); err != nil { 107 | fmt.Println(err) 108 | } 109 | fmt.Printf("%+v %s%s %+v\n", client, opname, hdrStr, cr) 110 | } 111 | 112 | init = false 113 | 114 | written, err := conn2.Write(buf[:4+blen]) 115 | if err != nil { 116 | fmt.Println("3>", client, err) 117 | return 118 | } else if written != 4+blen { 119 | fmt.Printf("Written != read: %d != %d\n", written, blen) 120 | return 121 | } 122 | } 123 | } 124 | 125 | func handleConnection(addr string, conn net.Conn) { 126 | zkConn, err := net.Dial("tcp", addr) 127 | if err != nil { 128 | fmt.Println(err) 129 | return 130 | } 131 | go trace(conn, zkConn, true) 132 | trace(zkConn, conn, false) 133 | } 134 | 135 | func StartTracer(listenAddr, serverAddr string) { 136 | ln, err := net.Listen("tcp", listenAddr) 137 | if err != nil { 138 | panic(err) 139 | } 140 | for { 141 | conn, err := ln.Accept() 142 | if err != nil { 143 | fmt.Println(err) 144 | continue 145 | } 146 | go handleConnection(serverAddr, conn) 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/util.go: -------------------------------------------------------------------------------- 1 | package zk 2 | 3 | import ( 4 | "crypto/sha1" 5 | "encoding/base64" 6 | "fmt" 7 | "math/rand" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | // AuthACL produces an ACL list containing a single ACL which uses the 13 | // provided permissions, with the scheme "auth", and ID "", which is used 14 | // by ZooKeeper to represent any authenticated user. 15 | func AuthACL(perms int32) []ACL { 16 | return []ACL{{perms, "auth", ""}} 17 | } 18 | 19 | // WorldACL produces an ACL list containing a single ACL which uses the 20 | // provided permissions, with the scheme "world", and ID "anyone", which 21 | // is used by ZooKeeper to represent any user at all. 22 | func WorldACL(perms int32) []ACL { 23 | return []ACL{{perms, "world", "anyone"}} 24 | } 25 | 26 | func DigestACL(perms int32, user, password string) []ACL { 27 | userPass := []byte(fmt.Sprintf("%s:%s", user, password)) 28 | h := sha1.New() 29 | if n, err := h.Write(userPass); err != nil || n != len(userPass) { 30 | panic("SHA1 failed") 31 | } 32 | digest := base64.StdEncoding.EncodeToString(h.Sum(nil)) 33 | return []ACL{{perms, "digest", fmt.Sprintf("%s:%s", user, digest)}} 34 | } 35 | 36 | // FormatServers takes a slice of addresses, and makes sure they are in a format 37 | // that resembles :. If the server has no port provided, the 38 | // DefaultPort constant is added to the end. 39 | func FormatServers(servers []string) []string { 40 | for i := range servers { 41 | if !strings.Contains(servers[i], ":") { 42 | servers[i] = servers[i] + ":" + strconv.Itoa(DefaultPort) 43 | } 44 | } 45 | return servers 46 | } 47 | 48 | // stringShuffle performs a Fisher-Yates shuffle on a slice of strings 49 | func stringShuffle(s []string) { 50 | for i := len(s) - 1; i > 0; i-- { 51 | j := rand.Intn(i + 1) 52 | s[i], s[j] = s[j], s[i] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /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/ugorji/go/codec/codecgen/z.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const genCodecPath = "github.com/ugorji/go/codec" 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/ugorji/go/codec/gen-dec-array.go.tmpl: -------------------------------------------------------------------------------- 1 | {{var "v"}} := {{ if not isArray}}*{{ end }}{{ .Varname }} 2 | {{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() 3 | 4 | var {{var "c"}} bool 5 | _ = {{var "c"}} 6 | 7 | {{ if not isArray }}if {{var "v"}} == nil { 8 | if {{var "l"}} <= 0 { 9 | {{var "v"}} = make({{ .CTyp }}, 0) 10 | } else { 11 | {{var "v"}} = make({{ .CTyp }}, {{var "l"}}) 12 | } 13 | {{var "c"}} = true 14 | } 15 | {{ end }} 16 | if {{var "l"}} == 0 { {{ if isSlice }} 17 | if len({{var "v"}}) != 0 { 18 | {{var "v"}} = {{var "v"}}[:0] 19 | {{var "c"}} = true 20 | } {{ end }} 21 | } else if {{var "l"}} > 0 { 22 | {{ if isChan }} 23 | for {{var "r"}} := 0; {{var "r"}} < {{var "l"}}; {{var "r"}}++ { 24 | var {{var "t"}} {{ .Typ }} 25 | {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} 26 | {{var "v"}} <- {{var "t"}} 27 | {{ else }} 28 | {{var "n"}} := {{var "l"}} 29 | if {{var "l"}} > cap({{var "v"}}) { 30 | {{ if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "l"}}) 31 | {{var "n"}} = len({{var "v"}}) 32 | {{ else }}{{ if .Immutable }} 33 | {{var "v2"}} := {{var "v"}} 34 | {{var "v"}} = make([]{{ .Typ }}, {{var "l"}}, {{var "l"}}) 35 | if len({{var "v"}}) > 0 { 36 | copy({{var "v"}}, {{var "v2"}}[:cap({{var "v2"}})]) 37 | } 38 | {{ else }}{{var "v"}} = make([]{{ .Typ }}, {{var "l"}}, {{var "l"}}) 39 | {{ end }}{{var "c"}} = true 40 | {{ end }} 41 | } else if {{var "l"}} != len({{var "v"}}) { 42 | {{ if isSlice }}{{var "v"}} = {{var "v"}}[:{{var "l"}}] 43 | {{var "c"}} = true {{ end }} 44 | } 45 | {{var "j"}} := 0 46 | for ; {{var "j"}} < {{var "n"}} ; {{var "j"}}++ { 47 | {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} 48 | } {{ if isArray }} 49 | for ; {{var "j"}} < {{var "l"}} ; {{var "j"}}++ { 50 | z.DecSwallow() 51 | }{{ end }} 52 | {{ end }}{{/* closing if not chan */}} 53 | } else { 54 | for {{var "j"}} := 0; !r.CheckBreak(); {{var "j"}}++ { 55 | if {{var "j"}} >= len({{var "v"}}) { 56 | {{ if isArray }}z.DecArrayCannotExpand(len({{var "v"}}), {{var "j"}}+1) 57 | {{ else if isSlice}}{{var "v"}} = append({{var "v"}}, {{zero}})// var {{var "z"}} {{ .Typ }} 58 | {{var "c"}} = true {{ end }} 59 | } 60 | if {{var "j"}} > 0 { 61 | {{var "h"}}.Sep({{var "j"}}) 62 | } 63 | {{ if isChan}} 64 | var {{var "t"}} {{ .Typ }} 65 | {{ $x := printf "%st%s" .TempVar .Rand }}{{ decLineVar $x }} 66 | {{var "v"}} <- {{var "t"}} 67 | {{ else }} 68 | if {{var "j"}} < len({{var "v"}}) { 69 | {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }} 70 | } else { 71 | z.DecSwallow() 72 | } 73 | {{ end }} 74 | } 75 | {{var "h"}}.End() 76 | } 77 | {{ if not isArray }}if {{var "c"}} { 78 | *{{ .Varname }} = {{var "v"}} 79 | }{{ end }} 80 | 81 | -------------------------------------------------------------------------------- /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/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 MIT 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/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 MIT 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/ugorji/go/codec/prebuild.go: -------------------------------------------------------------------------------- 1 | package codec 2 | 3 | //go:generate bash prebuild.sh 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kvfs 2 | FUSE based filesystem for KV stores 3 | Connects to a supported KV store and maps the structure to a FUSE based filesystem. 4 | 5 | Supports: 6 | - etcd 7 | - zookeeper 8 | - consul 9 | - boltdb 10 | 11 | ### Usage 12 | 13 | ```bash 14 | $ sudo ./kvfs -store consul -addr 1.2.3.4:8500 -addr 1.2.3.5:8500 -to /data 15 | ``` 16 | This command initiates a connection to the consul servers at the specified addresses and mounts the structure to `/data` on your filesystem. 17 | 18 | 19 | ### Build 20 | 21 | ```bash 22 | $ godep get 23 | $ godep go build 24 | ``` 25 | 26 | ## THANKS 27 | https://github.com/docker/libkv 28 | 29 | https://github.com/hanwen/go-fuse 30 | -------------------------------------------------------------------------------- /fs/file.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "strings" 5 | "time" 6 | 7 | "github.com/Sirupsen/logrus" 8 | "github.com/docker/libkv/store" 9 | "github.com/hanwen/go-fuse/fuse" 10 | "github.com/hanwen/go-fuse/fuse/nodefs" 11 | ) 12 | 13 | type file struct { 14 | kvStore store.Store 15 | kv *store.KVPair 16 | nodefs.File 17 | } 18 | 19 | func newFile(s store.Store, kv *store.KVPair) nodefs.File { 20 | return &file{s, kv, nodefs.NewDefaultFile()} 21 | } 22 | 23 | func (f *file) String() string { 24 | return f.kv.Key 25 | } 26 | 27 | func (f *file) Read(buf []byte, offset int64) (fuse.ReadResult, fuse.Status) { 28 | logrus.Debugf("Read: %s", string(f.kv.Value)) 29 | 30 | end := int(offset) + len(buf) 31 | if end > len(f.kv.Value) { 32 | end = len(f.kv.Value) 33 | } 34 | 35 | copy(buf, f.kv.Value[offset:end]) 36 | return fuse.ReadResultData(buf), fuse.OK 37 | } 38 | 39 | func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) { 40 | val := f.kv.Value[:off] 41 | val = append(val, data...) 42 | copy(val[off:], data) 43 | 44 | if err := f.kvStore.Put(f.kv.Key, val, nil); err != nil { 45 | logrus.Error(err) 46 | return uint32(0), fuse.EIO 47 | } 48 | return uint32(len(data)), fuse.OK 49 | } 50 | 51 | func (f *file) GetAttr(out *fuse.Attr) fuse.Status { 52 | logrus.Debugf("FGetAttr %s", f.kv.Key) 53 | now := time.Now() 54 | out.Mtime = uint64(now.Unix()) 55 | out.Mtimensec = uint32(now.UnixNano()) 56 | out.Atime = uint64(now.Unix()) 57 | out.Atimensec = uint32(now.UnixNano()) 58 | out.Ctime = uint64(now.Unix()) 59 | out.Ctimensec = uint32(now.UnixNano()) 60 | 61 | if f.kv == nil || strings.HasSuffix(f.kv.Key, "/") || f.kv.Key == "" { 62 | out.Mode = fuse.S_IFDIR | 0755 63 | return fuse.OK 64 | } 65 | 66 | if len(f.kv.Value) > 0 { 67 | out.Mode = fuse.S_IFREG | 0644 68 | out.Size = uint64(len(f.kv.Value)) 69 | } 70 | return fuse.OK 71 | } 72 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/Sirupsen/logrus" 9 | "github.com/cpuguy83/kvfs/fs" 10 | "github.com/docker/docker/pkg/signal" 11 | "github.com/docker/libkv/store" 12 | "github.com/docker/libkv/store/boltdb" 13 | "github.com/docker/libkv/store/consul" 14 | "github.com/docker/libkv/store/etcd" 15 | "github.com/docker/libkv/store/zookeeper" 16 | ) 17 | 18 | func init() { 19 | consul.Register() 20 | boltdb.Register() 21 | etcd.Register() 22 | zookeeper.Register() 23 | } 24 | 25 | type stringsFlag []string 26 | 27 | func (s *stringsFlag) String() string { 28 | return fmt.Sprintf("%v", *s) 29 | } 30 | 31 | func (s *stringsFlag) Set(val string) error { 32 | *s = append(*s, val) 33 | return nil 34 | } 35 | 36 | func (s *stringsFlag) GetAll() []string { 37 | var out []string 38 | for _, i := range *s { 39 | out = append(out, i) 40 | } 41 | return out 42 | } 43 | 44 | var ( 45 | flAddrs stringsFlag 46 | flMountpoint = flag.String("to", "", "Set the mount point to use") 47 | flStore = flag.String("store", "", "Set the KV store type to use") 48 | flDebug = flag.Bool("debug", false, "enable debug logging") 49 | flRoot = flag.String("root", "", "set the root node for the store") 50 | ) 51 | 52 | func main() { 53 | flag.Var(&flAddrs, "addr", "List of address to KV store") 54 | flag.Parse() 55 | 56 | if len(flAddrs) == 0 { 57 | logrus.Fatal("need at least one addr to connect to kv store") 58 | } 59 | 60 | if *flMountpoint == "" { 61 | logrus.Fatal("invalid mount point, must set the `-to` flag") 62 | } 63 | 64 | if _, err := os.Stat(*flMountpoint); err != nil { 65 | logrus.Fatalf("error with specified mountpoint %s: %v", *flMountpoint, err) 66 | } 67 | 68 | if *flStore == "" { 69 | logrus.Fatal("must specify a valid KV store") 70 | } 71 | 72 | if *flDebug { 73 | logrus.SetLevel(logrus.DebugLevel) 74 | } 75 | 76 | fs, err := fs.NewKVFS(fs.Options{*flStore, flAddrs.GetAll(), *flRoot, store.Config{}}) 77 | if err != nil { 78 | logrus.Fatal(err) 79 | } 80 | 81 | srv, err := fs.NewServer(*flMountpoint) 82 | if err != nil { 83 | logrus.Fatal(err) 84 | } 85 | 86 | signal.Trap(func() { 87 | srv.Unmount() 88 | }) 89 | srv.Serve() 90 | } 91 | --------------------------------------------------------------------------------