├── .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
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
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
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 |
--------------------------------------------------------------------------------