diff --git a/Gopkg.lock b/Gopkg.lock
index 35238780..e4b3d2d0 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -21,6 +21,112 @@
pruneopts = "NUT"
revision = "1ff28809256a84bb6966640ff3d0371af82ccba4"
+[[projects]]
+ branch = "master"
+ digest = "1:707ebe952a8b3d00b343c01536c79c73771d100f63ec6babeaed5c79e2b8a8dd"
+ name = "github.com/beorn7/perks"
+ packages = ["quantile"]
+ pruneopts = "NUT"
+ revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
+
+[[projects]]
+ digest = "1:82d3ecba951974e9842e4f83defa94f7b6feb9b9ec5e07da474bac0954ffbe2e"
+ name = "github.com/codegangsta/negroni"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "c6a59be0ce122566695fbd5e48a77f8f10c8a63a"
+ version = "v1.0.0"
+
+[[projects]]
+ digest = "1:4c7a379d06f493d3cf4301a08667d9b83011a92b1d9defc7ec58a10ade19e796"
+ name = "github.com/coreos/bbolt"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "583e8937c61f1af6513608ccc75c97b6abdf4ff9"
+ version = "v1.3.0"
+
+[[projects]]
+ digest = "1:7a3075921fc5c022e8f02350758dd066ff67ac53c733b44cdd5cf0d4d88c7b2b"
+ name = "github.com/coreos/etcd"
+ packages = [
+ "alarm",
+ "auth",
+ "auth/authpb",
+ "client",
+ "clientv3",
+ "compactor",
+ "discovery",
+ "error",
+ "etcdserver",
+ "etcdserver/api",
+ "etcdserver/api/v2http/httptypes",
+ "etcdserver/api/v3rpc/rpctypes",
+ "etcdserver/etcdserverpb",
+ "etcdserver/membership",
+ "etcdserver/stats",
+ "lease",
+ "lease/leasehttp",
+ "lease/leasepb",
+ "mvcc",
+ "mvcc/backend",
+ "mvcc/mvccpb",
+ "pkg/adt",
+ "pkg/contention",
+ "pkg/cpuutil",
+ "pkg/crc",
+ "pkg/fileutil",
+ "pkg/httputil",
+ "pkg/idutil",
+ "pkg/ioutil",
+ "pkg/logutil",
+ "pkg/netutil",
+ "pkg/pathutil",
+ "pkg/pbutil",
+ "pkg/runtime",
+ "pkg/schedule",
+ "pkg/srv",
+ "pkg/tlsutil",
+ "pkg/transport",
+ "pkg/types",
+ "pkg/wait",
+ "raft",
+ "raft/raftpb",
+ "rafthttp",
+ "snap",
+ "snap/snappb",
+ "store",
+ "version",
+ "wal",
+ "wal/walpb",
+ ]
+ pruneopts = "NUT"
+ revision = "fca8add78a9d926166eb739b8e4a124434025ba3"
+ version = "v3.3.9"
+
+[[projects]]
+ digest = "1:0ef770954bca104ee99b3b6b7f9b240605ac03517d9f98cbc1893daa03f3c038"
+ name = "github.com/coreos/go-semver"
+ packages = ["semver"]
+ pruneopts = "NUT"
+ revision = "8ab6407b697782a06568d4b7f1db25550ec2e4c6"
+ version = "v0.2.0"
+
+[[projects]]
+ digest = "1:e3b55611cb86797357cc1cd2b3d38faf07ae3c4079f04b32e84d497422ab0d60"
+ name = "github.com/coreos/go-systemd"
+ packages = ["journal"]
+ pruneopts = "NUT"
+ revision = "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
+ version = "v17"
+
+[[projects]]
+ digest = "1:22332f13485f13511589dc1f59eb97594e8636d3606b69d172a9a85421ad465d"
+ name = "github.com/coreos/pkg"
+ packages = ["capnslog"]
+ pruneopts = "NUT"
+ revision = "97fdf19511ea361ae1c100dd393cc47f8dcfa1e1"
+ version = "v4"
+
[[projects]]
digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39"
name = "github.com/davecgh/go-spew"
@@ -37,6 +143,17 @@
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
+[[projects]]
+ digest = "1:3cabbabc9e0e4aa7e12b882bdc213f41cf8bd2b2ce2a7b5e0aceaf8a6a78049b"
+ name = "github.com/docker/distribution"
+ packages = [
+ "digest",
+ "reference",
+ ]
+ pruneopts = "NUT"
+ revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
+ version = "v2.6.2"
+
[[projects]]
digest = "1:abfe129dc92b16fbf0cc9d6336096a2823151756f62072a700eb10754141b38e"
name = "github.com/ghodss/yaml"
@@ -53,10 +170,12 @@
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
[[projects]]
- digest = "1:a6afc27b2a73a5506832f3c5a1c19a30772cb69e7bd1ced4639eb36a55db224f"
+ digest = "1:b15cd9015d6ebdedb4e7f415bb9cc8870210081c256dc6c5bae2928d31f6c5ba"
name = "github.com/gogo/protobuf"
packages = [
+ "gogoproto",
"proto",
+ "protoc-gen-gogo/descriptor",
"sortkeys",
]
pruneopts = "NUT"
@@ -89,6 +208,17 @@
pruneopts = "NUT"
revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
+[[projects]]
+ digest = "1:38ec74012390146c45af1f92d46e5382b50531247929ff3a685d2b2be65155ac"
+ name = "github.com/gomodule/redigo"
+ packages = [
+ "internal",
+ "redis",
+ ]
+ pruneopts = "NUT"
+ revision = "9c11da706d9b7902c6da69c592f75637793fe121"
+ version = "v2.0.0"
+
[[projects]]
branch = "master"
digest = "1:245bd4eb633039cd66106a5d340ae826d87f4e36a8602fcc940e14176fd26ea7"
@@ -144,6 +274,22 @@
pruneopts = "NUT"
revision = "19d3956666f33e02b023e9a2299a7d428cd9768a"
+[[projects]]
+ digest = "1:c01767916c59f084bb7c41a7d5877c0f3099b1595cfa066e84ec6ad6b084dd89"
+ name = "github.com/gorilla/context"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42"
+ version = "v1.1.1"
+
+[[projects]]
+ digest = "1:bf5cf1d53d703332e9bd8984c69784645b73a938317bf5ace9aadf20ac49379a"
+ name = "github.com/gorilla/mux"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
+ version = "v1.6.2"
+
[[projects]]
branch = "master"
digest = "1:7fdf3223c7372d1ced0b98bf53457c5e89d89aecbad9a77ba9fcc6e01f9e5621"
@@ -172,6 +318,14 @@
pruneopts = "NUT"
revision = "6633656539c1639d9d78127b7d47c622b5d7b6dc"
+[[projects]]
+ digest = "1:6b1eae4bb93e5ccd23cb09d1e005ecb391316d27701b7a5264f8555a6e2f3d87"
+ name = "github.com/jonboulle/clockwork"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "2eee05ed794112d45db504eb05aa693efd2b8b09"
+ version = "v0.1.0"
+
[[projects]]
digest = "1:0243cffa4a3410f161ee613dfdd903a636d07e838a42d341da95d81f42cd1d41"
name = "github.com/json-iterator/go"
@@ -218,11 +372,11 @@
[[projects]]
branch = "master"
- digest = "1:849fc53918b4658b896a43881305d60afc0d6a51d87c0d5b065afd631415f1d4"
+ digest = "1:4543de04755d2d0e4eeee7bd172ea56d7ebfbca44a598cb9e0c8a4b584a3af22"
name = "github.com/knative/test-infra"
packages = ["."]
pruneopts = "T"
- revision = "51872094d69a5b0266fd92a38978819e20ee70c8"
+ revision = "b5ab6fc2aa925d039b62bf9d8c8af7c4525e52be"
[[projects]]
branch = "master"
@@ -232,6 +386,14 @@
pruneopts = "NUT"
revision = "81af80346b1a01caae0cbc27fd3c1ba5b11e189f"
+[[projects]]
+ digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6"
+ name = "github.com/matttproud/golang_protobuf_extensions"
+ packages = ["pbutil"]
+ pruneopts = "NUT"
+ revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
+ version = "v1.0.1"
+
[[projects]]
digest = "1:2f42fa12d6911c7b7659738758631bec870b7e9b4c6be5444f963cdcfccc191f"
name = "github.com/modern-go/concurrent"
@@ -264,6 +426,50 @@
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
version = "v2.0.1"
+[[projects]]
+ digest = "1:03bca087b180bf24c4f9060775f137775550a0834e18f0bca0520a868679dbd7"
+ name = "github.com/prometheus/client_golang"
+ packages = [
+ "prometheus",
+ "prometheus/promhttp",
+ ]
+ pruneopts = "NUT"
+ revision = "c5b7fccd204277076155f10851dad72b76a49317"
+ version = "v0.8.0"
+
+[[projects]]
+ branch = "master"
+ digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
+ name = "github.com/prometheus/client_model"
+ packages = ["go"]
+ pruneopts = "NUT"
+ revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f"
+
+[[projects]]
+ branch = "master"
+ digest = "1:fad5a35eea6a1a33d6c8f949fbc146f24275ca809ece854248187683f52cc30b"
+ name = "github.com/prometheus/common"
+ packages = [
+ "expfmt",
+ "internal/bitbucket.org/ww/goautoneg",
+ "model",
+ ]
+ pruneopts = "NUT"
+ revision = "c7de2306084e37d54b8be01f3541a8464345e9a5"
+
+[[projects]]
+ branch = "master"
+ digest = "1:6621142cd60b7150ab66f38ff36303ca55843dc5a635c1f9a28f95ecddab72b4"
+ name = "github.com/prometheus/procfs"
+ packages = [
+ ".",
+ "internal/util",
+ "nfs",
+ "xfs",
+ ]
+ pruneopts = "NUT"
+ revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92"
+
[[projects]]
digest = "1:d917313f309bda80d27274d53985bc65651f81a5b66b820749ac7f8ef061fd04"
name = "github.com/sergi/go-diff"
@@ -279,6 +485,38 @@
pruneopts = "NUT"
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
+[[projects]]
+ digest = "1:919fc2a81add8ac4a7a236dceaf3e4c29ba4df96d13c3f2ce13a4d0132ebefb8"
+ name = "github.com/ugorji/go"
+ packages = ["codec"]
+ pruneopts = "NUT"
+ revision = "b4c50a2b199d93b13dc15e78929cfb23bfdf21ab"
+ version = "v1.1.1"
+
+[[projects]]
+ digest = "1:e4ffb3b860a4c71f7805415b4ba1e9a27e04eb9c4c03ddd943e9ff1790eda506"
+ name = "github.com/xiang90/probing"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "07dd2e8dfe18522e9c447ba95f2fe95262f63bb2"
+ version = "0.0.1"
+
+[[projects]]
+ digest = "1:eb8c45554dc0271586e6b4d7dbbb6fc6ad5eccf2b46adde2d1274737609c2596"
+ name = "github.com/xyproto/pinterface"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "05fa0e3080664c781c213d0a890a9d22718f7afb"
+ version = "4.1"
+
+[[projects]]
+ digest = "1:a4017f498e81bc3e8c6c9821b5a65aa3b912d9534bc772a302e5c449f715e805"
+ name = "github.com/xyproto/simpleredis"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "2f4b48d695d6f8dcd63a97c25efe3f41101e84a6"
+ version = "2.4"
+
[[projects]]
digest = "1:0a068b4ef25fbfb5988a1dcad677a91bbd469eb6d169d0d86fdfc3810876948b"
name = "go.opencensus.io"
@@ -329,14 +567,18 @@
version = "v1.8.0"
[[projects]]
- digest = "1:624a05c7c6ed502bf77364cd3d54631383dafc169982fddd8ee77b53c3d9cccf"
+ digest = "1:7d23b292d47779a336067fed1e72c12a92c1254c26ede2906ecb39a70472e7bd"
name = "golang.org/x/crypto"
- packages = ["ssh/terminal"]
+ packages = [
+ "bcrypt",
+ "blowfish",
+ "ssh/terminal",
+ ]
pruneopts = "NUT"
revision = "81e90905daefcd6fd217b62423c0908922eadb30"
[[projects]]
- digest = "1:546efc585d0b3b4ef026faa94ae2d3211c1744d517841a27c83905e18fd0828d"
+ digest = "1:ce8a4c0642d5e3881d1970f39008477671a2a5157d051c36d1618cf6bb669556"
name = "golang.org/x/net"
packages = [
"context",
@@ -344,7 +586,9 @@
"http2",
"http2/hpack",
"idna",
+ "internal/timeseries",
"lex/httplex",
+ "trace",
]
pruneopts = "NUT"
revision = "1c05540f6879653db88113bc4a2b70aec4bd491f"
@@ -428,6 +672,50 @@
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
version = "v1.0.0"
+[[projects]]
+ branch = "master"
+ digest = "1:9cc1d3de11a1b6994eb01fe3cf81db064470d0fd39a37475f53a396aa5e8622c"
+ name = "google.golang.org/genproto"
+ packages = ["googleapis/rpc/status"]
+ pruneopts = "NUT"
+ revision = "5a2fd4cab2d6d4a18e70c34937662526cd0c4bd1"
+
+[[projects]]
+ digest = "1:16b89ca20eda0a2103ea08cbe266bcb04814254dac3d5045b6ed81e4e45bddd5"
+ name = "google.golang.org/grpc"
+ packages = [
+ ".",
+ "balancer",
+ "balancer/base",
+ "balancer/roundrobin",
+ "codes",
+ "connectivity",
+ "credentials",
+ "encoding",
+ "encoding/proto",
+ "grpclog",
+ "health/grpc_health_v1",
+ "internal",
+ "internal/backoff",
+ "internal/channelz",
+ "internal/envconfig",
+ "internal/grpcrand",
+ "internal/transport",
+ "keepalive",
+ "metadata",
+ "naming",
+ "peer",
+ "resolver",
+ "resolver/dns",
+ "resolver/passthrough",
+ "stats",
+ "status",
+ "tap",
+ ]
+ pruneopts = "NUT"
+ revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1"
+ version = "v1.15.0"
+
[[projects]]
digest = "1:ef72505cf098abdd34efeea032103377bec06abb61d8a06f002d5d296a4b1185"
name = "gopkg.in/inf.v0"
@@ -483,6 +771,14 @@
revision = "072894a440bdee3a891dea811fe42902311cd2a3"
version = "kubernetes-1.11.0"
+[[projects]]
+ branch = "master"
+ digest = "1:aff2ac035da399e2ccd6d58a0c484f87a52c82868b652397727c2ce1a3aba7f0"
+ name = "k8s.io/apiextensions-apiserver"
+ packages = ["pkg/features"]
+ pruneopts = "NUT"
+ revision = "d65f4428c04f2d28f924a47d1d2177d0cbf45a16"
+
[[projects]]
digest = "1:4b0d523ee389c762d02febbcfa0734c4530ebe87abe925db18f05422adcb33e8"
name = "k8s.io/apimachinery"
@@ -535,6 +831,17 @@
revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae"
version = "kubernetes-1.11.0"
+[[projects]]
+ branch = "master"
+ digest = "1:0453df4e78d4b7678729cdf747169c341e57039a570b0a0b0c19198c57b6ebef"
+ name = "k8s.io/apiserver"
+ packages = [
+ "pkg/features",
+ "pkg/util/feature",
+ ]
+ pruneopts = "NUT"
+ revision = "67c89284117046b26ecd3776eed2a39289399f15"
+
[[projects]]
digest = "1:cfc8072be6ac85c93c499687f89244d02a157331d20be6012323818675024367"
name = "k8s.io/client-go"
@@ -759,12 +1066,131 @@
pruneopts = "NUT"
revision = "39a7bf85c140f972372c2a0d1ee40adbf0c8bfe1"
+[[projects]]
+ digest = "1:cc9baeaf368ade83006e8e9b9b64d1acb53cf6cc32746875dd332b4af162ab07"
+ name = "k8s.io/kubernetes"
+ packages = [
+ "pkg/api/legacyscheme",
+ "pkg/api/ref",
+ "pkg/apis/admissionregistration",
+ "pkg/apis/admissionregistration/install",
+ "pkg/apis/admissionregistration/v1alpha1",
+ "pkg/apis/admissionregistration/v1beta1",
+ "pkg/apis/apps",
+ "pkg/apis/apps/install",
+ "pkg/apis/apps/v1",
+ "pkg/apis/apps/v1beta1",
+ "pkg/apis/apps/v1beta2",
+ "pkg/apis/authentication",
+ "pkg/apis/authentication/install",
+ "pkg/apis/authentication/v1",
+ "pkg/apis/authentication/v1beta1",
+ "pkg/apis/authorization",
+ "pkg/apis/authorization/install",
+ "pkg/apis/authorization/v1",
+ "pkg/apis/authorization/v1beta1",
+ "pkg/apis/autoscaling",
+ "pkg/apis/autoscaling/install",
+ "pkg/apis/autoscaling/v1",
+ "pkg/apis/autoscaling/v2beta1",
+ "pkg/apis/batch",
+ "pkg/apis/batch/install",
+ "pkg/apis/batch/v1",
+ "pkg/apis/batch/v1beta1",
+ "pkg/apis/batch/v2alpha1",
+ "pkg/apis/certificates",
+ "pkg/apis/certificates/install",
+ "pkg/apis/certificates/v1beta1",
+ "pkg/apis/componentconfig",
+ "pkg/apis/componentconfig/install",
+ "pkg/apis/componentconfig/v1alpha1",
+ "pkg/apis/core",
+ "pkg/apis/core/install",
+ "pkg/apis/core/v1",
+ "pkg/apis/events",
+ "pkg/apis/events/install",
+ "pkg/apis/events/v1beta1",
+ "pkg/apis/extensions",
+ "pkg/apis/extensions/install",
+ "pkg/apis/extensions/v1beta1",
+ "pkg/apis/networking",
+ "pkg/apis/networking/install",
+ "pkg/apis/networking/v1",
+ "pkg/apis/policy",
+ "pkg/apis/policy/install",
+ "pkg/apis/policy/v1beta1",
+ "pkg/apis/rbac",
+ "pkg/apis/rbac/install",
+ "pkg/apis/rbac/v1",
+ "pkg/apis/rbac/v1alpha1",
+ "pkg/apis/rbac/v1beta1",
+ "pkg/apis/scheduling",
+ "pkg/apis/scheduling/install",
+ "pkg/apis/scheduling/v1alpha1",
+ "pkg/apis/scheduling/v1beta1",
+ "pkg/apis/settings",
+ "pkg/apis/settings/install",
+ "pkg/apis/settings/v1alpha1",
+ "pkg/apis/storage",
+ "pkg/apis/storage/install",
+ "pkg/apis/storage/v1",
+ "pkg/apis/storage/v1alpha1",
+ "pkg/apis/storage/v1beta1",
+ "pkg/client/clientset_generated/internalclientset",
+ "pkg/client/clientset_generated/internalclientset/scheme",
+ "pkg/client/clientset_generated/internalclientset/typed/admissionregistration/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/apps/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/batch/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/core/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/events/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/networking/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/policy/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/scheduling/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/settings/internalversion",
+ "pkg/client/clientset_generated/internalclientset/typed/storage/internalversion",
+ "pkg/features",
+ "pkg/kubelet/apis",
+ "pkg/master/ports",
+ "pkg/util/parsers",
+ "pkg/util/pointer",
+ "third_party/forked/etcd221/pkg/fileutil",
+ "third_party/forked/etcd221/wal",
+ ]
+ pruneopts = "NUT"
+ revision = "a4529464e4629c21224b3d52edfe0ea91b072862"
+ version = "v1.11.3"
+
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
+ "github.com/codegangsta/negroni",
+ "github.com/coreos/etcd/clientv3",
+ "github.com/coreos/etcd/etcdserver",
+ "github.com/coreos/etcd/etcdserver/etcdserverpb",
+ "github.com/coreos/etcd/etcdserver/membership",
+ "github.com/coreos/etcd/mvcc/backend",
+ "github.com/coreos/etcd/mvcc/mvccpb",
+ "github.com/coreos/etcd/pkg/pbutil",
+ "github.com/coreos/etcd/pkg/types",
+ "github.com/coreos/etcd/raft/raftpb",
+ "github.com/coreos/etcd/snap",
+ "github.com/coreos/etcd/store",
+ "github.com/coreos/etcd/wal",
+ "github.com/coreos/etcd/wal/walpb",
+ "github.com/coreos/go-semver/semver",
+ "github.com/davecgh/go-spew/spew",
"github.com/go-yaml/yaml",
+ "github.com/gogo/protobuf/proto",
+ "github.com/golang/glog",
"github.com/google/go-cmp/cmp",
+ "github.com/gorilla/mux",
"github.com/knative/caching/pkg/apis/caching",
"github.com/knative/caching/pkg/apis/caching/v1alpha1",
"github.com/knative/caching/pkg/client/clientset/versioned",
@@ -780,8 +1206,15 @@
"github.com/knative/pkg/test",
"github.com/knative/test-infra",
"github.com/mattbaird/jsonpatch",
+ "github.com/prometheus/client_golang/prometheus",
+ "github.com/prometheus/client_golang/prometheus/promhttp",
+ "github.com/prometheus/client_model/go",
+ "github.com/prometheus/common/expfmt",
"github.com/sergi/go-diff/diffmatchpatch",
+ "github.com/spf13/pflag",
+ "github.com/xyproto/simpleredis",
"go.uber.org/zap",
+ "golang.org/x/net/context",
"k8s.io/api/admission/v1beta1",
"k8s.io/api/admissionregistration/v1beta1",
"k8s.io/api/core/v1",
@@ -812,6 +1245,7 @@
"k8s.io/client-go/testing",
"k8s.io/client-go/tools/cache",
"k8s.io/client-go/tools/clientcmd",
+ "k8s.io/client-go/tools/clientcmd/api",
"k8s.io/client-go/tools/record",
"k8s.io/client-go/util/flowcontrol",
"k8s.io/client-go/util/workqueue",
@@ -820,6 +1254,11 @@
"k8s.io/code-generator/cmd/defaulter-gen",
"k8s.io/code-generator/cmd/informer-gen",
"k8s.io/code-generator/cmd/lister-gen",
+ "k8s.io/kubernetes/pkg/api/legacyscheme",
+ "k8s.io/kubernetes/pkg/apis/core",
+ "k8s.io/kubernetes/pkg/apis/core/install",
+ "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset",
+ "k8s.io/kubernetes/third_party/forked/etcd221/wal",
]
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/vendor/github.com/beorn7/perks/LICENSE b/vendor/github.com/beorn7/perks/LICENSE
new file mode 100644
index 00000000..339177be
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/LICENSE
@@ -0,0 +1,20 @@
+Copyright (C) 2013 Blake Mizerany
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go
new file mode 100644
index 00000000..d7d14f8e
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/quantile/stream.go
@@ -0,0 +1,316 @@
+// Package quantile computes approximate quantiles over an unbounded data
+// stream within low memory and CPU bounds.
+//
+// A small amount of accuracy is traded to achieve the above properties.
+//
+// Multiple streams can be merged before calling Query to generate a single set
+// of results. This is meaningful when the streams represent the same type of
+// data. See Merge and Samples.
+//
+// For more detailed information about the algorithm used, see:
+//
+// Effective Computation of Biased Quantiles over Data Streams
+//
+// http://www.cs.rutgers.edu/~muthu/bquant.pdf
+package quantile
+
+import (
+ "math"
+ "sort"
+)
+
+// Sample holds an observed value and meta information for compression. JSON
+// tags have been added for convenience.
+type Sample struct {
+ Value float64 `json:",string"`
+ Width float64 `json:",string"`
+ Delta float64 `json:",string"`
+}
+
+// Samples represents a slice of samples. It implements sort.Interface.
+type Samples []Sample
+
+func (a Samples) Len() int { return len(a) }
+func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value }
+func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type invariant func(s *stream, r float64) float64
+
+// NewLowBiased returns an initialized Stream for low-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the lower ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within (1±Epsilon)*Quantile.
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewLowBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * r
+ }
+ return newStream(ƒ)
+}
+
+// NewHighBiased returns an initialized Stream for high-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the higher ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewHighBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * (s.n - r)
+ }
+ return newStream(ƒ)
+}
+
+// NewTargeted returns an initialized Stream concerned with a particular set of
+// quantile values that are supplied a priori. Knowing these a priori reduces
+// space and computation time. The targets map maps the desired quantiles to
+// their absolute errors, i.e. the true quantile of a value returned by a query
+// is guaranteed to be within (Quantile±Epsilon).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
+func NewTargeted(targetMap map[float64]float64) *Stream {
+ // Convert map to slice to avoid slow iterations on a map.
+ // ƒ is called on the hot path, so converting the map to a slice
+ // beforehand results in significant CPU savings.
+ targets := targetMapToSlice(targetMap)
+
+ ƒ := func(s *stream, r float64) float64 {
+ var m = math.MaxFloat64
+ var f float64
+ for _, t := range targets {
+ if t.quantile*s.n <= r {
+ f = (2 * t.epsilon * r) / t.quantile
+ } else {
+ f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile)
+ }
+ if f < m {
+ m = f
+ }
+ }
+ return m
+ }
+ return newStream(ƒ)
+}
+
+type target struct {
+ quantile float64
+ epsilon float64
+}
+
+func targetMapToSlice(targetMap map[float64]float64) []target {
+ targets := make([]target, 0, len(targetMap))
+
+ for quantile, epsilon := range targetMap {
+ t := target{
+ quantile: quantile,
+ epsilon: epsilon,
+ }
+ targets = append(targets, t)
+ }
+
+ return targets
+}
+
+// Stream computes quantiles for a stream of float64s. It is not thread-safe by
+// design. Take care when using across multiple goroutines.
+type Stream struct {
+ *stream
+ b Samples
+ sorted bool
+}
+
+func newStream(ƒ invariant) *Stream {
+ x := &stream{ƒ: ƒ}
+ return &Stream{x, make(Samples, 0, 500), true}
+}
+
+// Insert inserts v into the stream.
+func (s *Stream) Insert(v float64) {
+ s.insert(Sample{Value: v, Width: 1})
+}
+
+func (s *Stream) insert(sample Sample) {
+ s.b = append(s.b, sample)
+ s.sorted = false
+ if len(s.b) == cap(s.b) {
+ s.flush()
+ }
+}
+
+// Query returns the computed qth percentiles value. If s was created with
+// NewTargeted, and q is not in the set of quantiles provided a priori, Query
+// will return an unspecified result.
+func (s *Stream) Query(q float64) float64 {
+ if !s.flushed() {
+ // Fast path when there hasn't been enough data for a flush;
+ // this also yields better accuracy for small sets of data.
+ l := len(s.b)
+ if l == 0 {
+ return 0
+ }
+ i := int(math.Ceil(float64(l) * q))
+ if i > 0 {
+ i -= 1
+ }
+ s.maybeSort()
+ return s.b[i].Value
+ }
+ s.flush()
+ return s.stream.query(q)
+}
+
+// Merge merges samples into the underlying streams samples. This is handy when
+// merging multiple streams from separate threads, database shards, etc.
+//
+// ATTENTION: This method is broken and does not yield correct results. The
+// underlying algorithm is not capable of merging streams correctly.
+func (s *Stream) Merge(samples Samples) {
+ sort.Sort(samples)
+ s.stream.merge(samples)
+}
+
+// Reset reinitializes and clears the list reusing the samples buffer memory.
+func (s *Stream) Reset() {
+ s.stream.reset()
+ s.b = s.b[:0]
+}
+
+// Samples returns stream samples held by s.
+func (s *Stream) Samples() Samples {
+ if !s.flushed() {
+ return s.b
+ }
+ s.flush()
+ return s.stream.samples()
+}
+
+// Count returns the total number of samples observed in the stream
+// since initialization.
+func (s *Stream) Count() int {
+ return len(s.b) + s.stream.count()
+}
+
+func (s *Stream) flush() {
+ s.maybeSort()
+ s.stream.merge(s.b)
+ s.b = s.b[:0]
+}
+
+func (s *Stream) maybeSort() {
+ if !s.sorted {
+ s.sorted = true
+ sort.Sort(s.b)
+ }
+}
+
+func (s *Stream) flushed() bool {
+ return len(s.stream.l) > 0
+}
+
+type stream struct {
+ n float64
+ l []Sample
+ ƒ invariant
+}
+
+func (s *stream) reset() {
+ s.l = s.l[:0]
+ s.n = 0
+}
+
+func (s *stream) insert(v float64) {
+ s.merge(Samples{{v, 1, 0}})
+}
+
+func (s *stream) merge(samples Samples) {
+ // TODO(beorn7): This tries to merge not only individual samples, but
+ // whole summaries. The paper doesn't mention merging summaries at
+ // all. Unittests show that the merging is inaccurate. Find out how to
+ // do merges properly.
+ var r float64
+ i := 0
+ for _, sample := range samples {
+ for ; i < len(s.l); i++ {
+ c := s.l[i]
+ if c.Value > sample.Value {
+ // Insert at position i.
+ s.l = append(s.l, Sample{})
+ copy(s.l[i+1:], s.l[i:])
+ s.l[i] = Sample{
+ sample.Value,
+ sample.Width,
+ math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1),
+ // TODO(beorn7): How to calculate delta correctly?
+ }
+ i++
+ goto inserted
+ }
+ r += c.Width
+ }
+ s.l = append(s.l, Sample{sample.Value, sample.Width, 0})
+ i++
+ inserted:
+ s.n += sample.Width
+ r += sample.Width
+ }
+ s.compress()
+}
+
+func (s *stream) count() int {
+ return int(s.n)
+}
+
+func (s *stream) query(q float64) float64 {
+ t := math.Ceil(q * s.n)
+ t += math.Ceil(s.ƒ(s, t) / 2)
+ p := s.l[0]
+ var r float64
+ for _, c := range s.l[1:] {
+ r += p.Width
+ if r+c.Width+c.Delta > t {
+ return p.Value
+ }
+ p = c
+ }
+ return p.Value
+}
+
+func (s *stream) compress() {
+ if len(s.l) < 2 {
+ return
+ }
+ x := s.l[len(s.l)-1]
+ xi := len(s.l) - 1
+ r := s.n - 1 - x.Width
+
+ for i := len(s.l) - 2; i >= 0; i-- {
+ c := s.l[i]
+ if c.Width+x.Width+x.Delta <= s.ƒ(s, r) {
+ x.Width += c.Width
+ s.l[xi] = x
+ // Remove element at i.
+ copy(s.l[i:], s.l[i+1:])
+ s.l = s.l[:len(s.l)-1]
+ xi -= 1
+ } else {
+ x = c
+ xi = i
+ }
+ r -= c.Width
+ }
+}
+
+func (s *stream) samples() Samples {
+ samples := make(Samples, len(s.l))
+ copy(samples, s.l)
+ return samples
+}
diff --git a/vendor/github.com/codegangsta/negroni/LICENSE b/vendor/github.com/codegangsta/negroni/LICENSE
new file mode 100644
index 00000000..08b5e20a
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Jeremy Saenz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/codegangsta/negroni/doc.go b/vendor/github.com/codegangsta/negroni/doc.go
new file mode 100644
index 00000000..add1ed9f
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/doc.go
@@ -0,0 +1,25 @@
+// Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers.
+//
+// If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit.
+//
+// For a full guide visit http://github.com/urfave/negroni
+//
+// package main
+//
+// import (
+// "github.com/urfave/negroni"
+// "net/http"
+// "fmt"
+// )
+//
+// func main() {
+// mux := http.NewServeMux()
+// mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+// fmt.Fprintf(w, "Welcome to the home page!")
+// })
+//
+// n := negroni.Classic()
+// n.UseHandler(mux)
+// n.Run(":3000")
+// }
+package negroni
diff --git a/vendor/github.com/codegangsta/negroni/logger.go b/vendor/github.com/codegangsta/negroni/logger.go
new file mode 100644
index 00000000..9c2216ba
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/logger.go
@@ -0,0 +1,78 @@
+package negroni
+
+import (
+ "bytes"
+
+ "log"
+ "net/http"
+ "os"
+ "text/template"
+ "time"
+)
+
+// LoggerEntry is the structure passed to the template.
+type LoggerEntry struct {
+ StartTime string
+ Status int
+ Duration time.Duration
+ Hostname string
+ Method string
+ Path string
+ Request *http.Request
+}
+
+// LoggerDefaultFormat is the format logged used by the default Logger instance.
+var LoggerDefaultFormat = "{{.StartTime}} | {{.Status}} | \t {{.Duration}} | {{.Hostname}} | {{.Method}} {{.Path}}"
+
+// LoggerDefaultDateFormat is the format used for date by the default Logger instance.
+var LoggerDefaultDateFormat = time.RFC3339
+
+// ALogger interface
+type ALogger interface {
+ Println(v ...interface{})
+ Printf(format string, v ...interface{})
+}
+
+// Logger is a middleware handler that logs the request as it goes in and the response as it goes out.
+type Logger struct {
+ // ALogger implements just enough log.Logger interface to be compatible with other implementations
+ ALogger
+ dateFormat string
+ template *template.Template
+}
+
+// NewLogger returns a new Logger instance
+func NewLogger() *Logger {
+ logger := &Logger{ALogger: log.New(os.Stdout, "[negroni] ", 0), dateFormat: LoggerDefaultDateFormat}
+ logger.SetFormat(LoggerDefaultFormat)
+ return logger
+}
+
+func (l *Logger) SetFormat(format string) {
+ l.template = template.Must(template.New("negroni_parser").Parse(format))
+}
+
+func (l *Logger) SetDateFormat(format string) {
+ l.dateFormat = format
+}
+
+func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ start := time.Now()
+
+ next(rw, r)
+
+ res := rw.(ResponseWriter)
+ log := LoggerEntry{
+ StartTime: start.Format(l.dateFormat),
+ Status: res.Status(),
+ Duration: time.Since(start),
+ Hostname: r.Host,
+ Method: r.Method,
+ Path: r.URL.Path,
+ Request: r,
+ }
+
+ buff := &bytes.Buffer{}
+ l.template.Execute(buff, log)
+ l.Println(buff.String())
+}
diff --git a/vendor/github.com/codegangsta/negroni/negroni.go b/vendor/github.com/codegangsta/negroni/negroni.go
new file mode 100644
index 00000000..d1d77820
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/negroni.go
@@ -0,0 +1,169 @@
+package negroni
+
+import (
+ "log"
+ "net/http"
+ "os"
+)
+
+const (
+ // DefaultAddress is used if no other is specified.
+ DefaultAddress = ":8080"
+)
+
+// Handler handler is an interface that objects can implement to be registered to serve as middleware
+// in the Negroni middleware stack.
+// ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc
+// passed in.
+//
+// If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked.
+type Handler interface {
+ ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+}
+
+// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.
+// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.
+type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+
+func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ h(rw, r, next)
+}
+
+type middleware struct {
+ handler Handler
+ next *middleware
+}
+
+func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
+}
+
+// Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni
+// middleware. The next http.HandlerFunc is automatically called after the Handler
+// is executed.
+func Wrap(handler http.Handler) Handler {
+ return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ handler.ServeHTTP(rw, r)
+ next(rw, r)
+ })
+}
+
+// WrapFunc converts a http.HandlerFunc into a negroni.Handler so it can be used as a Negroni
+// middleware. The next http.HandlerFunc is automatically called after the Handler
+// is executed.
+func WrapFunc(handlerFunc http.HandlerFunc) Handler {
+ return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ handlerFunc(rw, r)
+ next(rw, r)
+ })
+}
+
+// Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler.
+// Negroni middleware is evaluated in the order that they are added to the stack using
+// the Use and UseHandler methods.
+type Negroni struct {
+ middleware middleware
+ handlers []Handler
+}
+
+// New returns a new Negroni instance with no middleware preconfigured.
+func New(handlers ...Handler) *Negroni {
+ return &Negroni{
+ handlers: handlers,
+ middleware: build(handlers),
+ }
+}
+
+// With returns a new Negroni instance that is a combination of the negroni
+// receiver's handlers and the provided handlers.
+func (n *Negroni) With(handlers ...Handler) *Negroni {
+ return New(
+ append(n.handlers, handlers...)...,
+ )
+}
+
+// Classic returns a new Negroni instance with the default middleware already
+// in the stack.
+//
+// Recovery - Panic Recovery Middleware
+// Logger - Request/Response Logging
+// Static - Static File Serving
+func Classic() *Negroni {
+ return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public")))
+}
+
+func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ n.middleware.ServeHTTP(NewResponseWriter(rw), r)
+}
+
+// Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
+func (n *Negroni) Use(handler Handler) {
+ if handler == nil {
+ panic("handler cannot be nil")
+ }
+
+ n.handlers = append(n.handlers, handler)
+ n.middleware = build(n.handlers)
+}
+
+// UseFunc adds a Negroni-style handler function onto the middleware stack.
+func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {
+ n.Use(HandlerFunc(handlerFunc))
+}
+
+// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
+func (n *Negroni) UseHandler(handler http.Handler) {
+ n.Use(Wrap(handler))
+}
+
+// UseHandlerFunc adds a http.HandlerFunc-style handler function onto the middleware stack.
+func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) {
+ n.UseHandler(http.HandlerFunc(handlerFunc))
+}
+
+// Run is a convenience function that runs the negroni stack as an HTTP
+// server. The addr string, if provided, takes the same format as http.ListenAndServe.
+// If no address is provided but the PORT environment variable is set, the PORT value is used.
+// If neither is provided, the address' value will equal the DefaultAddress constant.
+func (n *Negroni) Run(addr ...string) {
+ l := log.New(os.Stdout, "[negroni] ", 0)
+ finalAddr := detectAddress(addr...)
+ l.Printf("listening on %s", finalAddr)
+ l.Fatal(http.ListenAndServe(finalAddr, n))
+}
+
+func detectAddress(addr ...string) string {
+ if len(addr) > 0 {
+ return addr[0]
+ }
+ if port := os.Getenv("PORT"); port != "" {
+ return ":" + port
+ }
+ return DefaultAddress
+}
+
+// Returns a list of all the handlers in the current Negroni middleware chain.
+func (n *Negroni) Handlers() []Handler {
+ return n.handlers
+}
+
+func build(handlers []Handler) middleware {
+ var next middleware
+
+ if len(handlers) == 0 {
+ return voidMiddleware()
+ } else if len(handlers) > 1 {
+ next = build(handlers[1:])
+ } else {
+ next = voidMiddleware()
+ }
+
+ return middleware{handlers[0], &next}
+}
+
+func voidMiddleware() middleware {
+ return middleware{
+ HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}),
+ &middleware{},
+ }
+}
diff --git a/vendor/github.com/codegangsta/negroni/recovery.go b/vendor/github.com/codegangsta/negroni/recovery.go
new file mode 100644
index 00000000..c6fc24ef
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/recovery.go
@@ -0,0 +1,194 @@
+package negroni
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "runtime"
+ "runtime/debug"
+ "text/template"
+)
+
+const (
+ panicText = "PANIC: %s\n%s"
+ panicHTML = `
+
PANIC: {{.RecoveredPanic}}
+
+
+Negroni - PANIC
+
+
+
{{.RequestDescription}}
+ Runtime error: {{.RecoveredPanic}}
+
+
+{{ if .Stack }}
+
+
Runtime Stack
+
{{.StackAsString}}
+
+{{ end }}
+
+
+`
+ nilRequestMessage = "Request is nil"
+)
+
+var panicHTMLTemplate = template.Must(template.New("PanicPage").Parse(panicHTML))
+
+// PanicInformation contains all
+// elements for printing stack informations.
+type PanicInformation struct {
+ RecoveredPanic interface{}
+ Stack []byte
+ Request *http.Request
+}
+
+// StackAsString returns a printable version of the stack
+func (p *PanicInformation) StackAsString() string {
+ return string(p.Stack)
+}
+
+// RequestDescription returns a printable description of the url
+func (p *PanicInformation) RequestDescription() string {
+
+ if p.Request == nil {
+ return nilRequestMessage
+ }
+
+ var queryOutput string
+ if p.Request.URL.RawQuery != "" {
+ queryOutput = "?" + p.Request.URL.RawQuery
+ }
+ return fmt.Sprintf("%s %s%s", p.Request.Method, p.Request.URL.Path, queryOutput)
+}
+
+// PanicFormatter is an interface on object can implement
+// to be able to output the stack trace
+type PanicFormatter interface {
+ // FormatPanicError output the stack for a given answer/response.
+ // In case the the middleware should not output the stack trace,
+ // the field `Stack` of the passed `PanicInformation` instance equals `[]byte{}`.
+ FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation)
+}
+
+// TextPanicFormatter output the stack
+// as simple text on os.Stdout. If no `Content-Type` is set,
+// it will output the data as `text/plain; charset=utf-8`.
+// Otherwise, the origin `Content-Type` is kept.
+type TextPanicFormatter struct{}
+
+func (t *TextPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) {
+ if rw.Header().Get("Content-Type") == "" {
+ rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ }
+ fmt.Fprintf(rw, panicText, infos.RecoveredPanic, infos.Stack)
+}
+
+// HTMLPanicFormatter output the stack inside
+// an HTML page. This has been largely inspired by
+// https://github.com/go-martini/martini/pull/156/commits.
+type HTMLPanicFormatter struct{}
+
+func (t *HTMLPanicFormatter) FormatPanicError(rw http.ResponseWriter, r *http.Request, infos *PanicInformation) {
+ if rw.Header().Get("Content-Type") == "" {
+ rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+ }
+ panicHTMLTemplate.Execute(rw, infos)
+}
+
+// Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one.
+type Recovery struct {
+ Logger ALogger
+ PrintStack bool
+ PanicHandlerFunc func(*PanicInformation)
+ StackAll bool
+ StackSize int
+ Formatter PanicFormatter
+
+ // Deprecated: Use PanicHandlerFunc instead to receive panic
+ // error with additional information (see PanicInformation)
+ ErrorHandlerFunc func(interface{})
+}
+
+// NewRecovery returns a new instance of Recovery
+func NewRecovery() *Recovery {
+ return &Recovery{
+ Logger: log.New(os.Stdout, "[negroni] ", 0),
+ PrintStack: true,
+ StackAll: false,
+ StackSize: 1024 * 8,
+ Formatter: &TextPanicFormatter{},
+ }
+}
+
+func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ defer func() {
+ if err := recover(); err != nil {
+ rw.WriteHeader(http.StatusInternalServerError)
+
+ stack := make([]byte, rec.StackSize)
+ stack = stack[:runtime.Stack(stack, rec.StackAll)]
+ infos := &PanicInformation{RecoveredPanic: err, Request: r}
+
+ if rec.PrintStack {
+ infos.Stack = stack
+ }
+ rec.Logger.Printf(panicText, err, stack)
+ rec.Formatter.FormatPanicError(rw, r, infos)
+
+ if rec.ErrorHandlerFunc != nil {
+ func() {
+ defer func() {
+ if err := recover(); err != nil {
+ rec.Logger.Printf("provided ErrorHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack())
+ rec.Logger.Printf("%s\n", debug.Stack())
+ }
+ }()
+ rec.ErrorHandlerFunc(err)
+ }()
+ }
+ if rec.PanicHandlerFunc != nil {
+ func() {
+ defer func() {
+ if err := recover(); err != nil {
+ rec.Logger.Printf("provided PanicHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack())
+ rec.Logger.Printf("%s\n", debug.Stack())
+ }
+ }()
+ rec.PanicHandlerFunc(infos)
+ }()
+ }
+ }
+ }()
+
+ next(rw, r)
+}
diff --git a/vendor/github.com/codegangsta/negroni/response_writer.go b/vendor/github.com/codegangsta/negroni/response_writer.go
new file mode 100644
index 00000000..cc507eb4
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/response_writer.go
@@ -0,0 +1,113 @@
+package negroni
+
+import (
+ "bufio"
+ "fmt"
+ "net"
+ "net/http"
+)
+
+// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
+// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
+// if the functionality calls for it.
+type ResponseWriter interface {
+ http.ResponseWriter
+ http.Flusher
+ // Status returns the status code of the response or 0 if the response has
+ // not been written
+ Status() int
+ // Written returns whether or not the ResponseWriter has been written.
+ Written() bool
+ // Size returns the size of the response body.
+ Size() int
+ // Before allows for a function to be called before the ResponseWriter has been written to. This is
+ // useful for setting headers or any other operations that must happen before a response has been written.
+ Before(func(ResponseWriter))
+}
+
+type beforeFunc func(ResponseWriter)
+
+// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
+func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
+ nrw := &responseWriter{
+ ResponseWriter: rw,
+ }
+
+ if _, ok := rw.(http.CloseNotifier); ok {
+ return &responseWriterCloseNotifer{nrw}
+ }
+
+ return nrw
+}
+
+type responseWriter struct {
+ http.ResponseWriter
+ status int
+ size int
+ beforeFuncs []beforeFunc
+}
+
+func (rw *responseWriter) WriteHeader(s int) {
+ rw.status = s
+ rw.callBefore()
+ rw.ResponseWriter.WriteHeader(s)
+}
+
+func (rw *responseWriter) Write(b []byte) (int, error) {
+ if !rw.Written() {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ rw.WriteHeader(http.StatusOK)
+ }
+ size, err := rw.ResponseWriter.Write(b)
+ rw.size += size
+ return size, err
+}
+
+func (rw *responseWriter) Status() int {
+ return rw.status
+}
+
+func (rw *responseWriter) Size() int {
+ return rw.size
+}
+
+func (rw *responseWriter) Written() bool {
+ return rw.status != 0
+}
+
+func (rw *responseWriter) Before(before func(ResponseWriter)) {
+ rw.beforeFuncs = append(rw.beforeFuncs, before)
+}
+
+func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ hijacker, ok := rw.ResponseWriter.(http.Hijacker)
+ if !ok {
+ return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
+ }
+ return hijacker.Hijack()
+}
+
+func (rw *responseWriter) callBefore() {
+ for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
+ rw.beforeFuncs[i](rw)
+ }
+}
+
+func (rw *responseWriter) Flush() {
+ flusher, ok := rw.ResponseWriter.(http.Flusher)
+ if ok {
+ if !rw.Written() {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ rw.WriteHeader(http.StatusOK)
+ }
+ flusher.Flush()
+ }
+}
+
+type responseWriterCloseNotifer struct {
+ *responseWriter
+}
+
+func (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool {
+ return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
diff --git a/vendor/github.com/codegangsta/negroni/response_writer_pusher.go b/vendor/github.com/codegangsta/negroni/response_writer_pusher.go
new file mode 100644
index 00000000..213cb35f
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/response_writer_pusher.go
@@ -0,0 +1,16 @@
+//+build go1.8
+
+package negroni
+
+import (
+ "fmt"
+ "net/http"
+)
+
+func (rw *responseWriter) Push(target string, opts *http.PushOptions) error {
+ pusher, ok := rw.ResponseWriter.(http.Pusher)
+ if ok {
+ return pusher.Push(target, opts)
+ }
+ return fmt.Errorf("the ResponseWriter doesn't support the Pusher interface")
+}
diff --git a/vendor/github.com/codegangsta/negroni/static.go b/vendor/github.com/codegangsta/negroni/static.go
new file mode 100644
index 00000000..34be967c
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/static.go
@@ -0,0 +1,88 @@
+package negroni
+
+import (
+ "net/http"
+ "path"
+ "strings"
+)
+
+// Static is a middleware handler that serves static files in the given
+// directory/filesystem. If the file does not exist on the filesystem, it
+// passes along to the next middleware in the chain. If you desire "fileserver"
+// type behavior where it returns a 404 for unfound files, you should consider
+// using http.FileServer from the Go stdlib.
+type Static struct {
+ // Dir is the directory to serve static files from
+ Dir http.FileSystem
+ // Prefix is the optional prefix used to serve the static directory content
+ Prefix string
+ // IndexFile defines which file to serve as index if it exists.
+ IndexFile string
+}
+
+// NewStatic returns a new instance of Static
+func NewStatic(directory http.FileSystem) *Static {
+ return &Static{
+ Dir: directory,
+ Prefix: "",
+ IndexFile: "index.html",
+ }
+}
+
+func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ if r.Method != "GET" && r.Method != "HEAD" {
+ next(rw, r)
+ return
+ }
+ file := r.URL.Path
+ // if we have a prefix, filter requests by stripping the prefix
+ if s.Prefix != "" {
+ if !strings.HasPrefix(file, s.Prefix) {
+ next(rw, r)
+ return
+ }
+ file = file[len(s.Prefix):]
+ if file != "" && file[0] != '/' {
+ next(rw, r)
+ return
+ }
+ }
+ f, err := s.Dir.Open(file)
+ if err != nil {
+ // discard the error?
+ next(rw, r)
+ return
+ }
+ defer f.Close()
+
+ fi, err := f.Stat()
+ if err != nil {
+ next(rw, r)
+ return
+ }
+
+ // try to serve index file
+ if fi.IsDir() {
+ // redirect if missing trailing slash
+ if !strings.HasSuffix(r.URL.Path, "/") {
+ http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound)
+ return
+ }
+
+ file = path.Join(file, s.IndexFile)
+ f, err = s.Dir.Open(file)
+ if err != nil {
+ next(rw, r)
+ return
+ }
+ defer f.Close()
+
+ fi, err = f.Stat()
+ if err != nil || fi.IsDir() {
+ next(rw, r)
+ return
+ }
+ }
+
+ http.ServeContent(rw, r, file, fi.ModTime(), f)
+}
diff --git a/vendor/github.com/coreos/bbolt/LICENSE b/vendor/github.com/coreos/bbolt/LICENSE
new file mode 100644
index 00000000..004e77fe
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Ben Johnson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/coreos/bbolt/bolt_386.go b/vendor/github.com/coreos/bbolt/bolt_386.go
new file mode 100644
index 00000000..e659bfb9
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_386.go
@@ -0,0 +1,7 @@
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x7FFFFFFF // 2GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0xFFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_amd64.go b/vendor/github.com/coreos/bbolt/bolt_amd64.go
new file mode 100644
index 00000000..cca6b7eb
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_amd64.go
@@ -0,0 +1,7 @@
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_arm.go b/vendor/github.com/coreos/bbolt/bolt_arm.go
new file mode 100644
index 00000000..e659bfb9
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_arm.go
@@ -0,0 +1,7 @@
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x7FFFFFFF // 2GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0xFFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_arm64.go b/vendor/github.com/coreos/bbolt/bolt_arm64.go
new file mode 100644
index 00000000..6d230935
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_arm64.go
@@ -0,0 +1,9 @@
+// +build arm64
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_linux.go b/vendor/github.com/coreos/bbolt/bolt_linux.go
new file mode 100644
index 00000000..2b676661
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_linux.go
@@ -0,0 +1,10 @@
+package bolt
+
+import (
+ "syscall"
+)
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(db *DB) error {
+ return syscall.Fdatasync(int(db.file.Fd()))
+}
diff --git a/vendor/github.com/coreos/bbolt/bolt_openbsd.go b/vendor/github.com/coreos/bbolt/bolt_openbsd.go
new file mode 100644
index 00000000..7058c3d7
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_openbsd.go
@@ -0,0 +1,27 @@
+package bolt
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+const (
+ msAsync = 1 << iota // perform asynchronous writes
+ msSync // perform synchronous writes
+ msInvalidate // invalidate cached data
+)
+
+func msync(db *DB) error {
+ _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate)
+ if errno != 0 {
+ return errno
+ }
+ return nil
+}
+
+func fdatasync(db *DB) error {
+ if db.data != nil {
+ return msync(db)
+ }
+ return db.file.Sync()
+}
diff --git a/vendor/github.com/coreos/bbolt/bolt_ppc.go b/vendor/github.com/coreos/bbolt/bolt_ppc.go
new file mode 100644
index 00000000..645ddc3e
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_ppc.go
@@ -0,0 +1,9 @@
+// +build ppc
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x7FFFFFFF // 2GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0xFFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_ppc64.go b/vendor/github.com/coreos/bbolt/bolt_ppc64.go
new file mode 100644
index 00000000..2dc6be02
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_ppc64.go
@@ -0,0 +1,9 @@
+// +build ppc64
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_ppc64le.go b/vendor/github.com/coreos/bbolt/bolt_ppc64le.go
new file mode 100644
index 00000000..8351e129
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_ppc64le.go
@@ -0,0 +1,9 @@
+// +build ppc64le
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_s390x.go b/vendor/github.com/coreos/bbolt/bolt_s390x.go
new file mode 100644
index 00000000..f4dd26bb
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_s390x.go
@@ -0,0 +1,9 @@
+// +build s390x
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
diff --git a/vendor/github.com/coreos/bbolt/bolt_unix.go b/vendor/github.com/coreos/bbolt/bolt_unix.go
new file mode 100644
index 00000000..cad62dda
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_unix.go
@@ -0,0 +1,89 @@
+// +build !windows,!plan9,!solaris
+
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ for {
+ // If we're beyond our timeout then return an error.
+ // This can only occur after we've attempted a flock once.
+ if t.IsZero() {
+ t = time.Now()
+ } else if timeout > 0 && time.Since(t) > timeout {
+ return ErrTimeout
+ }
+ flag := syscall.LOCK_SH
+ if exclusive {
+ flag = syscall.LOCK_EX
+ }
+
+ // Otherwise attempt to obtain an exclusive lock.
+ err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB)
+ if err == nil {
+ return nil
+ } else if err != syscall.EWOULDBLOCK {
+ return err
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(db *DB) error {
+ return syscall.Flock(int(db.file.Fd()), syscall.LOCK_UN)
+}
+
+// mmap memory maps a DB's data file.
+func mmap(db *DB, sz int) error {
+ // Map the data file to memory.
+ b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
+ if err != nil {
+ return err
+ }
+
+ // Advise the kernel that the mmap is accessed randomly.
+ if err := madvise(b, syscall.MADV_RANDOM); err != nil {
+ return fmt.Errorf("madvise: %s", err)
+ }
+
+ // Save the original byte slice and convert to a byte array pointer.
+ db.dataref = b
+ db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
+ db.datasz = sz
+ return nil
+}
+
+// munmap unmaps a DB's data file from memory.
+func munmap(db *DB) error {
+ // Ignore the unmap if we have no mapped data.
+ if db.dataref == nil {
+ return nil
+ }
+
+ // Unmap using the original byte slice.
+ err := syscall.Munmap(db.dataref)
+ db.dataref = nil
+ db.data = nil
+ db.datasz = 0
+ return err
+}
+
+// NOTE: This function is copied from stdlib because it is not available on darwin.
+func madvise(b []byte, advice int) (err error) {
+ _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice))
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
diff --git a/vendor/github.com/coreos/bbolt/bolt_unix_solaris.go b/vendor/github.com/coreos/bbolt/bolt_unix_solaris.go
new file mode 100644
index 00000000..307bf2b3
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_unix_solaris.go
@@ -0,0 +1,90 @@
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ for {
+ // If we're beyond our timeout then return an error.
+ // This can only occur after we've attempted a flock once.
+ if t.IsZero() {
+ t = time.Now()
+ } else if timeout > 0 && time.Since(t) > timeout {
+ return ErrTimeout
+ }
+ var lock syscall.Flock_t
+ lock.Start = 0
+ lock.Len = 0
+ lock.Pid = 0
+ lock.Whence = 0
+ lock.Pid = 0
+ if exclusive {
+ lock.Type = syscall.F_WRLCK
+ } else {
+ lock.Type = syscall.F_RDLCK
+ }
+ err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock)
+ if err == nil {
+ return nil
+ } else if err != syscall.EAGAIN {
+ return err
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(db *DB) error {
+ var lock syscall.Flock_t
+ lock.Start = 0
+ lock.Len = 0
+ lock.Type = syscall.F_UNLCK
+ lock.Whence = 0
+ return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock)
+}
+
+// mmap memory maps a DB's data file.
+func mmap(db *DB, sz int) error {
+ // Map the data file to memory.
+ b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
+ if err != nil {
+ return err
+ }
+
+ // Advise the kernel that the mmap is accessed randomly.
+ if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil {
+ return fmt.Errorf("madvise: %s", err)
+ }
+
+ // Save the original byte slice and convert to a byte array pointer.
+ db.dataref = b
+ db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
+ db.datasz = sz
+ return nil
+}
+
+// munmap unmaps a DB's data file from memory.
+func munmap(db *DB) error {
+ // Ignore the unmap if we have no mapped data.
+ if db.dataref == nil {
+ return nil
+ }
+
+ // Unmap using the original byte slice.
+ err := unix.Munmap(db.dataref)
+ db.dataref = nil
+ db.data = nil
+ db.datasz = 0
+ return err
+}
diff --git a/vendor/github.com/coreos/bbolt/bolt_windows.go b/vendor/github.com/coreos/bbolt/bolt_windows.go
new file mode 100644
index 00000000..d538e6af
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bolt_windows.go
@@ -0,0 +1,144 @@
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+// LockFileEx code derived from golang build filemutex_windows.go @ v1.5.1
+var (
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+ procLockFileEx = modkernel32.NewProc("LockFileEx")
+ procUnlockFileEx = modkernel32.NewProc("UnlockFileEx")
+)
+
+const (
+ lockExt = ".lock"
+
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
+ flagLockExclusive = 2
+ flagLockFailImmediately = 1
+
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
+ errLockViolation syscall.Errno = 0x21
+)
+
+func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
+ r, _, err := procLockFileEx.Call(uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)))
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
+ r, _, err := procUnlockFileEx.Call(uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0)
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(db *DB) error {
+ return db.file.Sync()
+}
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
+ // Create a separate lock file on windows because a process
+ // cannot share an exclusive lock on the same file. This is
+ // needed during Tx.WriteTo().
+ f, err := os.OpenFile(db.path+lockExt, os.O_CREATE, mode)
+ if err != nil {
+ return err
+ }
+ db.lockfile = f
+
+ var t time.Time
+ for {
+ // If we're beyond our timeout then return an error.
+ // This can only occur after we've attempted a flock once.
+ if t.IsZero() {
+ t = time.Now()
+ } else if timeout > 0 && time.Since(t) > timeout {
+ return ErrTimeout
+ }
+
+ var flag uint32 = flagLockFailImmediately
+ if exclusive {
+ flag |= flagLockExclusive
+ }
+
+ err := lockFileEx(syscall.Handle(db.lockfile.Fd()), flag, 0, 1, 0, &syscall.Overlapped{})
+ if err == nil {
+ return nil
+ } else if err != errLockViolation {
+ return err
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(db *DB) error {
+ err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{})
+ db.lockfile.Close()
+ os.Remove(db.path+lockExt)
+ return err
+}
+
+// mmap memory maps a DB's data file.
+// Based on: https://github.com/edsrzf/mmap-go
+func mmap(db *DB, sz int) error {
+ if !db.readOnly {
+ // Truncate the database to the size of the mmap.
+ if err := db.file.Truncate(int64(sz)); err != nil {
+ return fmt.Errorf("truncate: %s", err)
+ }
+ }
+
+ // Open a file mapping handle.
+ sizelo := uint32(sz >> 32)
+ sizehi := uint32(sz) & 0xffffffff
+ h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil)
+ if h == 0 {
+ return os.NewSyscallError("CreateFileMapping", errno)
+ }
+
+ // Create the memory map.
+ addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz))
+ if addr == 0 {
+ return os.NewSyscallError("MapViewOfFile", errno)
+ }
+
+ // Close mapping handle.
+ if err := syscall.CloseHandle(syscall.Handle(h)); err != nil {
+ return os.NewSyscallError("CloseHandle", err)
+ }
+
+ // Convert to a byte array.
+ db.data = ((*[maxMapSize]byte)(unsafe.Pointer(addr)))
+ db.datasz = sz
+
+ return nil
+}
+
+// munmap unmaps a pointer from a file.
+// Based on: https://github.com/edsrzf/mmap-go
+func munmap(db *DB) error {
+ if db.data == nil {
+ return nil
+ }
+
+ addr := (uintptr)(unsafe.Pointer(&db.data[0]))
+ if err := syscall.UnmapViewOfFile(addr); err != nil {
+ return os.NewSyscallError("UnmapViewOfFile", err)
+ }
+ return nil
+}
diff --git a/vendor/github.com/coreos/bbolt/boltsync_unix.go b/vendor/github.com/coreos/bbolt/boltsync_unix.go
new file mode 100644
index 00000000..f5044252
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/boltsync_unix.go
@@ -0,0 +1,8 @@
+// +build !windows,!plan9,!linux,!openbsd
+
+package bolt
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(db *DB) error {
+ return db.file.Sync()
+}
diff --git a/vendor/github.com/coreos/bbolt/bucket.go b/vendor/github.com/coreos/bbolt/bucket.go
new file mode 100644
index 00000000..d2f8c524
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/bucket.go
@@ -0,0 +1,748 @@
+package bolt
+
+import (
+ "bytes"
+ "fmt"
+ "unsafe"
+)
+
+const (
+ // MaxKeySize is the maximum length of a key, in bytes.
+ MaxKeySize = 32768
+
+ // MaxValueSize is the maximum length of a value, in bytes.
+ MaxValueSize = (1 << 31) - 2
+)
+
+const (
+ maxUint = ^uint(0)
+ minUint = 0
+ maxInt = int(^uint(0) >> 1)
+ minInt = -maxInt - 1
+)
+
+const bucketHeaderSize = int(unsafe.Sizeof(bucket{}))
+
+const (
+ minFillPercent = 0.1
+ maxFillPercent = 1.0
+)
+
+// DefaultFillPercent is the percentage that split pages are filled.
+// This value can be changed by setting Bucket.FillPercent.
+const DefaultFillPercent = 0.5
+
+// Bucket represents a collection of key/value pairs inside the database.
+type Bucket struct {
+ *bucket
+ tx *Tx // the associated transaction
+ buckets map[string]*Bucket // subbucket cache
+ page *page // inline page reference
+ rootNode *node // materialized node for the root page.
+ nodes map[pgid]*node // node cache
+
+ // Sets the threshold for filling nodes when they split. By default,
+ // the bucket will fill to 50% but it can be useful to increase this
+ // amount if you know that your write workloads are mostly append-only.
+ //
+ // This is non-persisted across transactions so it must be set in every Tx.
+ FillPercent float64
+}
+
+// bucket represents the on-file representation of a bucket.
+// This is stored as the "value" of a bucket key. If the bucket is small enough,
+// then its root page can be stored inline in the "value", after the bucket
+// header. In the case of inline buckets, the "root" will be 0.
+type bucket struct {
+ root pgid // page id of the bucket's root-level page
+ sequence uint64 // monotonically incrementing, used by NextSequence()
+}
+
+// newBucket returns a new bucket associated with a transaction.
+func newBucket(tx *Tx) Bucket {
+ var b = Bucket{tx: tx, FillPercent: DefaultFillPercent}
+ if tx.writable {
+ b.buckets = make(map[string]*Bucket)
+ b.nodes = make(map[pgid]*node)
+ }
+ return b
+}
+
+// Tx returns the tx of the bucket.
+func (b *Bucket) Tx() *Tx {
+ return b.tx
+}
+
+// Root returns the root of the bucket.
+func (b *Bucket) Root() pgid {
+ return b.root
+}
+
+// Writable returns whether the bucket is writable.
+func (b *Bucket) Writable() bool {
+ return b.tx.writable
+}
+
+// Cursor creates a cursor associated with the bucket.
+// The cursor is only valid as long as the transaction is open.
+// Do not use a cursor after the transaction is closed.
+func (b *Bucket) Cursor() *Cursor {
+ // Update transaction statistics.
+ b.tx.stats.CursorCount++
+
+ // Allocate and return a cursor.
+ return &Cursor{
+ bucket: b,
+ stack: make([]elemRef, 0),
+ }
+}
+
+// Bucket retrieves a nested bucket by name.
+// Returns nil if the bucket does not exist.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (b *Bucket) Bucket(name []byte) *Bucket {
+ if b.buckets != nil {
+ if child := b.buckets[string(name)]; child != nil {
+ return child
+ }
+ }
+
+ // Move cursor to key.
+ c := b.Cursor()
+ k, v, flags := c.seek(name)
+
+ // Return nil if the key doesn't exist or it is not a bucket.
+ if !bytes.Equal(name, k) || (flags&bucketLeafFlag) == 0 {
+ return nil
+ }
+
+ // Otherwise create a bucket and cache it.
+ var child = b.openBucket(v)
+ if b.buckets != nil {
+ b.buckets[string(name)] = child
+ }
+
+ return child
+}
+
+// Helper method that re-interprets a sub-bucket value
+// from a parent into a Bucket
+func (b *Bucket) openBucket(value []byte) *Bucket {
+ var child = newBucket(b.tx)
+
+ // If this is a writable transaction then we need to copy the bucket entry.
+ // Read-only transactions can point directly at the mmap entry.
+ if b.tx.writable {
+ child.bucket = &bucket{}
+ *child.bucket = *(*bucket)(unsafe.Pointer(&value[0]))
+ } else {
+ child.bucket = (*bucket)(unsafe.Pointer(&value[0]))
+ }
+
+ // Save a reference to the inline page if the bucket is inline.
+ if child.root == 0 {
+ child.page = (*page)(unsafe.Pointer(&value[bucketHeaderSize]))
+ }
+
+ return &child
+}
+
+// CreateBucket creates a new bucket at the given key and returns the new bucket.
+// Returns an error if the key already exists, if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) {
+ if b.tx.db == nil {
+ return nil, ErrTxClosed
+ } else if !b.tx.writable {
+ return nil, ErrTxNotWritable
+ } else if len(key) == 0 {
+ return nil, ErrBucketNameRequired
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ k, _, flags := c.seek(key)
+
+ // Return an error if there is an existing key.
+ if bytes.Equal(key, k) {
+ if (flags & bucketLeafFlag) != 0 {
+ return nil, ErrBucketExists
+ } else {
+ return nil, ErrIncompatibleValue
+ }
+ }
+
+ // Create empty, inline bucket.
+ var bucket = Bucket{
+ bucket: &bucket{},
+ rootNode: &node{isLeaf: true},
+ FillPercent: DefaultFillPercent,
+ }
+ var value = bucket.write()
+
+ // Insert into node.
+ key = cloneBytes(key)
+ c.node().put(key, key, value, 0, bucketLeafFlag)
+
+ // Since subbuckets are not allowed on inline buckets, we need to
+ // dereference the inline page, if it exists. This will cause the bucket
+ // to be treated as a regular, non-inline bucket for the rest of the tx.
+ b.page = nil
+
+ return b.Bucket(key), nil
+}
+
+// CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it.
+// Returns an error if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) {
+ child, err := b.CreateBucket(key)
+ if err == ErrBucketExists {
+ return b.Bucket(key), nil
+ } else if err != nil {
+ return nil, err
+ }
+ return child, nil
+}
+
+// DeleteBucket deletes a bucket at the given key.
+// Returns an error if the bucket does not exists, or if the key represents a non-bucket value.
+func (b *Bucket) DeleteBucket(key []byte) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return ErrTxNotWritable
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ k, _, flags := c.seek(key)
+
+ // Return an error if bucket doesn't exist or is not a bucket.
+ if !bytes.Equal(key, k) {
+ return ErrBucketNotFound
+ } else if (flags & bucketLeafFlag) == 0 {
+ return ErrIncompatibleValue
+ }
+
+ // Recursively delete all child buckets.
+ child := b.Bucket(key)
+ err := child.ForEach(func(k, v []byte) error {
+ if v == nil {
+ if err := child.DeleteBucket(k); err != nil {
+ return fmt.Errorf("delete bucket: %s", err)
+ }
+ }
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ // Remove cached copy.
+ delete(b.buckets, string(key))
+
+ // Release all bucket pages to freelist.
+ child.nodes = nil
+ child.rootNode = nil
+ child.free()
+
+ // Delete the node if we have a matching key.
+ c.node().del(key)
+
+ return nil
+}
+
+// Get retrieves the value for a key in the bucket.
+// Returns a nil value if the key does not exist or if the key is a nested bucket.
+// The returned value is only valid for the life of the transaction.
+func (b *Bucket) Get(key []byte) []byte {
+ k, v, flags := b.Cursor().seek(key)
+
+ // Return nil if this is a bucket.
+ if (flags & bucketLeafFlag) != 0 {
+ return nil
+ }
+
+ // If our target node isn't the same key as what's passed in then return nil.
+ if !bytes.Equal(key, k) {
+ return nil
+ }
+ return v
+}
+
+// Put sets the value for a key in the bucket.
+// If the key exist then its previous value will be overwritten.
+// Supplied value must remain valid for the life of the transaction.
+// Returns an error if the bucket was created from a read-only transaction, if the key is blank, if the key is too large, or if the value is too large.
+func (b *Bucket) Put(key []byte, value []byte) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return ErrTxNotWritable
+ } else if len(key) == 0 {
+ return ErrKeyRequired
+ } else if len(key) > MaxKeySize {
+ return ErrKeyTooLarge
+ } else if int64(len(value)) > MaxValueSize {
+ return ErrValueTooLarge
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ k, _, flags := c.seek(key)
+
+ // Return an error if there is an existing key with a bucket value.
+ if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 {
+ return ErrIncompatibleValue
+ }
+
+ // Insert into node.
+ key = cloneBytes(key)
+ c.node().put(key, key, value, 0, 0)
+
+ return nil
+}
+
+// Delete removes a key from the bucket.
+// If the key does not exist then nothing is done and a nil error is returned.
+// Returns an error if the bucket was created from a read-only transaction.
+func (b *Bucket) Delete(key []byte) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return ErrTxNotWritable
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ _, _, flags := c.seek(key)
+
+ // Return an error if there is already existing bucket value.
+ if (flags & bucketLeafFlag) != 0 {
+ return ErrIncompatibleValue
+ }
+
+ // Delete the node if we have a matching key.
+ c.node().del(key)
+
+ return nil
+}
+
+// NextSequence returns an autoincrementing integer for the bucket.
+func (b *Bucket) NextSequence() (uint64, error) {
+ if b.tx.db == nil {
+ return 0, ErrTxClosed
+ } else if !b.Writable() {
+ return 0, ErrTxNotWritable
+ }
+
+ // Materialize the root node if it hasn't been already so that the
+ // bucket will be saved during commit.
+ if b.rootNode == nil {
+ _ = b.node(b.root, nil)
+ }
+
+ // Increment and return the sequence.
+ b.bucket.sequence++
+ return b.bucket.sequence, nil
+}
+
+// ForEach executes a function for each key/value pair in a bucket.
+// If the provided function returns an error then the iteration is stopped and
+// the error is returned to the caller. The provided function must not modify
+// the bucket; this will result in undefined behavior.
+func (b *Bucket) ForEach(fn func(k, v []byte) error) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ }
+ c := b.Cursor()
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ if err := fn(k, v); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Stat returns stats on a bucket.
+func (b *Bucket) Stats() BucketStats {
+ var s, subStats BucketStats
+ pageSize := b.tx.db.pageSize
+ s.BucketN += 1
+ if b.root == 0 {
+ s.InlineBucketN += 1
+ }
+ b.forEachPage(func(p *page, depth int) {
+ if (p.flags & leafPageFlag) != 0 {
+ s.KeyN += int(p.count)
+
+ // used totals the used bytes for the page
+ used := pageHeaderSize
+
+ if p.count != 0 {
+ // If page has any elements, add all element headers.
+ used += leafPageElementSize * int(p.count-1)
+
+ // Add all element key, value sizes.
+ // The computation takes advantage of the fact that the position
+ // of the last element's key/value equals to the total of the sizes
+ // of all previous elements' keys and values.
+ // It also includes the last element's header.
+ lastElement := p.leafPageElement(p.count - 1)
+ used += int(lastElement.pos + lastElement.ksize + lastElement.vsize)
+ }
+
+ if b.root == 0 {
+ // For inlined bucket just update the inline stats
+ s.InlineBucketInuse += used
+ } else {
+ // For non-inlined bucket update all the leaf stats
+ s.LeafPageN++
+ s.LeafInuse += used
+ s.LeafOverflowN += int(p.overflow)
+
+ // Collect stats from sub-buckets.
+ // Do that by iterating over all element headers
+ // looking for the ones with the bucketLeafFlag.
+ for i := uint16(0); i < p.count; i++ {
+ e := p.leafPageElement(i)
+ if (e.flags & bucketLeafFlag) != 0 {
+ // For any bucket element, open the element value
+ // and recursively call Stats on the contained bucket.
+ subStats.Add(b.openBucket(e.value()).Stats())
+ }
+ }
+ }
+ } else if (p.flags & branchPageFlag) != 0 {
+ s.BranchPageN++
+ lastElement := p.branchPageElement(p.count - 1)
+
+ // used totals the used bytes for the page
+ // Add header and all element headers.
+ used := pageHeaderSize + (branchPageElementSize * int(p.count-1))
+
+ // Add size of all keys and values.
+ // Again, use the fact that last element's position equals to
+ // the total of key, value sizes of all previous elements.
+ used += int(lastElement.pos + lastElement.ksize)
+ s.BranchInuse += used
+ s.BranchOverflowN += int(p.overflow)
+ }
+
+ // Keep track of maximum page depth.
+ if depth+1 > s.Depth {
+ s.Depth = (depth + 1)
+ }
+ })
+
+ // Alloc stats can be computed from page counts and pageSize.
+ s.BranchAlloc = (s.BranchPageN + s.BranchOverflowN) * pageSize
+ s.LeafAlloc = (s.LeafPageN + s.LeafOverflowN) * pageSize
+
+ // Add the max depth of sub-buckets to get total nested depth.
+ s.Depth += subStats.Depth
+ // Add the stats for all sub-buckets
+ s.Add(subStats)
+ return s
+}
+
+// forEachPage iterates over every page in a bucket, including inline pages.
+func (b *Bucket) forEachPage(fn func(*page, int)) {
+ // If we have an inline page then just use that.
+ if b.page != nil {
+ fn(b.page, 0)
+ return
+ }
+
+ // Otherwise traverse the page hierarchy.
+ b.tx.forEachPage(b.root, 0, fn)
+}
+
+// forEachPageNode iterates over every page (or node) in a bucket.
+// This also includes inline pages.
+func (b *Bucket) forEachPageNode(fn func(*page, *node, int)) {
+ // If we have an inline page or root node then just use that.
+ if b.page != nil {
+ fn(b.page, nil, 0)
+ return
+ }
+ b._forEachPageNode(b.root, 0, fn)
+}
+
+func (b *Bucket) _forEachPageNode(pgid pgid, depth int, fn func(*page, *node, int)) {
+ var p, n = b.pageNode(pgid)
+
+ // Execute function.
+ fn(p, n, depth)
+
+ // Recursively loop over children.
+ if p != nil {
+ if (p.flags & branchPageFlag) != 0 {
+ for i := 0; i < int(p.count); i++ {
+ elem := p.branchPageElement(uint16(i))
+ b._forEachPageNode(elem.pgid, depth+1, fn)
+ }
+ }
+ } else {
+ if !n.isLeaf {
+ for _, inode := range n.inodes {
+ b._forEachPageNode(inode.pgid, depth+1, fn)
+ }
+ }
+ }
+}
+
+// spill writes all the nodes for this bucket to dirty pages.
+func (b *Bucket) spill() error {
+ // Spill all child buckets first.
+ for name, child := range b.buckets {
+ // If the child bucket is small enough and it has no child buckets then
+ // write it inline into the parent bucket's page. Otherwise spill it
+ // like a normal bucket and make the parent value a pointer to the page.
+ var value []byte
+ if child.inlineable() {
+ child.free()
+ value = child.write()
+ } else {
+ if err := child.spill(); err != nil {
+ return err
+ }
+
+ // Update the child bucket header in this bucket.
+ value = make([]byte, unsafe.Sizeof(bucket{}))
+ var bucket = (*bucket)(unsafe.Pointer(&value[0]))
+ *bucket = *child.bucket
+ }
+
+ // Skip writing the bucket if there are no materialized nodes.
+ if child.rootNode == nil {
+ continue
+ }
+
+ // Update parent node.
+ var c = b.Cursor()
+ k, _, flags := c.seek([]byte(name))
+ if !bytes.Equal([]byte(name), k) {
+ panic(fmt.Sprintf("misplaced bucket header: %x -> %x", []byte(name), k))
+ }
+ if flags&bucketLeafFlag == 0 {
+ panic(fmt.Sprintf("unexpected bucket header flag: %x", flags))
+ }
+ c.node().put([]byte(name), []byte(name), value, 0, bucketLeafFlag)
+ }
+
+ // Ignore if there's not a materialized root node.
+ if b.rootNode == nil {
+ return nil
+ }
+
+ // Spill nodes.
+ if err := b.rootNode.spill(); err != nil {
+ return err
+ }
+ b.rootNode = b.rootNode.root()
+
+ // Update the root node for this bucket.
+ if b.rootNode.pgid >= b.tx.meta.pgid {
+ panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", b.rootNode.pgid, b.tx.meta.pgid))
+ }
+ b.root = b.rootNode.pgid
+
+ return nil
+}
+
+// inlineable returns true if a bucket is small enough to be written inline
+// and if it contains no subbuckets. Otherwise returns false.
+func (b *Bucket) inlineable() bool {
+ var n = b.rootNode
+
+ // Bucket must only contain a single leaf node.
+ if n == nil || !n.isLeaf {
+ return false
+ }
+
+ // Bucket is not inlineable if it contains subbuckets or if it goes beyond
+ // our threshold for inline bucket size.
+ var size = pageHeaderSize
+ for _, inode := range n.inodes {
+ size += leafPageElementSize + len(inode.key) + len(inode.value)
+
+ if inode.flags&bucketLeafFlag != 0 {
+ return false
+ } else if size > b.maxInlineBucketSize() {
+ return false
+ }
+ }
+
+ return true
+}
+
+// Returns the maximum total size of a bucket to make it a candidate for inlining.
+func (b *Bucket) maxInlineBucketSize() int {
+ return b.tx.db.pageSize / 4
+}
+
+// write allocates and writes a bucket to a byte slice.
+func (b *Bucket) write() []byte {
+ // Allocate the appropriate size.
+ var n = b.rootNode
+ var value = make([]byte, bucketHeaderSize+n.size())
+
+ // Write a bucket header.
+ var bucket = (*bucket)(unsafe.Pointer(&value[0]))
+ *bucket = *b.bucket
+
+ // Convert byte slice to a fake page and write the root node.
+ var p = (*page)(unsafe.Pointer(&value[bucketHeaderSize]))
+ n.write(p)
+
+ return value
+}
+
+// rebalance attempts to balance all nodes.
+func (b *Bucket) rebalance() {
+ for _, n := range b.nodes {
+ n.rebalance()
+ }
+ for _, child := range b.buckets {
+ child.rebalance()
+ }
+}
+
+// node creates a node from a page and associates it with a given parent.
+func (b *Bucket) node(pgid pgid, parent *node) *node {
+ _assert(b.nodes != nil, "nodes map expected")
+
+ // Retrieve node if it's already been created.
+ if n := b.nodes[pgid]; n != nil {
+ return n
+ }
+
+ // Otherwise create a node and cache it.
+ n := &node{bucket: b, parent: parent}
+ if parent == nil {
+ b.rootNode = n
+ } else {
+ parent.children = append(parent.children, n)
+ }
+
+ // Use the inline page if this is an inline bucket.
+ var p = b.page
+ if p == nil {
+ p = b.tx.page(pgid)
+ }
+
+ // Read the page into the node and cache it.
+ n.read(p)
+ b.nodes[pgid] = n
+
+ // Update statistics.
+ b.tx.stats.NodeCount++
+
+ return n
+}
+
+// free recursively frees all pages in the bucket.
+func (b *Bucket) free() {
+ if b.root == 0 {
+ return
+ }
+
+ var tx = b.tx
+ b.forEachPageNode(func(p *page, n *node, _ int) {
+ if p != nil {
+ tx.db.freelist.free(tx.meta.txid, p)
+ } else {
+ n.free()
+ }
+ })
+ b.root = 0
+}
+
+// dereference removes all references to the old mmap.
+func (b *Bucket) dereference() {
+ if b.rootNode != nil {
+ b.rootNode.root().dereference()
+ }
+
+ for _, child := range b.buckets {
+ child.dereference()
+ }
+}
+
+// pageNode returns the in-memory node, if it exists.
+// Otherwise returns the underlying page.
+func (b *Bucket) pageNode(id pgid) (*page, *node) {
+ // Inline buckets have a fake page embedded in their value so treat them
+ // differently. We'll return the rootNode (if available) or the fake page.
+ if b.root == 0 {
+ if id != 0 {
+ panic(fmt.Sprintf("inline bucket non-zero page access(2): %d != 0", id))
+ }
+ if b.rootNode != nil {
+ return nil, b.rootNode
+ }
+ return b.page, nil
+ }
+
+ // Check the node cache for non-inline buckets.
+ if b.nodes != nil {
+ if n := b.nodes[id]; n != nil {
+ return nil, n
+ }
+ }
+
+ // Finally lookup the page from the transaction if no node is materialized.
+ return b.tx.page(id), nil
+}
+
+// BucketStats records statistics about resources used by a bucket.
+type BucketStats struct {
+ // Page count statistics.
+ BranchPageN int // number of logical branch pages
+ BranchOverflowN int // number of physical branch overflow pages
+ LeafPageN int // number of logical leaf pages
+ LeafOverflowN int // number of physical leaf overflow pages
+
+ // Tree statistics.
+ KeyN int // number of keys/value pairs
+ Depth int // number of levels in B+tree
+
+ // Page size utilization.
+ BranchAlloc int // bytes allocated for physical branch pages
+ BranchInuse int // bytes actually used for branch data
+ LeafAlloc int // bytes allocated for physical leaf pages
+ LeafInuse int // bytes actually used for leaf data
+
+ // Bucket statistics
+ BucketN int // total number of buckets including the top bucket
+ InlineBucketN int // total number on inlined buckets
+ InlineBucketInuse int // bytes used for inlined buckets (also accounted for in LeafInuse)
+}
+
+func (s *BucketStats) Add(other BucketStats) {
+ s.BranchPageN += other.BranchPageN
+ s.BranchOverflowN += other.BranchOverflowN
+ s.LeafPageN += other.LeafPageN
+ s.LeafOverflowN += other.LeafOverflowN
+ s.KeyN += other.KeyN
+ if s.Depth < other.Depth {
+ s.Depth = other.Depth
+ }
+ s.BranchAlloc += other.BranchAlloc
+ s.BranchInuse += other.BranchInuse
+ s.LeafAlloc += other.LeafAlloc
+ s.LeafInuse += other.LeafInuse
+
+ s.BucketN += other.BucketN
+ s.InlineBucketN += other.InlineBucketN
+ s.InlineBucketInuse += other.InlineBucketInuse
+}
+
+// cloneBytes returns a copy of a given slice.
+func cloneBytes(v []byte) []byte {
+ var clone = make([]byte, len(v))
+ copy(clone, v)
+ return clone
+}
diff --git a/vendor/github.com/coreos/bbolt/cursor.go b/vendor/github.com/coreos/bbolt/cursor.go
new file mode 100644
index 00000000..1be9f35e
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/cursor.go
@@ -0,0 +1,400 @@
+package bolt
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+)
+
+// Cursor represents an iterator that can traverse over all key/value pairs in a bucket in sorted order.
+// Cursors see nested buckets with value == nil.
+// Cursors can be obtained from a transaction and are valid as long as the transaction is open.
+//
+// Keys and values returned from the cursor are only valid for the life of the transaction.
+//
+// Changing data while traversing with a cursor may cause it to be invalidated
+// and return unexpected keys and/or values. You must reposition your cursor
+// after mutating data.
+type Cursor struct {
+ bucket *Bucket
+ stack []elemRef
+}
+
+// Bucket returns the bucket that this cursor was created from.
+func (c *Cursor) Bucket() *Bucket {
+ return c.bucket
+}
+
+// First moves the cursor to the first item in the bucket and returns its key and value.
+// If the bucket is empty then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) First() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+ c.stack = c.stack[:0]
+ p, n := c.bucket.pageNode(c.bucket.root)
+ c.stack = append(c.stack, elemRef{page: p, node: n, index: 0})
+ c.first()
+
+ // If we land on an empty page then move to the next value.
+ // https://github.com/boltdb/bolt/issues/450
+ if c.stack[len(c.stack)-1].count() == 0 {
+ c.next()
+ }
+
+ k, v, flags := c.keyValue()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+
+}
+
+// Last moves the cursor to the last item in the bucket and returns its key and value.
+// If the bucket is empty then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Last() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+ c.stack = c.stack[:0]
+ p, n := c.bucket.pageNode(c.bucket.root)
+ ref := elemRef{page: p, node: n}
+ ref.index = ref.count() - 1
+ c.stack = append(c.stack, ref)
+ c.last()
+ k, v, flags := c.keyValue()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Next moves the cursor to the next item in the bucket and returns its key and value.
+// If the cursor is at the end of the bucket then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Next() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+ k, v, flags := c.next()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Prev moves the cursor to the previous item in the bucket and returns its key and value.
+// If the cursor is at the beginning of the bucket then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Prev() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+
+ // Attempt to move back one element until we're successful.
+ // Move up the stack as we hit the beginning of each page in our stack.
+ for i := len(c.stack) - 1; i >= 0; i-- {
+ elem := &c.stack[i]
+ if elem.index > 0 {
+ elem.index--
+ break
+ }
+ c.stack = c.stack[:i]
+ }
+
+ // If we've hit the end then return nil.
+ if len(c.stack) == 0 {
+ return nil, nil
+ }
+
+ // Move down the stack to find the last element of the last leaf under this branch.
+ c.last()
+ k, v, flags := c.keyValue()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Seek moves the cursor to a given key and returns it.
+// If the key does not exist then the next key is used. If no keys
+// follow, a nil key is returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) {
+ k, v, flags := c.seek(seek)
+
+ // If we ended up after the last element of a page then move to the next one.
+ if ref := &c.stack[len(c.stack)-1]; ref.index >= ref.count() {
+ k, v, flags = c.next()
+ }
+
+ if k == nil {
+ return nil, nil
+ } else if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Delete removes the current key/value under the cursor from the bucket.
+// Delete fails if current key/value is a bucket or if the transaction is not writable.
+func (c *Cursor) Delete() error {
+ if c.bucket.tx.db == nil {
+ return ErrTxClosed
+ } else if !c.bucket.Writable() {
+ return ErrTxNotWritable
+ }
+
+ key, _, flags := c.keyValue()
+ // Return an error if current value is a bucket.
+ if (flags & bucketLeafFlag) != 0 {
+ return ErrIncompatibleValue
+ }
+ c.node().del(key)
+
+ return nil
+}
+
+// seek moves the cursor to a given key and returns it.
+// If the key does not exist then the next key is used.
+func (c *Cursor) seek(seek []byte) (key []byte, value []byte, flags uint32) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+
+ // Start from root page/node and traverse to correct page.
+ c.stack = c.stack[:0]
+ c.search(seek, c.bucket.root)
+ ref := &c.stack[len(c.stack)-1]
+
+ // If the cursor is pointing to the end of page/node then return nil.
+ if ref.index >= ref.count() {
+ return nil, nil, 0
+ }
+
+ // If this is a bucket then return a nil value.
+ return c.keyValue()
+}
+
+// first moves the cursor to the first leaf element under the last page in the stack.
+func (c *Cursor) first() {
+ for {
+ // Exit when we hit a leaf page.
+ var ref = &c.stack[len(c.stack)-1]
+ if ref.isLeaf() {
+ break
+ }
+
+ // Keep adding pages pointing to the first element to the stack.
+ var pgid pgid
+ if ref.node != nil {
+ pgid = ref.node.inodes[ref.index].pgid
+ } else {
+ pgid = ref.page.branchPageElement(uint16(ref.index)).pgid
+ }
+ p, n := c.bucket.pageNode(pgid)
+ c.stack = append(c.stack, elemRef{page: p, node: n, index: 0})
+ }
+}
+
+// last moves the cursor to the last leaf element under the last page in the stack.
+func (c *Cursor) last() {
+ for {
+ // Exit when we hit a leaf page.
+ ref := &c.stack[len(c.stack)-1]
+ if ref.isLeaf() {
+ break
+ }
+
+ // Keep adding pages pointing to the last element in the stack.
+ var pgid pgid
+ if ref.node != nil {
+ pgid = ref.node.inodes[ref.index].pgid
+ } else {
+ pgid = ref.page.branchPageElement(uint16(ref.index)).pgid
+ }
+ p, n := c.bucket.pageNode(pgid)
+
+ var nextRef = elemRef{page: p, node: n}
+ nextRef.index = nextRef.count() - 1
+ c.stack = append(c.stack, nextRef)
+ }
+}
+
+// next moves to the next leaf element and returns the key and value.
+// If the cursor is at the last leaf element then it stays there and returns nil.
+func (c *Cursor) next() (key []byte, value []byte, flags uint32) {
+ for {
+ // Attempt to move over one element until we're successful.
+ // Move up the stack as we hit the end of each page in our stack.
+ var i int
+ for i = len(c.stack) - 1; i >= 0; i-- {
+ elem := &c.stack[i]
+ if elem.index < elem.count()-1 {
+ elem.index++
+ break
+ }
+ }
+
+ // If we've hit the root page then stop and return. This will leave the
+ // cursor on the last element of the last page.
+ if i == -1 {
+ return nil, nil, 0
+ }
+
+ // Otherwise start from where we left off in the stack and find the
+ // first element of the first leaf page.
+ c.stack = c.stack[:i+1]
+ c.first()
+
+ // If this is an empty page then restart and move back up the stack.
+ // https://github.com/boltdb/bolt/issues/450
+ if c.stack[len(c.stack)-1].count() == 0 {
+ continue
+ }
+
+ return c.keyValue()
+ }
+}
+
+// search recursively performs a binary search against a given page/node until it finds a given key.
+func (c *Cursor) search(key []byte, pgid pgid) {
+ p, n := c.bucket.pageNode(pgid)
+ if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 {
+ panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags))
+ }
+ e := elemRef{page: p, node: n}
+ c.stack = append(c.stack, e)
+
+ // If we're on a leaf page/node then find the specific node.
+ if e.isLeaf() {
+ c.nsearch(key)
+ return
+ }
+
+ if n != nil {
+ c.searchNode(key, n)
+ return
+ }
+ c.searchPage(key, p)
+}
+
+func (c *Cursor) searchNode(key []byte, n *node) {
+ var exact bool
+ index := sort.Search(len(n.inodes), func(i int) bool {
+ // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
+ // sort.Search() finds the lowest index where f() != -1 but we need the highest index.
+ ret := bytes.Compare(n.inodes[i].key, key)
+ if ret == 0 {
+ exact = true
+ }
+ return ret != -1
+ })
+ if !exact && index > 0 {
+ index--
+ }
+ c.stack[len(c.stack)-1].index = index
+
+ // Recursively search to the next page.
+ c.search(key, n.inodes[index].pgid)
+}
+
+func (c *Cursor) searchPage(key []byte, p *page) {
+ // Binary search for the correct range.
+ inodes := p.branchPageElements()
+
+ var exact bool
+ index := sort.Search(int(p.count), func(i int) bool {
+ // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
+ // sort.Search() finds the lowest index where f() != -1 but we need the highest index.
+ ret := bytes.Compare(inodes[i].key(), key)
+ if ret == 0 {
+ exact = true
+ }
+ return ret != -1
+ })
+ if !exact && index > 0 {
+ index--
+ }
+ c.stack[len(c.stack)-1].index = index
+
+ // Recursively search to the next page.
+ c.search(key, inodes[index].pgid)
+}
+
+// nsearch searches the leaf node on the top of the stack for a key.
+func (c *Cursor) nsearch(key []byte) {
+ e := &c.stack[len(c.stack)-1]
+ p, n := e.page, e.node
+
+ // If we have a node then search its inodes.
+ if n != nil {
+ index := sort.Search(len(n.inodes), func(i int) bool {
+ return bytes.Compare(n.inodes[i].key, key) != -1
+ })
+ e.index = index
+ return
+ }
+
+ // If we have a page then search its leaf elements.
+ inodes := p.leafPageElements()
+ index := sort.Search(int(p.count), func(i int) bool {
+ return bytes.Compare(inodes[i].key(), key) != -1
+ })
+ e.index = index
+}
+
+// keyValue returns the key and value of the current leaf element.
+func (c *Cursor) keyValue() ([]byte, []byte, uint32) {
+ ref := &c.stack[len(c.stack)-1]
+ if ref.count() == 0 || ref.index >= ref.count() {
+ return nil, nil, 0
+ }
+
+ // Retrieve value from node.
+ if ref.node != nil {
+ inode := &ref.node.inodes[ref.index]
+ return inode.key, inode.value, inode.flags
+ }
+
+ // Or retrieve value from page.
+ elem := ref.page.leafPageElement(uint16(ref.index))
+ return elem.key(), elem.value(), elem.flags
+}
+
+// node returns the node that the cursor is currently positioned on.
+func (c *Cursor) node() *node {
+ _assert(len(c.stack) > 0, "accessing a node with a zero-length cursor stack")
+
+ // If the top of the stack is a leaf node then just return it.
+ if ref := &c.stack[len(c.stack)-1]; ref.node != nil && ref.isLeaf() {
+ return ref.node
+ }
+
+ // Start from root and traverse down the hierarchy.
+ var n = c.stack[0].node
+ if n == nil {
+ n = c.bucket.node(c.stack[0].page.id, nil)
+ }
+ for _, ref := range c.stack[:len(c.stack)-1] {
+ _assert(!n.isLeaf, "expected branch node")
+ n = n.childAt(int(ref.index))
+ }
+ _assert(n.isLeaf, "expected leaf node")
+ return n
+}
+
+// elemRef represents a reference to an element on a given page/node.
+type elemRef struct {
+ page *page
+ node *node
+ index int
+}
+
+// isLeaf returns whether the ref is pointing at a leaf page/node.
+func (r *elemRef) isLeaf() bool {
+ if r.node != nil {
+ return r.node.isLeaf
+ }
+ return (r.page.flags & leafPageFlag) != 0
+}
+
+// count returns the number of inodes or page elements.
+func (r *elemRef) count() int {
+ if r.node != nil {
+ return len(r.node.inodes)
+ }
+ return int(r.page.count)
+}
diff --git a/vendor/github.com/coreos/bbolt/db.go b/vendor/github.com/coreos/bbolt/db.go
new file mode 100644
index 00000000..1223493c
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/db.go
@@ -0,0 +1,1036 @@
+package bolt
+
+import (
+ "errors"
+ "fmt"
+ "hash/fnv"
+ "log"
+ "os"
+ "runtime"
+ "runtime/debug"
+ "strings"
+ "sync"
+ "time"
+ "unsafe"
+)
+
+// The largest step that can be taken when remapping the mmap.
+const maxMmapStep = 1 << 30 // 1GB
+
+// The data file format version.
+const version = 2
+
+// Represents a marker value to indicate that a file is a Bolt DB.
+const magic uint32 = 0xED0CDAED
+
+// IgnoreNoSync specifies whether the NoSync field of a DB is ignored when
+// syncing changes to a file. This is required as some operating systems,
+// such as OpenBSD, do not have a unified buffer cache (UBC) and writes
+// must be synchronized using the msync(2) syscall.
+const IgnoreNoSync = runtime.GOOS == "openbsd"
+
+// Default values if not set in a DB instance.
+const (
+ DefaultMaxBatchSize int = 1000
+ DefaultMaxBatchDelay = 10 * time.Millisecond
+ DefaultAllocSize = 16 * 1024 * 1024
+)
+
+// default page size for db is set to the OS page size.
+var defaultPageSize = os.Getpagesize()
+
+// DB represents a collection of buckets persisted to a file on disk.
+// All data access is performed through transactions which can be obtained through the DB.
+// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
+type DB struct {
+ // When enabled, the database will perform a Check() after every commit.
+ // A panic is issued if the database is in an inconsistent state. This
+ // flag has a large performance impact so it should only be used for
+ // debugging purposes.
+ StrictMode bool
+
+ // Setting the NoSync flag will cause the database to skip fsync()
+ // calls after each commit. This can be useful when bulk loading data
+ // into a database and you can restart the bulk load in the event of
+ // a system failure or database corruption. Do not set this flag for
+ // normal use.
+ //
+ // If the package global IgnoreNoSync constant is true, this value is
+ // ignored. See the comment on that constant for more details.
+ //
+ // THIS IS UNSAFE. PLEASE USE WITH CAUTION.
+ NoSync bool
+
+ // When true, skips the truncate call when growing the database.
+ // Setting this to true is only safe on non-ext3/ext4 systems.
+ // Skipping truncation avoids preallocation of hard drive space and
+ // bypasses a truncate() and fsync() syscall on remapping.
+ //
+ // https://github.com/boltdb/bolt/issues/284
+ NoGrowSync bool
+
+ // If you want to read the entire database fast, you can set MmapFlag to
+ // syscall.MAP_POPULATE on Linux 2.6.23+ for sequential read-ahead.
+ MmapFlags int
+
+ // MaxBatchSize is the maximum size of a batch. Default value is
+ // copied from DefaultMaxBatchSize in Open.
+ //
+ // If <=0, disables batching.
+ //
+ // Do not change concurrently with calls to Batch.
+ MaxBatchSize int
+
+ // MaxBatchDelay is the maximum delay before a batch starts.
+ // Default value is copied from DefaultMaxBatchDelay in Open.
+ //
+ // If <=0, effectively disables batching.
+ //
+ // Do not change concurrently with calls to Batch.
+ MaxBatchDelay time.Duration
+
+ // AllocSize is the amount of space allocated when the database
+ // needs to create new pages. This is done to amortize the cost
+ // of truncate() and fsync() when growing the data file.
+ AllocSize int
+
+ path string
+ file *os.File
+ lockfile *os.File // windows only
+ dataref []byte // mmap'ed readonly, write throws SEGV
+ data *[maxMapSize]byte
+ datasz int
+ filesz int // current on disk file size
+ meta0 *meta
+ meta1 *meta
+ pageSize int
+ opened bool
+ rwtx *Tx
+ txs []*Tx
+ freelist *freelist
+ stats Stats
+
+ pagePool sync.Pool
+
+ batchMu sync.Mutex
+ batch *batch
+
+ rwlock sync.Mutex // Allows only one writer at a time.
+ metalock sync.Mutex // Protects meta page access.
+ mmaplock sync.RWMutex // Protects mmap access during remapping.
+ statlock sync.RWMutex // Protects stats access.
+
+ ops struct {
+ writeAt func(b []byte, off int64) (n int, err error)
+ }
+
+ // Read only mode.
+ // When true, Update() and Begin(true) return ErrDatabaseReadOnly immediately.
+ readOnly bool
+}
+
+// Path returns the path to currently open database file.
+func (db *DB) Path() string {
+ return db.path
+}
+
+// GoString returns the Go string representation of the database.
+func (db *DB) GoString() string {
+ return fmt.Sprintf("bolt.DB{path:%q}", db.path)
+}
+
+// String returns the string representation of the database.
+func (db *DB) String() string {
+ return fmt.Sprintf("DB<%q>", db.path)
+}
+
+// Open creates and opens a database at the given path.
+// If the file does not exist then it will be created automatically.
+// Passing in nil options will cause Bolt to open the database with the default options.
+func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
+ var db = &DB{opened: true}
+
+ // Set default options if no options are provided.
+ if options == nil {
+ options = DefaultOptions
+ }
+ db.NoGrowSync = options.NoGrowSync
+ db.MmapFlags = options.MmapFlags
+
+ // Set default values for later DB operations.
+ db.MaxBatchSize = DefaultMaxBatchSize
+ db.MaxBatchDelay = DefaultMaxBatchDelay
+ db.AllocSize = DefaultAllocSize
+
+ flag := os.O_RDWR
+ if options.ReadOnly {
+ flag = os.O_RDONLY
+ db.readOnly = true
+ }
+
+ // Open data file and separate sync handler for metadata writes.
+ db.path = path
+ var err error
+ if db.file, err = os.OpenFile(db.path, flag|os.O_CREATE, mode); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+
+ // Lock file so that other processes using Bolt in read-write mode cannot
+ // use the database at the same time. This would cause corruption since
+ // the two processes would write meta pages and free pages separately.
+ // The database file is locked exclusively (only one process can grab the lock)
+ // if !options.ReadOnly.
+ // The database file is locked using the shared lock (more than one process may
+ // hold a lock at the same time) otherwise (options.ReadOnly is set).
+ if err := flock(db, mode, !db.readOnly, options.Timeout); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+
+ // Default values for test hooks
+ db.ops.writeAt = db.file.WriteAt
+
+ // Initialize the database if it doesn't exist.
+ if info, err := db.file.Stat(); err != nil {
+ return nil, err
+ } else if info.Size() == 0 {
+ // Initialize new files with meta pages.
+ if err := db.init(); err != nil {
+ return nil, err
+ }
+ } else {
+ // Read the first meta page to determine the page size.
+ var buf [0x1000]byte
+ if _, err := db.file.ReadAt(buf[:], 0); err == nil {
+ m := db.pageInBuffer(buf[:], 0).meta()
+ if err := m.validate(); err != nil {
+ // If we can't read the page size, we can assume it's the same
+ // as the OS -- since that's how the page size was chosen in the
+ // first place.
+ //
+ // If the first page is invalid and this OS uses a different
+ // page size than what the database was created with then we
+ // are out of luck and cannot access the database.
+ db.pageSize = os.Getpagesize()
+ } else {
+ db.pageSize = int(m.pageSize)
+ }
+ }
+ }
+
+ // Initialize page pool.
+ db.pagePool = sync.Pool{
+ New: func() interface{} {
+ return make([]byte, db.pageSize)
+ },
+ }
+
+ // Memory map the data file.
+ if err := db.mmap(options.InitialMmapSize); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+
+ // Read in the freelist.
+ db.freelist = newFreelist()
+ db.freelist.read(db.page(db.meta().freelist))
+
+ // Mark the database as opened and return.
+ return db, nil
+}
+
+// mmap opens the underlying memory-mapped file and initializes the meta references.
+// minsz is the minimum size that the new mmap can be.
+func (db *DB) mmap(minsz int) error {
+ db.mmaplock.Lock()
+ defer db.mmaplock.Unlock()
+
+ info, err := db.file.Stat()
+ if err != nil {
+ return fmt.Errorf("mmap stat error: %s", err)
+ } else if int(info.Size()) < db.pageSize*2 {
+ return fmt.Errorf("file size too small")
+ }
+
+ // Ensure the size is at least the minimum size.
+ var size = int(info.Size())
+ if size < minsz {
+ size = minsz
+ }
+ size, err = db.mmapSize(size)
+ if err != nil {
+ return err
+ }
+
+ // Dereference all mmap references before unmapping.
+ if db.rwtx != nil {
+ db.rwtx.root.dereference()
+ }
+
+ // Unmap existing data before continuing.
+ if err := db.munmap(); err != nil {
+ return err
+ }
+
+ // Memory-map the data file as a byte slice.
+ if err := mmap(db, size); err != nil {
+ return err
+ }
+
+ // Save references to the meta pages.
+ db.meta0 = db.page(0).meta()
+ db.meta1 = db.page(1).meta()
+
+ // Validate the meta pages. We only return an error if both meta pages fail
+ // validation, since meta0 failing validation means that it wasn't saved
+ // properly -- but we can recover using meta1. And vice-versa.
+ err0 := db.meta0.validate()
+ err1 := db.meta1.validate()
+ if err0 != nil && err1 != nil {
+ return err0
+ }
+
+ return nil
+}
+
+// munmap unmaps the data file from memory.
+func (db *DB) munmap() error {
+ if err := munmap(db); err != nil {
+ return fmt.Errorf("unmap error: " + err.Error())
+ }
+ return nil
+}
+
+// mmapSize determines the appropriate size for the mmap given the current size
+// of the database. The minimum size is 32KB and doubles until it reaches 1GB.
+// Returns an error if the new mmap size is greater than the max allowed.
+func (db *DB) mmapSize(size int) (int, error) {
+ // Double the size from 32KB until 1GB.
+ for i := uint(15); i <= 30; i++ {
+ if size <= 1< maxMapSize {
+ return 0, fmt.Errorf("mmap too large")
+ }
+
+ // If larger than 1GB then grow by 1GB at a time.
+ sz := int64(size)
+ if remainder := sz % int64(maxMmapStep); remainder > 0 {
+ sz += int64(maxMmapStep) - remainder
+ }
+
+ // Ensure that the mmap size is a multiple of the page size.
+ // This should always be true since we're incrementing in MBs.
+ pageSize := int64(db.pageSize)
+ if (sz % pageSize) != 0 {
+ sz = ((sz / pageSize) + 1) * pageSize
+ }
+
+ // If we've exceeded the max size then only grow up to the max size.
+ if sz > maxMapSize {
+ sz = maxMapSize
+ }
+
+ return int(sz), nil
+}
+
+// init creates a new database file and initializes its meta pages.
+func (db *DB) init() error {
+ // Set the page size to the OS page size.
+ db.pageSize = os.Getpagesize()
+
+ // Create two meta pages on a buffer.
+ buf := make([]byte, db.pageSize*4)
+ for i := 0; i < 2; i++ {
+ p := db.pageInBuffer(buf[:], pgid(i))
+ p.id = pgid(i)
+ p.flags = metaPageFlag
+
+ // Initialize the meta page.
+ m := p.meta()
+ m.magic = magic
+ m.version = version
+ m.pageSize = uint32(db.pageSize)
+ m.freelist = 2
+ m.root = bucket{root: 3}
+ m.pgid = 4
+ m.txid = txid(i)
+ m.checksum = m.sum64()
+ }
+
+ // Write an empty freelist at page 3.
+ p := db.pageInBuffer(buf[:], pgid(2))
+ p.id = pgid(2)
+ p.flags = freelistPageFlag
+ p.count = 0
+
+ // Write an empty leaf page at page 4.
+ p = db.pageInBuffer(buf[:], pgid(3))
+ p.id = pgid(3)
+ p.flags = leafPageFlag
+ p.count = 0
+
+ // Write the buffer to our data file.
+ if _, err := db.ops.writeAt(buf, 0); err != nil {
+ return err
+ }
+ if err := fdatasync(db); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Close releases all database resources.
+// All transactions must be closed before closing the database.
+func (db *DB) Close() error {
+ db.rwlock.Lock()
+ defer db.rwlock.Unlock()
+
+ db.metalock.Lock()
+ defer db.metalock.Unlock()
+
+ db.mmaplock.RLock()
+ defer db.mmaplock.RUnlock()
+
+ return db.close()
+}
+
+func (db *DB) close() error {
+ if !db.opened {
+ return nil
+ }
+
+ db.opened = false
+
+ db.freelist = nil
+
+ // Clear ops.
+ db.ops.writeAt = nil
+
+ // Close the mmap.
+ if err := db.munmap(); err != nil {
+ return err
+ }
+
+ // Close file handles.
+ if db.file != nil {
+ // No need to unlock read-only file.
+ if !db.readOnly {
+ // Unlock the file.
+ if err := funlock(db); err != nil {
+ log.Printf("bolt.Close(): funlock error: %s", err)
+ }
+ }
+
+ // Close the file descriptor.
+ if err := db.file.Close(); err != nil {
+ return fmt.Errorf("db file close: %s", err)
+ }
+ db.file = nil
+ }
+
+ db.path = ""
+ return nil
+}
+
+// Begin starts a new transaction.
+// Multiple read-only transactions can be used concurrently but only one
+// write transaction can be used at a time. Starting multiple write transactions
+// will cause the calls to block and be serialized until the current write
+// transaction finishes.
+//
+// Transactions should not be dependent on one another. Opening a read
+// transaction and a write transaction in the same goroutine can cause the
+// writer to deadlock because the database periodically needs to re-mmap itself
+// as it grows and it cannot do that while a read transaction is open.
+//
+// If a long running read transaction (for example, a snapshot transaction) is
+// needed, you might want to set DB.InitialMmapSize to a large enough value
+// to avoid potential blocking of write transaction.
+//
+// IMPORTANT: You must close read-only transactions after you are finished or
+// else the database will not reclaim old pages.
+func (db *DB) Begin(writable bool) (*Tx, error) {
+ if writable {
+ return db.beginRWTx()
+ }
+ return db.beginTx()
+}
+
+func (db *DB) beginTx() (*Tx, error) {
+ // Lock the meta pages while we initialize the transaction. We obtain
+ // the meta lock before the mmap lock because that's the order that the
+ // write transaction will obtain them.
+ db.metalock.Lock()
+
+ // Obtain a read-only lock on the mmap. When the mmap is remapped it will
+ // obtain a write lock so all transactions must finish before it can be
+ // remapped.
+ db.mmaplock.RLock()
+
+ // Exit if the database is not open yet.
+ if !db.opened {
+ db.mmaplock.RUnlock()
+ db.metalock.Unlock()
+ return nil, ErrDatabaseNotOpen
+ }
+
+ // Create a transaction associated with the database.
+ t := &Tx{}
+ t.init(db)
+
+ // Keep track of transaction until it closes.
+ db.txs = append(db.txs, t)
+ n := len(db.txs)
+
+ // Unlock the meta pages.
+ db.metalock.Unlock()
+
+ // Update the transaction stats.
+ db.statlock.Lock()
+ db.stats.TxN++
+ db.stats.OpenTxN = n
+ db.statlock.Unlock()
+
+ return t, nil
+}
+
+func (db *DB) beginRWTx() (*Tx, error) {
+ // If the database was opened with Options.ReadOnly, return an error.
+ if db.readOnly {
+ return nil, ErrDatabaseReadOnly
+ }
+
+ // Obtain writer lock. This is released by the transaction when it closes.
+ // This enforces only one writer transaction at a time.
+ db.rwlock.Lock()
+
+ // Once we have the writer lock then we can lock the meta pages so that
+ // we can set up the transaction.
+ db.metalock.Lock()
+ defer db.metalock.Unlock()
+
+ // Exit if the database is not open yet.
+ if !db.opened {
+ db.rwlock.Unlock()
+ return nil, ErrDatabaseNotOpen
+ }
+
+ // Create a transaction associated with the database.
+ t := &Tx{writable: true}
+ t.init(db)
+ db.rwtx = t
+
+ // Free any pages associated with closed read-only transactions.
+ var minid txid = 0xFFFFFFFFFFFFFFFF
+ for _, t := range db.txs {
+ if t.meta.txid < minid {
+ minid = t.meta.txid
+ }
+ }
+ if minid > 0 {
+ db.freelist.release(minid - 1)
+ }
+
+ return t, nil
+}
+
+// removeTx removes a transaction from the database.
+func (db *DB) removeTx(tx *Tx) {
+ // Release the read lock on the mmap.
+ db.mmaplock.RUnlock()
+
+ // Use the meta lock to restrict access to the DB object.
+ db.metalock.Lock()
+
+ // Remove the transaction.
+ for i, t := range db.txs {
+ if t == tx {
+ db.txs = append(db.txs[:i], db.txs[i+1:]...)
+ break
+ }
+ }
+ n := len(db.txs)
+
+ // Unlock the meta pages.
+ db.metalock.Unlock()
+
+ // Merge statistics.
+ db.statlock.Lock()
+ db.stats.OpenTxN = n
+ db.stats.TxStats.add(&tx.stats)
+ db.statlock.Unlock()
+}
+
+// Update executes a function within the context of a read-write managed transaction.
+// If no error is returned from the function then the transaction is committed.
+// If an error is returned then the entire transaction is rolled back.
+// Any error that is returned from the function or returned from the commit is
+// returned from the Update() method.
+//
+// Attempting to manually commit or rollback within the function will cause a panic.
+func (db *DB) Update(fn func(*Tx) error) error {
+ t, err := db.Begin(true)
+ if err != nil {
+ return err
+ }
+
+ // Make sure the transaction rolls back in the event of a panic.
+ defer func() {
+ if t.db != nil {
+ t.rollback()
+ }
+ }()
+
+ // Mark as a managed tx so that the inner function cannot manually commit.
+ t.managed = true
+
+ // If an error is returned from the function then rollback and return error.
+ err = fn(t)
+ t.managed = false
+ if err != nil {
+ _ = t.Rollback()
+ return err
+ }
+
+ return t.Commit()
+}
+
+// View executes a function within the context of a managed read-only transaction.
+// Any error that is returned from the function is returned from the View() method.
+//
+// Attempting to manually rollback within the function will cause a panic.
+func (db *DB) View(fn func(*Tx) error) error {
+ t, err := db.Begin(false)
+ if err != nil {
+ return err
+ }
+
+ // Make sure the transaction rolls back in the event of a panic.
+ defer func() {
+ if t.db != nil {
+ t.rollback()
+ }
+ }()
+
+ // Mark as a managed tx so that the inner function cannot manually rollback.
+ t.managed = true
+
+ // If an error is returned from the function then pass it through.
+ err = fn(t)
+ t.managed = false
+ if err != nil {
+ _ = t.Rollback()
+ return err
+ }
+
+ if err := t.Rollback(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Batch calls fn as part of a batch. It behaves similar to Update,
+// except:
+//
+// 1. concurrent Batch calls can be combined into a single Bolt
+// transaction.
+//
+// 2. the function passed to Batch may be called multiple times,
+// regardless of whether it returns error or not.
+//
+// This means that Batch function side effects must be idempotent and
+// take permanent effect only after a successful return is seen in
+// caller.
+//
+// The maximum batch size and delay can be adjusted with DB.MaxBatchSize
+// and DB.MaxBatchDelay, respectively.
+//
+// Batch is only useful when there are multiple goroutines calling it.
+func (db *DB) Batch(fn func(*Tx) error) error {
+ errCh := make(chan error, 1)
+
+ db.batchMu.Lock()
+ if (db.batch == nil) || (db.batch != nil && len(db.batch.calls) >= db.MaxBatchSize) {
+ // There is no existing batch, or the existing batch is full; start a new one.
+ db.batch = &batch{
+ db: db,
+ }
+ db.batch.timer = time.AfterFunc(db.MaxBatchDelay, db.batch.trigger)
+ }
+ db.batch.calls = append(db.batch.calls, call{fn: fn, err: errCh})
+ if len(db.batch.calls) >= db.MaxBatchSize {
+ // wake up batch, it's ready to run
+ go db.batch.trigger()
+ }
+ db.batchMu.Unlock()
+
+ err := <-errCh
+ if err == trySolo {
+ err = db.Update(fn)
+ }
+ return err
+}
+
+type call struct {
+ fn func(*Tx) error
+ err chan<- error
+}
+
+type batch struct {
+ db *DB
+ timer *time.Timer
+ start sync.Once
+ calls []call
+}
+
+// trigger runs the batch if it hasn't already been run.
+func (b *batch) trigger() {
+ b.start.Do(b.run)
+}
+
+// run performs the transactions in the batch and communicates results
+// back to DB.Batch.
+func (b *batch) run() {
+ b.db.batchMu.Lock()
+ b.timer.Stop()
+ // Make sure no new work is added to this batch, but don't break
+ // other batches.
+ if b.db.batch == b {
+ b.db.batch = nil
+ }
+ b.db.batchMu.Unlock()
+
+retry:
+ for len(b.calls) > 0 {
+ var failIdx = -1
+ err := b.db.Update(func(tx *Tx) error {
+ for i, c := range b.calls {
+ if err := safelyCall(c.fn, tx); err != nil {
+ failIdx = i
+ return err
+ }
+ }
+ return nil
+ })
+
+ if failIdx >= 0 {
+ // take the failing transaction out of the batch. it's
+ // safe to shorten b.calls here because db.batch no longer
+ // points to us, and we hold the mutex anyway.
+ c := b.calls[failIdx]
+ b.calls[failIdx], b.calls = b.calls[len(b.calls)-1], b.calls[:len(b.calls)-1]
+ // tell the submitter re-run it solo, continue with the rest of the batch
+ c.err <- trySolo
+ continue retry
+ }
+
+ // pass success, or bolt internal errors, to all callers
+ for _, c := range b.calls {
+ if c.err != nil {
+ c.err <- err
+ }
+ }
+ break retry
+ }
+}
+
+// trySolo is a special sentinel error value used for signaling that a
+// transaction function should be re-run. It should never be seen by
+// callers.
+var trySolo = errors.New("batch function returned an error and should be re-run solo")
+
+type panicked struct {
+ reason interface{}
+}
+
+func (p panicked) Error() string {
+ if err, ok := p.reason.(error); ok {
+ return err.Error()
+ }
+ return fmt.Sprintf("panic: %v", p.reason)
+}
+
+func safelyCall(fn func(*Tx) error, tx *Tx) (err error) {
+ defer func() {
+ if p := recover(); p != nil {
+ err = panicked{p}
+ }
+ }()
+ return fn(tx)
+}
+
+// Sync executes fdatasync() against the database file handle.
+//
+// This is not necessary under normal operation, however, if you use NoSync
+// then it allows you to force the database file to sync against the disk.
+func (db *DB) Sync() error { return fdatasync(db) }
+
+// Stats retrieves ongoing performance stats for the database.
+// This is only updated when a transaction closes.
+func (db *DB) Stats() Stats {
+ db.statlock.RLock()
+ defer db.statlock.RUnlock()
+ return db.stats
+}
+
+// This is for internal access to the raw data bytes from the C cursor, use
+// carefully, or not at all.
+func (db *DB) Info() *Info {
+ return &Info{uintptr(unsafe.Pointer(&db.data[0])), db.pageSize}
+}
+
+// page retrieves a page reference from the mmap based on the current page size.
+func (db *DB) page(id pgid) *page {
+ pos := id * pgid(db.pageSize)
+ return (*page)(unsafe.Pointer(&db.data[pos]))
+}
+
+// pageInBuffer retrieves a page reference from a given byte array based on the current page size.
+func (db *DB) pageInBuffer(b []byte, id pgid) *page {
+ return (*page)(unsafe.Pointer(&b[id*pgid(db.pageSize)]))
+}
+
+// meta retrieves the current meta page reference.
+func (db *DB) meta() *meta {
+ // We have to return the meta with the highest txid which doesn't fail
+ // validation. Otherwise, we can cause errors when in fact the database is
+ // in a consistent state. metaA is the one with the higher txid.
+ metaA := db.meta0
+ metaB := db.meta1
+ if db.meta1.txid > db.meta0.txid {
+ metaA = db.meta1
+ metaB = db.meta0
+ }
+
+ // Use higher meta page if valid. Otherwise fallback to previous, if valid.
+ if err := metaA.validate(); err == nil {
+ return metaA
+ } else if err := metaB.validate(); err == nil {
+ return metaB
+ }
+
+ // This should never be reached, because both meta1 and meta0 were validated
+ // on mmap() and we do fsync() on every write.
+ panic("bolt.DB.meta(): invalid meta pages")
+}
+
+// allocate returns a contiguous block of memory starting at a given page.
+func (db *DB) allocate(count int) (*page, error) {
+ // Allocate a temporary buffer for the page.
+ var buf []byte
+ if count == 1 {
+ buf = db.pagePool.Get().([]byte)
+ } else {
+ buf = make([]byte, count*db.pageSize)
+ }
+ p := (*page)(unsafe.Pointer(&buf[0]))
+ p.overflow = uint32(count - 1)
+
+ // Use pages from the freelist if they are available.
+ if p.id = db.freelist.allocate(count); p.id != 0 {
+ return p, nil
+ }
+
+ // Resize mmap() if we're at the end.
+ p.id = db.rwtx.meta.pgid
+ var minsz = int((p.id+pgid(count))+1) * db.pageSize
+ if minsz >= db.datasz {
+ if err := db.mmap(minsz); err != nil {
+ return nil, fmt.Errorf("mmap allocate error: %s", err)
+ }
+ }
+
+ // Move the page id high water mark.
+ db.rwtx.meta.pgid += pgid(count)
+
+ return p, nil
+}
+
+// grow grows the size of the database to the given sz.
+func (db *DB) grow(sz int) error {
+ // Ignore if the new size is less than available file size.
+ if sz <= db.filesz {
+ return nil
+ }
+
+ // If the data is smaller than the alloc size then only allocate what's needed.
+ // Once it goes over the allocation size then allocate in chunks.
+ if db.datasz < db.AllocSize {
+ sz = db.datasz
+ } else {
+ sz += db.AllocSize
+ }
+
+ // Truncate and fsync to ensure file size metadata is flushed.
+ // https://github.com/boltdb/bolt/issues/284
+ if !db.NoGrowSync && !db.readOnly {
+ if runtime.GOOS != "windows" {
+ if err := db.file.Truncate(int64(sz)); err != nil {
+ return fmt.Errorf("file resize error: %s", err)
+ }
+ }
+ if err := db.file.Sync(); err != nil {
+ return fmt.Errorf("file sync error: %s", err)
+ }
+ }
+
+ db.filesz = sz
+ return nil
+}
+
+func (db *DB) IsReadOnly() bool {
+ return db.readOnly
+}
+
+// Options represents the options that can be set when opening a database.
+type Options struct {
+ // Timeout is the amount of time to wait to obtain a file lock.
+ // When set to zero it will wait indefinitely. This option is only
+ // available on Darwin and Linux.
+ Timeout time.Duration
+
+ // Sets the DB.NoGrowSync flag before memory mapping the file.
+ NoGrowSync bool
+
+ // Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to
+ // grab a shared lock (UNIX).
+ ReadOnly bool
+
+ // Sets the DB.MmapFlags flag before memory mapping the file.
+ MmapFlags int
+
+ // InitialMmapSize is the initial mmap size of the database
+ // in bytes. Read transactions won't block write transaction
+ // if the InitialMmapSize is large enough to hold database mmap
+ // size. (See DB.Begin for more information)
+ //
+ // If <=0, the initial map size is 0.
+ // If initialMmapSize is smaller than the previous database size,
+ // it takes no effect.
+ InitialMmapSize int
+}
+
+// DefaultOptions represent the options used if nil options are passed into Open().
+// No timeout is used which will cause Bolt to wait indefinitely for a lock.
+var DefaultOptions = &Options{
+ Timeout: 0,
+ NoGrowSync: false,
+}
+
+// Stats represents statistics about the database.
+type Stats struct {
+ // Freelist stats
+ FreePageN int // total number of free pages on the freelist
+ PendingPageN int // total number of pending pages on the freelist
+ FreeAlloc int // total bytes allocated in free pages
+ FreelistInuse int // total bytes used by the freelist
+
+ // Transaction stats
+ TxN int // total number of started read transactions
+ OpenTxN int // number of currently open read transactions
+
+ TxStats TxStats // global, ongoing stats.
+}
+
+// Sub calculates and returns the difference between two sets of database stats.
+// This is useful when obtaining stats at two different points and time and
+// you need the performance counters that occurred within that time span.
+func (s *Stats) Sub(other *Stats) Stats {
+ if other == nil {
+ return *s
+ }
+ var diff Stats
+ diff.FreePageN = s.FreePageN
+ diff.PendingPageN = s.PendingPageN
+ diff.FreeAlloc = s.FreeAlloc
+ diff.FreelistInuse = s.FreelistInuse
+ diff.TxN = other.TxN - s.TxN
+ diff.TxStats = s.TxStats.Sub(&other.TxStats)
+ return diff
+}
+
+func (s *Stats) add(other *Stats) {
+ s.TxStats.add(&other.TxStats)
+}
+
+type Info struct {
+ Data uintptr
+ PageSize int
+}
+
+type meta struct {
+ magic uint32
+ version uint32
+ pageSize uint32
+ flags uint32
+ root bucket
+ freelist pgid
+ pgid pgid
+ txid txid
+ checksum uint64
+}
+
+// validate checks the marker bytes and version of the meta page to ensure it matches this binary.
+func (m *meta) validate() error {
+ if m.magic != magic {
+ return ErrInvalid
+ } else if m.version != version {
+ return ErrVersionMismatch
+ } else if m.checksum != 0 && m.checksum != m.sum64() {
+ return ErrChecksum
+ }
+ return nil
+}
+
+// copy copies one meta object to another.
+func (m *meta) copy(dest *meta) {
+ *dest = *m
+}
+
+// write writes the meta onto a page.
+func (m *meta) write(p *page) {
+ if m.root.root >= m.pgid {
+ panic(fmt.Sprintf("root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid))
+ } else if m.freelist >= m.pgid {
+ panic(fmt.Sprintf("freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid))
+ }
+
+ // Page id is either going to be 0 or 1 which we can determine by the transaction ID.
+ p.id = pgid(m.txid % 2)
+ p.flags |= metaPageFlag
+
+ // Calculate the checksum.
+ m.checksum = m.sum64()
+
+ m.copy(p.meta())
+}
+
+// generates the checksum for the meta.
+func (m *meta) sum64() uint64 {
+ var h = fnv.New64a()
+ _, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:])
+ return h.Sum64()
+}
+
+// _assert will panic with a given formatted message if the given condition is false.
+func _assert(condition bool, msg string, v ...interface{}) {
+ if !condition {
+ panic(fmt.Sprintf("assertion failed: "+msg, v...))
+ }
+}
+
+func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
+func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
+
+func printstack() {
+ stack := strings.Join(strings.Split(string(debug.Stack()), "\n")[2:], "\n")
+ fmt.Fprintln(os.Stderr, stack)
+}
diff --git a/vendor/github.com/coreos/bbolt/doc.go b/vendor/github.com/coreos/bbolt/doc.go
new file mode 100644
index 00000000..cc937845
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/doc.go
@@ -0,0 +1,44 @@
+/*
+Package bolt implements a low-level key/value store in pure Go. It supports
+fully serializable transactions, ACID semantics, and lock-free MVCC with
+multiple readers and a single writer. Bolt can be used for projects that
+want a simple data store without the need to add large dependencies such as
+Postgres or MySQL.
+
+Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is
+optimized for fast read access and does not require recovery in the event of a
+system crash. Transactions which have not finished committing will simply be
+rolled back in the event of a crash.
+
+The design of Bolt is based on Howard Chu's LMDB database project.
+
+Bolt currently works on Windows, Mac OS X, and Linux.
+
+
+Basics
+
+There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is
+a collection of buckets and is represented by a single file on disk. A bucket is
+a collection of unique keys that are associated with values.
+
+Transactions provide either read-only or read-write access to the database.
+Read-only transactions can retrieve key/value pairs and can use Cursors to
+iterate over the dataset sequentially. Read-write transactions can create and
+delete buckets and can insert and remove keys. Only one read-write transaction
+is allowed at a time.
+
+
+Caveats
+
+The database uses a read-only, memory-mapped data file to ensure that
+applications cannot corrupt the database, however, this means that keys and
+values returned from Bolt cannot be changed. Writing to a read-only byte slice
+will cause Go to panic.
+
+Keys and values retrieved from the database are only valid for the life of
+the transaction. When used outside the transaction, these byte slices can
+point to different data or can point to invalid memory which will cause a panic.
+
+
+*/
+package bolt
diff --git a/vendor/github.com/coreos/bbolt/errors.go b/vendor/github.com/coreos/bbolt/errors.go
new file mode 100644
index 00000000..a3620a3e
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/errors.go
@@ -0,0 +1,71 @@
+package bolt
+
+import "errors"
+
+// These errors can be returned when opening or calling methods on a DB.
+var (
+ // ErrDatabaseNotOpen is returned when a DB instance is accessed before it
+ // is opened or after it is closed.
+ ErrDatabaseNotOpen = errors.New("database not open")
+
+ // ErrDatabaseOpen is returned when opening a database that is
+ // already open.
+ ErrDatabaseOpen = errors.New("database already open")
+
+ // ErrInvalid is returned when both meta pages on a database are invalid.
+ // This typically occurs when a file is not a bolt database.
+ ErrInvalid = errors.New("invalid database")
+
+ // ErrVersionMismatch is returned when the data file was created with a
+ // different version of Bolt.
+ ErrVersionMismatch = errors.New("version mismatch")
+
+ // ErrChecksum is returned when either meta page checksum does not match.
+ ErrChecksum = errors.New("checksum error")
+
+ // ErrTimeout is returned when a database cannot obtain an exclusive lock
+ // on the data file after the timeout passed to Open().
+ ErrTimeout = errors.New("timeout")
+)
+
+// These errors can occur when beginning or committing a Tx.
+var (
+ // ErrTxNotWritable is returned when performing a write operation on a
+ // read-only transaction.
+ ErrTxNotWritable = errors.New("tx not writable")
+
+ // ErrTxClosed is returned when committing or rolling back a transaction
+ // that has already been committed or rolled back.
+ ErrTxClosed = errors.New("tx closed")
+
+ // ErrDatabaseReadOnly is returned when a mutating transaction is started on a
+ // read-only database.
+ ErrDatabaseReadOnly = errors.New("database is in read-only mode")
+)
+
+// These errors can occur when putting or deleting a value or a bucket.
+var (
+ // ErrBucketNotFound is returned when trying to access a bucket that has
+ // not been created yet.
+ ErrBucketNotFound = errors.New("bucket not found")
+
+ // ErrBucketExists is returned when creating a bucket that already exists.
+ ErrBucketExists = errors.New("bucket already exists")
+
+ // ErrBucketNameRequired is returned when creating a bucket with a blank name.
+ ErrBucketNameRequired = errors.New("bucket name required")
+
+ // ErrKeyRequired is returned when inserting a zero-length key.
+ ErrKeyRequired = errors.New("key required")
+
+ // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize.
+ ErrKeyTooLarge = errors.New("key too large")
+
+ // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize.
+ ErrValueTooLarge = errors.New("value too large")
+
+ // ErrIncompatibleValue is returned when trying create or delete a bucket
+ // on an existing non-bucket key or when trying to create or delete a
+ // non-bucket key on an existing bucket key.
+ ErrIncompatibleValue = errors.New("incompatible value")
+)
diff --git a/vendor/github.com/coreos/bbolt/freelist.go b/vendor/github.com/coreos/bbolt/freelist.go
new file mode 100644
index 00000000..1b7ba91b
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/freelist.go
@@ -0,0 +1,248 @@
+package bolt
+
+import (
+ "fmt"
+ "sort"
+ "unsafe"
+)
+
+// freelist represents a list of all pages that are available for allocation.
+// It also tracks pages that have been freed but are still in use by open transactions.
+type freelist struct {
+ ids []pgid // all free and available free page ids.
+ pending map[txid][]pgid // mapping of soon-to-be free page ids by tx.
+ cache map[pgid]bool // fast lookup of all free and pending page ids.
+}
+
+// newFreelist returns an empty, initialized freelist.
+func newFreelist() *freelist {
+ return &freelist{
+ pending: make(map[txid][]pgid),
+ cache: make(map[pgid]bool),
+ }
+}
+
+// size returns the size of the page after serialization.
+func (f *freelist) size() int {
+ return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * f.count())
+}
+
+// count returns count of pages on the freelist
+func (f *freelist) count() int {
+ return f.free_count() + f.pending_count()
+}
+
+// free_count returns count of free pages
+func (f *freelist) free_count() int {
+ return len(f.ids)
+}
+
+// pending_count returns count of pending pages
+func (f *freelist) pending_count() int {
+ var count int
+ for _, list := range f.pending {
+ count += len(list)
+ }
+ return count
+}
+
+// all returns a list of all free ids and all pending ids in one sorted list.
+func (f *freelist) all() []pgid {
+ m := make(pgids, 0)
+
+ for _, list := range f.pending {
+ m = append(m, list...)
+ }
+
+ sort.Sort(m)
+ return pgids(f.ids).merge(m)
+}
+
+// allocate returns the starting page id of a contiguous list of pages of a given size.
+// If a contiguous block cannot be found then 0 is returned.
+func (f *freelist) allocate(n int) pgid {
+ if len(f.ids) == 0 {
+ return 0
+ }
+
+ var initial, previd pgid
+ for i, id := range f.ids {
+ if id <= 1 {
+ panic(fmt.Sprintf("invalid page allocation: %d", id))
+ }
+
+ // Reset initial page if this is not contiguous.
+ if previd == 0 || id-previd != 1 {
+ initial = id
+ }
+
+ // If we found a contiguous block then remove it and return it.
+ if (id-initial)+1 == pgid(n) {
+ // If we're allocating off the beginning then take the fast path
+ // and just adjust the existing slice. This will use extra memory
+ // temporarily but the append() in free() will realloc the slice
+ // as is necessary.
+ if (i + 1) == n {
+ f.ids = f.ids[i+1:]
+ } else {
+ copy(f.ids[i-n+1:], f.ids[i+1:])
+ f.ids = f.ids[:len(f.ids)-n]
+ }
+
+ // Remove from the free cache.
+ for i := pgid(0); i < pgid(n); i++ {
+ delete(f.cache, initial+i)
+ }
+
+ return initial
+ }
+
+ previd = id
+ }
+ return 0
+}
+
+// free releases a page and its overflow for a given transaction id.
+// If the page is already free then a panic will occur.
+func (f *freelist) free(txid txid, p *page) {
+ if p.id <= 1 {
+ panic(fmt.Sprintf("cannot free page 0 or 1: %d", p.id))
+ }
+
+ // Free page and all its overflow pages.
+ var ids = f.pending[txid]
+ for id := p.id; id <= p.id+pgid(p.overflow); id++ {
+ // Verify that page is not already free.
+ if f.cache[id] {
+ panic(fmt.Sprintf("page %d already freed", id))
+ }
+
+ // Add to the freelist and cache.
+ ids = append(ids, id)
+ f.cache[id] = true
+ }
+ f.pending[txid] = ids
+}
+
+// release moves all page ids for a transaction id (or older) to the freelist.
+func (f *freelist) release(txid txid) {
+ m := make(pgids, 0)
+ for tid, ids := range f.pending {
+ if tid <= txid {
+ // Move transaction's pending pages to the available freelist.
+ // Don't remove from the cache since the page is still free.
+ m = append(m, ids...)
+ delete(f.pending, tid)
+ }
+ }
+ sort.Sort(m)
+ f.ids = pgids(f.ids).merge(m)
+}
+
+// rollback removes the pages from a given pending tx.
+func (f *freelist) rollback(txid txid) {
+ // Remove page ids from cache.
+ for _, id := range f.pending[txid] {
+ delete(f.cache, id)
+ }
+
+ // Remove pages from pending list.
+ delete(f.pending, txid)
+}
+
+// freed returns whether a given page is in the free list.
+func (f *freelist) freed(pgid pgid) bool {
+ return f.cache[pgid]
+}
+
+// read initializes the freelist from a freelist page.
+func (f *freelist) read(p *page) {
+ // If the page.count is at the max uint16 value (64k) then it's considered
+ // an overflow and the size of the freelist is stored as the first element.
+ idx, count := 0, int(p.count)
+ if count == 0xFFFF {
+ idx = 1
+ count = int(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0])
+ }
+
+ // Copy the list of page ids from the freelist.
+ if count == 0 {
+ f.ids = nil
+ } else {
+ ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count]
+ f.ids = make([]pgid, len(ids))
+ copy(f.ids, ids)
+
+ // Make sure they're sorted.
+ sort.Sort(pgids(f.ids))
+ }
+
+ // Rebuild the page cache.
+ f.reindex()
+}
+
+// write writes the page ids onto a freelist page. All free and pending ids are
+// saved to disk since in the event of a program crash, all pending ids will
+// become free.
+func (f *freelist) write(p *page) error {
+ // Combine the old free pgids and pgids waiting on an open transaction.
+ ids := f.all()
+
+ // Update the header flag.
+ p.flags |= freelistPageFlag
+
+ // The page.count can only hold up to 64k elements so if we overflow that
+ // number then we handle it by putting the size in the first element.
+ if len(ids) == 0 {
+ p.count = uint16(len(ids))
+ } else if len(ids) < 0xFFFF {
+ p.count = uint16(len(ids))
+ copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:], ids)
+ } else {
+ p.count = 0xFFFF
+ ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(len(ids))
+ copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:], ids)
+ }
+
+ return nil
+}
+
+// reload reads the freelist from a page and filters out pending items.
+func (f *freelist) reload(p *page) {
+ f.read(p)
+
+ // Build a cache of only pending pages.
+ pcache := make(map[pgid]bool)
+ for _, pendingIDs := range f.pending {
+ for _, pendingID := range pendingIDs {
+ pcache[pendingID] = true
+ }
+ }
+
+ // Check each page in the freelist and build a new available freelist
+ // with any pages not in the pending lists.
+ var a []pgid
+ for _, id := range f.ids {
+ if !pcache[id] {
+ a = append(a, id)
+ }
+ }
+ f.ids = a
+
+ // Once the available list is rebuilt then rebuild the free cache so that
+ // it includes the available and pending free pages.
+ f.reindex()
+}
+
+// reindex rebuilds the free cache based on available and pending free lists.
+func (f *freelist) reindex() {
+ f.cache = make(map[pgid]bool)
+ for _, id := range f.ids {
+ f.cache[id] = true
+ }
+ for _, pendingIDs := range f.pending {
+ for _, pendingID := range pendingIDs {
+ f.cache[pendingID] = true
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/bbolt/node.go b/vendor/github.com/coreos/bbolt/node.go
new file mode 100644
index 00000000..159318b2
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/node.go
@@ -0,0 +1,604 @@
+package bolt
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "unsafe"
+)
+
+// node represents an in-memory, deserialized page.
+type node struct {
+ bucket *Bucket
+ isLeaf bool
+ unbalanced bool
+ spilled bool
+ key []byte
+ pgid pgid
+ parent *node
+ children nodes
+ inodes inodes
+}
+
+// root returns the top-level node this node is attached to.
+func (n *node) root() *node {
+ if n.parent == nil {
+ return n
+ }
+ return n.parent.root()
+}
+
+// minKeys returns the minimum number of inodes this node should have.
+func (n *node) minKeys() int {
+ if n.isLeaf {
+ return 1
+ }
+ return 2
+}
+
+// size returns the size of the node after serialization.
+func (n *node) size() int {
+ sz, elsz := pageHeaderSize, n.pageElementSize()
+ for i := 0; i < len(n.inodes); i++ {
+ item := &n.inodes[i]
+ sz += elsz + len(item.key) + len(item.value)
+ }
+ return sz
+}
+
+// sizeLessThan returns true if the node is less than a given size.
+// This is an optimization to avoid calculating a large node when we only need
+// to know if it fits inside a certain page size.
+func (n *node) sizeLessThan(v int) bool {
+ sz, elsz := pageHeaderSize, n.pageElementSize()
+ for i := 0; i < len(n.inodes); i++ {
+ item := &n.inodes[i]
+ sz += elsz + len(item.key) + len(item.value)
+ if sz >= v {
+ return false
+ }
+ }
+ return true
+}
+
+// pageElementSize returns the size of each page element based on the type of node.
+func (n *node) pageElementSize() int {
+ if n.isLeaf {
+ return leafPageElementSize
+ }
+ return branchPageElementSize
+}
+
+// childAt returns the child node at a given index.
+func (n *node) childAt(index int) *node {
+ if n.isLeaf {
+ panic(fmt.Sprintf("invalid childAt(%d) on a leaf node", index))
+ }
+ return n.bucket.node(n.inodes[index].pgid, n)
+}
+
+// childIndex returns the index of a given child node.
+func (n *node) childIndex(child *node) int {
+ index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, child.key) != -1 })
+ return index
+}
+
+// numChildren returns the number of children.
+func (n *node) numChildren() int {
+ return len(n.inodes)
+}
+
+// nextSibling returns the next node with the same parent.
+func (n *node) nextSibling() *node {
+ if n.parent == nil {
+ return nil
+ }
+ index := n.parent.childIndex(n)
+ if index >= n.parent.numChildren()-1 {
+ return nil
+ }
+ return n.parent.childAt(index + 1)
+}
+
+// prevSibling returns the previous node with the same parent.
+func (n *node) prevSibling() *node {
+ if n.parent == nil {
+ return nil
+ }
+ index := n.parent.childIndex(n)
+ if index == 0 {
+ return nil
+ }
+ return n.parent.childAt(index - 1)
+}
+
+// put inserts a key/value.
+func (n *node) put(oldKey, newKey, value []byte, pgid pgid, flags uint32) {
+ if pgid >= n.bucket.tx.meta.pgid {
+ panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", pgid, n.bucket.tx.meta.pgid))
+ } else if len(oldKey) <= 0 {
+ panic("put: zero-length old key")
+ } else if len(newKey) <= 0 {
+ panic("put: zero-length new key")
+ }
+
+ // Find insertion index.
+ index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, oldKey) != -1 })
+
+ // Add capacity and shift nodes if we don't have an exact match and need to insert.
+ exact := (len(n.inodes) > 0 && index < len(n.inodes) && bytes.Equal(n.inodes[index].key, oldKey))
+ if !exact {
+ n.inodes = append(n.inodes, inode{})
+ copy(n.inodes[index+1:], n.inodes[index:])
+ }
+
+ inode := &n.inodes[index]
+ inode.flags = flags
+ inode.key = newKey
+ inode.value = value
+ inode.pgid = pgid
+ _assert(len(inode.key) > 0, "put: zero-length inode key")
+}
+
+// del removes a key from the node.
+func (n *node) del(key []byte) {
+ // Find index of key.
+ index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, key) != -1 })
+
+ // Exit if the key isn't found.
+ if index >= len(n.inodes) || !bytes.Equal(n.inodes[index].key, key) {
+ return
+ }
+
+ // Delete inode from the node.
+ n.inodes = append(n.inodes[:index], n.inodes[index+1:]...)
+
+ // Mark the node as needing rebalancing.
+ n.unbalanced = true
+}
+
+// read initializes the node from a page.
+func (n *node) read(p *page) {
+ n.pgid = p.id
+ n.isLeaf = ((p.flags & leafPageFlag) != 0)
+ n.inodes = make(inodes, int(p.count))
+
+ for i := 0; i < int(p.count); i++ {
+ inode := &n.inodes[i]
+ if n.isLeaf {
+ elem := p.leafPageElement(uint16(i))
+ inode.flags = elem.flags
+ inode.key = elem.key()
+ inode.value = elem.value()
+ } else {
+ elem := p.branchPageElement(uint16(i))
+ inode.pgid = elem.pgid
+ inode.key = elem.key()
+ }
+ _assert(len(inode.key) > 0, "read: zero-length inode key")
+ }
+
+ // Save first key so we can find the node in the parent when we spill.
+ if len(n.inodes) > 0 {
+ n.key = n.inodes[0].key
+ _assert(len(n.key) > 0, "read: zero-length node key")
+ } else {
+ n.key = nil
+ }
+}
+
+// write writes the items onto one or more pages.
+func (n *node) write(p *page) {
+ // Initialize page.
+ if n.isLeaf {
+ p.flags |= leafPageFlag
+ } else {
+ p.flags |= branchPageFlag
+ }
+
+ if len(n.inodes) >= 0xFFFF {
+ panic(fmt.Sprintf("inode overflow: %d (pgid=%d)", len(n.inodes), p.id))
+ }
+ p.count = uint16(len(n.inodes))
+
+ // Stop here if there are no items to write.
+ if p.count == 0 {
+ return
+ }
+
+ // Loop over each item and write it to the page.
+ b := (*[maxAllocSize]byte)(unsafe.Pointer(&p.ptr))[n.pageElementSize()*len(n.inodes):]
+ for i, item := range n.inodes {
+ _assert(len(item.key) > 0, "write: zero-length inode key")
+
+ // Write the page element.
+ if n.isLeaf {
+ elem := p.leafPageElement(uint16(i))
+ elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem)))
+ elem.flags = item.flags
+ elem.ksize = uint32(len(item.key))
+ elem.vsize = uint32(len(item.value))
+ } else {
+ elem := p.branchPageElement(uint16(i))
+ elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem)))
+ elem.ksize = uint32(len(item.key))
+ elem.pgid = item.pgid
+ _assert(elem.pgid != p.id, "write: circular dependency occurred")
+ }
+
+ // If the length of key+value is larger than the max allocation size
+ // then we need to reallocate the byte array pointer.
+ //
+ // See: https://github.com/boltdb/bolt/pull/335
+ klen, vlen := len(item.key), len(item.value)
+ if len(b) < klen+vlen {
+ b = (*[maxAllocSize]byte)(unsafe.Pointer(&b[0]))[:]
+ }
+
+ // Write data for the element to the end of the page.
+ copy(b[0:], item.key)
+ b = b[klen:]
+ copy(b[0:], item.value)
+ b = b[vlen:]
+ }
+
+ // DEBUG ONLY: n.dump()
+}
+
+// split breaks up a node into multiple smaller nodes, if appropriate.
+// This should only be called from the spill() function.
+func (n *node) split(pageSize int) []*node {
+ var nodes []*node
+
+ node := n
+ for {
+ // Split node into two.
+ a, b := node.splitTwo(pageSize)
+ nodes = append(nodes, a)
+
+ // If we can't split then exit the loop.
+ if b == nil {
+ break
+ }
+
+ // Set node to b so it gets split on the next iteration.
+ node = b
+ }
+
+ return nodes
+}
+
+// splitTwo breaks up a node into two smaller nodes, if appropriate.
+// This should only be called from the split() function.
+func (n *node) splitTwo(pageSize int) (*node, *node) {
+ // Ignore the split if the page doesn't have at least enough nodes for
+ // two pages or if the nodes can fit in a single page.
+ if len(n.inodes) <= (minKeysPerPage*2) || n.sizeLessThan(pageSize) {
+ return n, nil
+ }
+
+ // Determine the threshold before starting a new node.
+ var fillPercent = n.bucket.FillPercent
+ if fillPercent < minFillPercent {
+ fillPercent = minFillPercent
+ } else if fillPercent > maxFillPercent {
+ fillPercent = maxFillPercent
+ }
+ threshold := int(float64(pageSize) * fillPercent)
+
+ // Determine split position and sizes of the two pages.
+ splitIndex, _ := n.splitIndex(threshold)
+
+ // Split node into two separate nodes.
+ // If there's no parent then we'll need to create one.
+ if n.parent == nil {
+ n.parent = &node{bucket: n.bucket, children: []*node{n}}
+ }
+
+ // Create a new node and add it to the parent.
+ next := &node{bucket: n.bucket, isLeaf: n.isLeaf, parent: n.parent}
+ n.parent.children = append(n.parent.children, next)
+
+ // Split inodes across two nodes.
+ next.inodes = n.inodes[splitIndex:]
+ n.inodes = n.inodes[:splitIndex]
+
+ // Update the statistics.
+ n.bucket.tx.stats.Split++
+
+ return n, next
+}
+
+// splitIndex finds the position where a page will fill a given threshold.
+// It returns the index as well as the size of the first page.
+// This is only be called from split().
+func (n *node) splitIndex(threshold int) (index, sz int) {
+ sz = pageHeaderSize
+
+ // Loop until we only have the minimum number of keys required for the second page.
+ for i := 0; i < len(n.inodes)-minKeysPerPage; i++ {
+ index = i
+ inode := n.inodes[i]
+ elsize := n.pageElementSize() + len(inode.key) + len(inode.value)
+
+ // If we have at least the minimum number of keys and adding another
+ // node would put us over the threshold then exit and return.
+ if i >= minKeysPerPage && sz+elsize > threshold {
+ break
+ }
+
+ // Add the element size to the total size.
+ sz += elsize
+ }
+
+ return
+}
+
+// spill writes the nodes to dirty pages and splits nodes as it goes.
+// Returns an error if dirty pages cannot be allocated.
+func (n *node) spill() error {
+ var tx = n.bucket.tx
+ if n.spilled {
+ return nil
+ }
+
+ // Spill child nodes first. Child nodes can materialize sibling nodes in
+ // the case of split-merge so we cannot use a range loop. We have to check
+ // the children size on every loop iteration.
+ sort.Sort(n.children)
+ for i := 0; i < len(n.children); i++ {
+ if err := n.children[i].spill(); err != nil {
+ return err
+ }
+ }
+
+ // We no longer need the child list because it's only used for spill tracking.
+ n.children = nil
+
+ // Split nodes into appropriate sizes. The first node will always be n.
+ var nodes = n.split(tx.db.pageSize)
+ for _, node := range nodes {
+ // Add node's page to the freelist if it's not new.
+ if node.pgid > 0 {
+ tx.db.freelist.free(tx.meta.txid, tx.page(node.pgid))
+ node.pgid = 0
+ }
+
+ // Allocate contiguous space for the node.
+ p, err := tx.allocate((node.size() / tx.db.pageSize) + 1)
+ if err != nil {
+ return err
+ }
+
+ // Write the node.
+ if p.id >= tx.meta.pgid {
+ panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid))
+ }
+ node.pgid = p.id
+ node.write(p)
+ node.spilled = true
+
+ // Insert into parent inodes.
+ if node.parent != nil {
+ var key = node.key
+ if key == nil {
+ key = node.inodes[0].key
+ }
+
+ node.parent.put(key, node.inodes[0].key, nil, node.pgid, 0)
+ node.key = node.inodes[0].key
+ _assert(len(node.key) > 0, "spill: zero-length node key")
+ }
+
+ // Update the statistics.
+ tx.stats.Spill++
+ }
+
+ // If the root node split and created a new root then we need to spill that
+ // as well. We'll clear out the children to make sure it doesn't try to respill.
+ if n.parent != nil && n.parent.pgid == 0 {
+ n.children = nil
+ return n.parent.spill()
+ }
+
+ return nil
+}
+
+// rebalance attempts to combine the node with sibling nodes if the node fill
+// size is below a threshold or if there are not enough keys.
+func (n *node) rebalance() {
+ if !n.unbalanced {
+ return
+ }
+ n.unbalanced = false
+
+ // Update statistics.
+ n.bucket.tx.stats.Rebalance++
+
+ // Ignore if node is above threshold (25%) and has enough keys.
+ var threshold = n.bucket.tx.db.pageSize / 4
+ if n.size() > threshold && len(n.inodes) > n.minKeys() {
+ return
+ }
+
+ // Root node has special handling.
+ if n.parent == nil {
+ // If root node is a branch and only has one node then collapse it.
+ if !n.isLeaf && len(n.inodes) == 1 {
+ // Move root's child up.
+ child := n.bucket.node(n.inodes[0].pgid, n)
+ n.isLeaf = child.isLeaf
+ n.inodes = child.inodes[:]
+ n.children = child.children
+
+ // Reparent all child nodes being moved.
+ for _, inode := range n.inodes {
+ if child, ok := n.bucket.nodes[inode.pgid]; ok {
+ child.parent = n
+ }
+ }
+
+ // Remove old child.
+ child.parent = nil
+ delete(n.bucket.nodes, child.pgid)
+ child.free()
+ }
+
+ return
+ }
+
+ // If node has no keys then just remove it.
+ if n.numChildren() == 0 {
+ n.parent.del(n.key)
+ n.parent.removeChild(n)
+ delete(n.bucket.nodes, n.pgid)
+ n.free()
+ n.parent.rebalance()
+ return
+ }
+
+ _assert(n.parent.numChildren() > 1, "parent must have at least 2 children")
+
+ // Destination node is right sibling if idx == 0, otherwise left sibling.
+ var target *node
+ var useNextSibling = (n.parent.childIndex(n) == 0)
+ if useNextSibling {
+ target = n.nextSibling()
+ } else {
+ target = n.prevSibling()
+ }
+
+ // If both this node and the target node are too small then merge them.
+ if useNextSibling {
+ // Reparent all child nodes being moved.
+ for _, inode := range target.inodes {
+ if child, ok := n.bucket.nodes[inode.pgid]; ok {
+ child.parent.removeChild(child)
+ child.parent = n
+ child.parent.children = append(child.parent.children, child)
+ }
+ }
+
+ // Copy over inodes from target and remove target.
+ n.inodes = append(n.inodes, target.inodes...)
+ n.parent.del(target.key)
+ n.parent.removeChild(target)
+ delete(n.bucket.nodes, target.pgid)
+ target.free()
+ } else {
+ // Reparent all child nodes being moved.
+ for _, inode := range n.inodes {
+ if child, ok := n.bucket.nodes[inode.pgid]; ok {
+ child.parent.removeChild(child)
+ child.parent = target
+ child.parent.children = append(child.parent.children, child)
+ }
+ }
+
+ // Copy over inodes to target and remove node.
+ target.inodes = append(target.inodes, n.inodes...)
+ n.parent.del(n.key)
+ n.parent.removeChild(n)
+ delete(n.bucket.nodes, n.pgid)
+ n.free()
+ }
+
+ // Either this node or the target node was deleted from the parent so rebalance it.
+ n.parent.rebalance()
+}
+
+// removes a node from the list of in-memory children.
+// This does not affect the inodes.
+func (n *node) removeChild(target *node) {
+ for i, child := range n.children {
+ if child == target {
+ n.children = append(n.children[:i], n.children[i+1:]...)
+ return
+ }
+ }
+}
+
+// dereference causes the node to copy all its inode key/value references to heap memory.
+// This is required when the mmap is reallocated so inodes are not pointing to stale data.
+func (n *node) dereference() {
+ if n.key != nil {
+ key := make([]byte, len(n.key))
+ copy(key, n.key)
+ n.key = key
+ _assert(n.pgid == 0 || len(n.key) > 0, "dereference: zero-length node key on existing node")
+ }
+
+ for i := range n.inodes {
+ inode := &n.inodes[i]
+
+ key := make([]byte, len(inode.key))
+ copy(key, inode.key)
+ inode.key = key
+ _assert(len(inode.key) > 0, "dereference: zero-length inode key")
+
+ value := make([]byte, len(inode.value))
+ copy(value, inode.value)
+ inode.value = value
+ }
+
+ // Recursively dereference children.
+ for _, child := range n.children {
+ child.dereference()
+ }
+
+ // Update statistics.
+ n.bucket.tx.stats.NodeDeref++
+}
+
+// free adds the node's underlying page to the freelist.
+func (n *node) free() {
+ if n.pgid != 0 {
+ n.bucket.tx.db.freelist.free(n.bucket.tx.meta.txid, n.bucket.tx.page(n.pgid))
+ n.pgid = 0
+ }
+}
+
+// dump writes the contents of the node to STDERR for debugging purposes.
+/*
+func (n *node) dump() {
+ // Write node header.
+ var typ = "branch"
+ if n.isLeaf {
+ typ = "leaf"
+ }
+ warnf("[NODE %d {type=%s count=%d}]", n.pgid, typ, len(n.inodes))
+
+ // Write out abbreviated version of each item.
+ for _, item := range n.inodes {
+ if n.isLeaf {
+ if item.flags&bucketLeafFlag != 0 {
+ bucket := (*bucket)(unsafe.Pointer(&item.value[0]))
+ warnf("+L %08x -> (bucket root=%d)", trunc(item.key, 4), bucket.root)
+ } else {
+ warnf("+L %08x -> %08x", trunc(item.key, 4), trunc(item.value, 4))
+ }
+ } else {
+ warnf("+B %08x -> pgid=%d", trunc(item.key, 4), item.pgid)
+ }
+ }
+ warn("")
+}
+*/
+
+type nodes []*node
+
+func (s nodes) Len() int { return len(s) }
+func (s nodes) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s nodes) Less(i, j int) bool { return bytes.Compare(s[i].inodes[0].key, s[j].inodes[0].key) == -1 }
+
+// inode represents an internal node inside of a node.
+// It can be used to point to elements in a page or point
+// to an element which hasn't been added to a page yet.
+type inode struct {
+ flags uint32
+ pgid pgid
+ key []byte
+ value []byte
+}
+
+type inodes []inode
diff --git a/vendor/github.com/coreos/bbolt/page.go b/vendor/github.com/coreos/bbolt/page.go
new file mode 100644
index 00000000..7651a6bf
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/page.go
@@ -0,0 +1,178 @@
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "sort"
+ "unsafe"
+)
+
+const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr))
+
+const minKeysPerPage = 2
+
+const branchPageElementSize = int(unsafe.Sizeof(branchPageElement{}))
+const leafPageElementSize = int(unsafe.Sizeof(leafPageElement{}))
+
+const (
+ branchPageFlag = 0x01
+ leafPageFlag = 0x02
+ metaPageFlag = 0x04
+ freelistPageFlag = 0x10
+)
+
+const (
+ bucketLeafFlag = 0x01
+)
+
+type pgid uint64
+
+type page struct {
+ id pgid
+ flags uint16
+ count uint16
+ overflow uint32
+ ptr uintptr
+}
+
+// typ returns a human readable page type string used for debugging.
+func (p *page) typ() string {
+ if (p.flags & branchPageFlag) != 0 {
+ return "branch"
+ } else if (p.flags & leafPageFlag) != 0 {
+ return "leaf"
+ } else if (p.flags & metaPageFlag) != 0 {
+ return "meta"
+ } else if (p.flags & freelistPageFlag) != 0 {
+ return "freelist"
+ }
+ return fmt.Sprintf("unknown<%02x>", p.flags)
+}
+
+// meta returns a pointer to the metadata section of the page.
+func (p *page) meta() *meta {
+ return (*meta)(unsafe.Pointer(&p.ptr))
+}
+
+// leafPageElement retrieves the leaf node by index
+func (p *page) leafPageElement(index uint16) *leafPageElement {
+ n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
+ return n
+}
+
+// leafPageElements retrieves a list of leaf nodes.
+func (p *page) leafPageElements() []leafPageElement {
+ if p.count == 0 {
+ return nil
+ }
+ return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:]
+}
+
+// branchPageElement retrieves the branch node by index
+func (p *page) branchPageElement(index uint16) *branchPageElement {
+ return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index]
+}
+
+// branchPageElements retrieves a list of branch nodes.
+func (p *page) branchPageElements() []branchPageElement {
+ if p.count == 0 {
+ return nil
+ }
+ return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:]
+}
+
+// dump writes n bytes of the page to STDERR as hex output.
+func (p *page) hexdump(n int) {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:n]
+ fmt.Fprintf(os.Stderr, "%x\n", buf)
+}
+
+type pages []*page
+
+func (s pages) Len() int { return len(s) }
+func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s pages) Less(i, j int) bool { return s[i].id < s[j].id }
+
+// branchPageElement represents a node on a branch page.
+type branchPageElement struct {
+ pos uint32
+ ksize uint32
+ pgid pgid
+}
+
+// key returns a byte slice of the node key.
+func (n *branchPageElement) key() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize]
+}
+
+// leafPageElement represents a node on a leaf page.
+type leafPageElement struct {
+ flags uint32
+ pos uint32
+ ksize uint32
+ vsize uint32
+}
+
+// key returns a byte slice of the node key.
+func (n *leafPageElement) key() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize:n.ksize]
+}
+
+// value returns a byte slice of the node value.
+func (n *leafPageElement) value() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize:n.vsize]
+}
+
+// PageInfo represents human readable information about a page.
+type PageInfo struct {
+ ID int
+ Type string
+ Count int
+ OverflowCount int
+}
+
+type pgids []pgid
+
+func (s pgids) Len() int { return len(s) }
+func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s pgids) Less(i, j int) bool { return s[i] < s[j] }
+
+// merge returns the sorted union of a and b.
+func (a pgids) merge(b pgids) pgids {
+ // Return the opposite slice if one is nil.
+ if len(a) == 0 {
+ return b
+ } else if len(b) == 0 {
+ return a
+ }
+
+ // Create a list to hold all elements from both lists.
+ merged := make(pgids, 0, len(a)+len(b))
+
+ // Assign lead to the slice with a lower starting value, follow to the higher value.
+ lead, follow := a, b
+ if b[0] < a[0] {
+ lead, follow = b, a
+ }
+
+ // Continue while there are elements in the lead.
+ for len(lead) > 0 {
+ // Merge largest prefix of lead that is ahead of follow[0].
+ n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] })
+ merged = append(merged, lead[:n]...)
+ if n >= len(lead) {
+ break
+ }
+
+ // Swap lead and follow.
+ lead, follow = follow, lead[n:]
+ }
+
+ // Append what's left in follow.
+ merged = append(merged, follow...)
+
+ return merged
+}
diff --git a/vendor/github.com/coreos/bbolt/tx.go b/vendor/github.com/coreos/bbolt/tx.go
new file mode 100644
index 00000000..1cfb4cde
--- /dev/null
+++ b/vendor/github.com/coreos/bbolt/tx.go
@@ -0,0 +1,682 @@
+package bolt
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strings"
+ "time"
+ "unsafe"
+)
+
+// txid represents the internal transaction identifier.
+type txid uint64
+
+// Tx represents a read-only or read/write transaction on the database.
+// Read-only transactions can be used for retrieving values for keys and creating cursors.
+// Read/write transactions can create and remove buckets and create and remove keys.
+//
+// IMPORTANT: You must commit or rollback transactions when you are done with
+// them. Pages can not be reclaimed by the writer until no more transactions
+// are using them. A long running read transaction can cause the database to
+// quickly grow.
+type Tx struct {
+ writable bool
+ managed bool
+ db *DB
+ meta *meta
+ root Bucket
+ pages map[pgid]*page
+ stats TxStats
+ commitHandlers []func()
+
+ // WriteFlag specifies the flag for write-related methods like WriteTo().
+ // Tx opens the database file with the specified flag to copy the data.
+ //
+ // By default, the flag is unset, which works well for mostly in-memory
+ // workloads. For databases that are much larger than available RAM,
+ // set the flag to syscall.O_DIRECT to avoid trashing the page cache.
+ WriteFlag int
+}
+
+// init initializes the transaction.
+func (tx *Tx) init(db *DB) {
+ tx.db = db
+ tx.pages = nil
+
+ // Copy the meta page since it can be changed by the writer.
+ tx.meta = &meta{}
+ db.meta().copy(tx.meta)
+
+ // Copy over the root bucket.
+ tx.root = newBucket(tx)
+ tx.root.bucket = &bucket{}
+ *tx.root.bucket = tx.meta.root
+
+ // Increment the transaction id and add a page cache for writable transactions.
+ if tx.writable {
+ tx.pages = make(map[pgid]*page)
+ tx.meta.txid += txid(1)
+ }
+}
+
+// ID returns the transaction id.
+func (tx *Tx) ID() int {
+ return int(tx.meta.txid)
+}
+
+// DB returns a reference to the database that created the transaction.
+func (tx *Tx) DB() *DB {
+ return tx.db
+}
+
+// Size returns current database size in bytes as seen by this transaction.
+func (tx *Tx) Size() int64 {
+ return int64(tx.meta.pgid) * int64(tx.db.pageSize)
+}
+
+// Writable returns whether the transaction can perform write operations.
+func (tx *Tx) Writable() bool {
+ return tx.writable
+}
+
+// Cursor creates a cursor associated with the root bucket.
+// All items in the cursor will return a nil value because all root bucket keys point to buckets.
+// The cursor is only valid as long as the transaction is open.
+// Do not use a cursor after the transaction is closed.
+func (tx *Tx) Cursor() *Cursor {
+ return tx.root.Cursor()
+}
+
+// Stats retrieves a copy of the current transaction statistics.
+func (tx *Tx) Stats() TxStats {
+ return tx.stats
+}
+
+// Bucket retrieves a bucket by name.
+// Returns nil if the bucket does not exist.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (tx *Tx) Bucket(name []byte) *Bucket {
+ return tx.root.Bucket(name)
+}
+
+// CreateBucket creates a new bucket.
+// Returns an error if the bucket already exists, if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (tx *Tx) CreateBucket(name []byte) (*Bucket, error) {
+ return tx.root.CreateBucket(name)
+}
+
+// CreateBucketIfNotExists creates a new bucket if it doesn't already exist.
+// Returns an error if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (tx *Tx) CreateBucketIfNotExists(name []byte) (*Bucket, error) {
+ return tx.root.CreateBucketIfNotExists(name)
+}
+
+// DeleteBucket deletes a bucket.
+// Returns an error if the bucket cannot be found or if the key represents a non-bucket value.
+func (tx *Tx) DeleteBucket(name []byte) error {
+ return tx.root.DeleteBucket(name)
+}
+
+// ForEach executes a function for each bucket in the root.
+// If the provided function returns an error then the iteration is stopped and
+// the error is returned to the caller.
+func (tx *Tx) ForEach(fn func(name []byte, b *Bucket) error) error {
+ return tx.root.ForEach(func(k, v []byte) error {
+ if err := fn(k, tx.root.Bucket(k)); err != nil {
+ return err
+ }
+ return nil
+ })
+}
+
+// OnCommit adds a handler function to be executed after the transaction successfully commits.
+func (tx *Tx) OnCommit(fn func()) {
+ tx.commitHandlers = append(tx.commitHandlers, fn)
+}
+
+// Commit writes all changes to disk and updates the meta page.
+// Returns an error if a disk write error occurs, or if Commit is
+// called on a read-only transaction.
+func (tx *Tx) Commit() error {
+ _assert(!tx.managed, "managed tx commit not allowed")
+ if tx.db == nil {
+ return ErrTxClosed
+ } else if !tx.writable {
+ return ErrTxNotWritable
+ }
+
+ // TODO(benbjohnson): Use vectorized I/O to write out dirty pages.
+
+ // Rebalance nodes which have had deletions.
+ var startTime = time.Now()
+ tx.root.rebalance()
+ if tx.stats.Rebalance > 0 {
+ tx.stats.RebalanceTime += time.Since(startTime)
+ }
+
+ // spill data onto dirty pages.
+ startTime = time.Now()
+ if err := tx.root.spill(); err != nil {
+ tx.rollback()
+ return err
+ }
+ tx.stats.SpillTime += time.Since(startTime)
+
+ // Free the old root bucket.
+ tx.meta.root.root = tx.root.root
+
+ opgid := tx.meta.pgid
+
+ // Free the freelist and allocate new pages for it. This will overestimate
+ // the size of the freelist but not underestimate the size (which would be bad).
+ tx.db.freelist.free(tx.meta.txid, tx.db.page(tx.meta.freelist))
+ p, err := tx.allocate((tx.db.freelist.size() / tx.db.pageSize) + 1)
+ if err != nil {
+ tx.rollback()
+ return err
+ }
+ if err := tx.db.freelist.write(p); err != nil {
+ tx.rollback()
+ return err
+ }
+ tx.meta.freelist = p.id
+
+ // If the high water mark has moved up then attempt to grow the database.
+ if tx.meta.pgid > opgid {
+ if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil {
+ tx.rollback()
+ return err
+ }
+ }
+
+ // Write dirty pages to disk.
+ startTime = time.Now()
+ if err := tx.write(); err != nil {
+ tx.rollback()
+ return err
+ }
+
+ // If strict mode is enabled then perform a consistency check.
+ // Only the first consistency error is reported in the panic.
+ if tx.db.StrictMode {
+ ch := tx.Check()
+ var errs []string
+ for {
+ err, ok := <-ch
+ if !ok {
+ break
+ }
+ errs = append(errs, err.Error())
+ }
+ if len(errs) > 0 {
+ panic("check fail: " + strings.Join(errs, "\n"))
+ }
+ }
+
+ // Write meta to disk.
+ if err := tx.writeMeta(); err != nil {
+ tx.rollback()
+ return err
+ }
+ tx.stats.WriteTime += time.Since(startTime)
+
+ // Finalize the transaction.
+ tx.close()
+
+ // Execute commit handlers now that the locks have been removed.
+ for _, fn := range tx.commitHandlers {
+ fn()
+ }
+
+ return nil
+}
+
+// Rollback closes the transaction and ignores all previous updates. Read-only
+// transactions must be rolled back and not committed.
+func (tx *Tx) Rollback() error {
+ _assert(!tx.managed, "managed tx rollback not allowed")
+ if tx.db == nil {
+ return ErrTxClosed
+ }
+ tx.rollback()
+ return nil
+}
+
+func (tx *Tx) rollback() {
+ if tx.db == nil {
+ return
+ }
+ if tx.writable {
+ tx.db.freelist.rollback(tx.meta.txid)
+ tx.db.freelist.reload(tx.db.page(tx.db.meta().freelist))
+ }
+ tx.close()
+}
+
+func (tx *Tx) close() {
+ if tx.db == nil {
+ return
+ }
+ if tx.writable {
+ // Grab freelist stats.
+ var freelistFreeN = tx.db.freelist.free_count()
+ var freelistPendingN = tx.db.freelist.pending_count()
+ var freelistAlloc = tx.db.freelist.size()
+
+ // Remove transaction ref & writer lock.
+ tx.db.rwtx = nil
+ tx.db.rwlock.Unlock()
+
+ // Merge statistics.
+ tx.db.statlock.Lock()
+ tx.db.stats.FreePageN = freelistFreeN
+ tx.db.stats.PendingPageN = freelistPendingN
+ tx.db.stats.FreeAlloc = (freelistFreeN + freelistPendingN) * tx.db.pageSize
+ tx.db.stats.FreelistInuse = freelistAlloc
+ tx.db.stats.TxStats.add(&tx.stats)
+ tx.db.statlock.Unlock()
+ } else {
+ tx.db.removeTx(tx)
+ }
+
+ // Clear all references.
+ tx.db = nil
+ tx.meta = nil
+ tx.root = Bucket{tx: tx}
+ tx.pages = nil
+}
+
+// Copy writes the entire database to a writer.
+// This function exists for backwards compatibility. Use WriteTo() instead.
+func (tx *Tx) Copy(w io.Writer) error {
+ _, err := tx.WriteTo(w)
+ return err
+}
+
+// WriteTo writes the entire database to a writer.
+// If err == nil then exactly tx.Size() bytes will be written into the writer.
+func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
+ // Attempt to open reader with WriteFlag
+ f, err := os.OpenFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0)
+ if err != nil {
+ return 0, err
+ }
+ defer func() { _ = f.Close() }()
+
+ // Generate a meta page. We use the same page data for both meta pages.
+ buf := make([]byte, tx.db.pageSize)
+ page := (*page)(unsafe.Pointer(&buf[0]))
+ page.flags = metaPageFlag
+ *page.meta() = *tx.meta
+
+ // Write meta 0.
+ page.id = 0
+ page.meta().checksum = page.meta().sum64()
+ nn, err := w.Write(buf)
+ n += int64(nn)
+ if err != nil {
+ return n, fmt.Errorf("meta 0 copy: %s", err)
+ }
+
+ // Write meta 1 with a lower transaction id.
+ page.id = 1
+ page.meta().txid -= 1
+ page.meta().checksum = page.meta().sum64()
+ nn, err = w.Write(buf)
+ n += int64(nn)
+ if err != nil {
+ return n, fmt.Errorf("meta 1 copy: %s", err)
+ }
+
+ // Move past the meta pages in the file.
+ if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil {
+ return n, fmt.Errorf("seek: %s", err)
+ }
+
+ // Copy data pages.
+ wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2))
+ n += wn
+ if err != nil {
+ return n, err
+ }
+
+ return n, f.Close()
+}
+
+// CopyFile copies the entire database to file at the given path.
+// A reader transaction is maintained during the copy so it is safe to continue
+// using the database while a copy is in progress.
+func (tx *Tx) CopyFile(path string, mode os.FileMode) error {
+ f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
+ if err != nil {
+ return err
+ }
+
+ err = tx.Copy(f)
+ if err != nil {
+ _ = f.Close()
+ return err
+ }
+ return f.Close()
+}
+
+// Check performs several consistency checks on the database for this transaction.
+// An error is returned if any inconsistency is found.
+//
+// It can be safely run concurrently on a writable transaction. However, this
+// incurs a high cost for large databases and databases with a lot of subbuckets
+// because of caching. This overhead can be removed if running on a read-only
+// transaction, however, it is not safe to execute other writer transactions at
+// the same time.
+func (tx *Tx) Check() <-chan error {
+ ch := make(chan error)
+ go tx.check(ch)
+ return ch
+}
+
+func (tx *Tx) check(ch chan error) {
+ // Check if any pages are double freed.
+ freed := make(map[pgid]bool)
+ for _, id := range tx.db.freelist.all() {
+ if freed[id] {
+ ch <- fmt.Errorf("page %d: already freed", id)
+ }
+ freed[id] = true
+ }
+
+ // Track every reachable page.
+ reachable := make(map[pgid]*page)
+ reachable[0] = tx.page(0) // meta0
+ reachable[1] = tx.page(1) // meta1
+ for i := uint32(0); i <= tx.page(tx.meta.freelist).overflow; i++ {
+ reachable[tx.meta.freelist+pgid(i)] = tx.page(tx.meta.freelist)
+ }
+
+ // Recursively check buckets.
+ tx.checkBucket(&tx.root, reachable, freed, ch)
+
+ // Ensure all pages below high water mark are either reachable or freed.
+ for i := pgid(0); i < tx.meta.pgid; i++ {
+ _, isReachable := reachable[i]
+ if !isReachable && !freed[i] {
+ ch <- fmt.Errorf("page %d: unreachable unfreed", int(i))
+ }
+ }
+
+ // Close the channel to signal completion.
+ close(ch)
+}
+
+func (tx *Tx) checkBucket(b *Bucket, reachable map[pgid]*page, freed map[pgid]bool, ch chan error) {
+ // Ignore inline buckets.
+ if b.root == 0 {
+ return
+ }
+
+ // Check every page used by this bucket.
+ b.tx.forEachPage(b.root, 0, func(p *page, _ int) {
+ if p.id > tx.meta.pgid {
+ ch <- fmt.Errorf("page %d: out of bounds: %d", int(p.id), int(b.tx.meta.pgid))
+ }
+
+ // Ensure each page is only referenced once.
+ for i := pgid(0); i <= pgid(p.overflow); i++ {
+ var id = p.id + i
+ if _, ok := reachable[id]; ok {
+ ch <- fmt.Errorf("page %d: multiple references", int(id))
+ }
+ reachable[id] = p
+ }
+
+ // We should only encounter un-freed leaf and branch pages.
+ if freed[p.id] {
+ ch <- fmt.Errorf("page %d: reachable freed", int(p.id))
+ } else if (p.flags&branchPageFlag) == 0 && (p.flags&leafPageFlag) == 0 {
+ ch <- fmt.Errorf("page %d: invalid type: %s", int(p.id), p.typ())
+ }
+ })
+
+ // Check each bucket within this bucket.
+ _ = b.ForEach(func(k, v []byte) error {
+ if child := b.Bucket(k); child != nil {
+ tx.checkBucket(child, reachable, freed, ch)
+ }
+ return nil
+ })
+}
+
+// allocate returns a contiguous block of memory starting at a given page.
+func (tx *Tx) allocate(count int) (*page, error) {
+ p, err := tx.db.allocate(count)
+ if err != nil {
+ return nil, err
+ }
+
+ // Save to our page cache.
+ tx.pages[p.id] = p
+
+ // Update statistics.
+ tx.stats.PageCount++
+ tx.stats.PageAlloc += count * tx.db.pageSize
+
+ return p, nil
+}
+
+// write writes any dirty pages to disk.
+func (tx *Tx) write() error {
+ // Sort pages by id.
+ pages := make(pages, 0, len(tx.pages))
+ for _, p := range tx.pages {
+ pages = append(pages, p)
+ }
+ // Clear out page cache early.
+ tx.pages = make(map[pgid]*page)
+ sort.Sort(pages)
+
+ // Write pages to disk in order.
+ for _, p := range pages {
+ size := (int(p.overflow) + 1) * tx.db.pageSize
+ offset := int64(p.id) * int64(tx.db.pageSize)
+
+ // Write out page in "max allocation" sized chunks.
+ ptr := (*[maxAllocSize]byte)(unsafe.Pointer(p))
+ for {
+ // Limit our write to our max allocation size.
+ sz := size
+ if sz > maxAllocSize-1 {
+ sz = maxAllocSize - 1
+ }
+
+ // Write chunk to disk.
+ buf := ptr[:sz]
+ if _, err := tx.db.ops.writeAt(buf, offset); err != nil {
+ return err
+ }
+
+ // Update statistics.
+ tx.stats.Write++
+
+ // Exit inner for loop if we've written all the chunks.
+ size -= sz
+ if size == 0 {
+ break
+ }
+
+ // Otherwise move offset forward and move pointer to next chunk.
+ offset += int64(sz)
+ ptr = (*[maxAllocSize]byte)(unsafe.Pointer(&ptr[sz]))
+ }
+ }
+
+ // Ignore file sync if flag is set on DB.
+ if !tx.db.NoSync || IgnoreNoSync {
+ if err := fdatasync(tx.db); err != nil {
+ return err
+ }
+ }
+
+ // Put small pages back to page pool.
+ for _, p := range pages {
+ // Ignore page sizes over 1 page.
+ // These are allocated using make() instead of the page pool.
+ if int(p.overflow) != 0 {
+ continue
+ }
+
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:tx.db.pageSize]
+
+ // See https://go.googlesource.com/go/+/f03c9202c43e0abb130669852082117ca50aa9b1
+ for i := range buf {
+ buf[i] = 0
+ }
+ tx.db.pagePool.Put(buf)
+ }
+
+ return nil
+}
+
+// writeMeta writes the meta to the disk.
+func (tx *Tx) writeMeta() error {
+ // Create a temporary buffer for the meta page.
+ buf := make([]byte, tx.db.pageSize)
+ p := tx.db.pageInBuffer(buf, 0)
+ tx.meta.write(p)
+
+ // Write the meta page to file.
+ if _, err := tx.db.ops.writeAt(buf, int64(p.id)*int64(tx.db.pageSize)); err != nil {
+ return err
+ }
+ if !tx.db.NoSync || IgnoreNoSync {
+ if err := fdatasync(tx.db); err != nil {
+ return err
+ }
+ }
+
+ // Update statistics.
+ tx.stats.Write++
+
+ return nil
+}
+
+// page returns a reference to the page with a given id.
+// If page has been written to then a temporary buffered page is returned.
+func (tx *Tx) page(id pgid) *page {
+ // Check the dirty pages first.
+ if tx.pages != nil {
+ if p, ok := tx.pages[id]; ok {
+ return p
+ }
+ }
+
+ // Otherwise return directly from the mmap.
+ return tx.db.page(id)
+}
+
+// forEachPage iterates over every page within a given page and executes a function.
+func (tx *Tx) forEachPage(pgid pgid, depth int, fn func(*page, int)) {
+ p := tx.page(pgid)
+
+ // Execute function.
+ fn(p, depth)
+
+ // Recursively loop over children.
+ if (p.flags & branchPageFlag) != 0 {
+ for i := 0; i < int(p.count); i++ {
+ elem := p.branchPageElement(uint16(i))
+ tx.forEachPage(elem.pgid, depth+1, fn)
+ }
+ }
+}
+
+// Page returns page information for a given page number.
+// This is only safe for concurrent use when used by a writable transaction.
+func (tx *Tx) Page(id int) (*PageInfo, error) {
+ if tx.db == nil {
+ return nil, ErrTxClosed
+ } else if pgid(id) >= tx.meta.pgid {
+ return nil, nil
+ }
+
+ // Build the page info.
+ p := tx.db.page(pgid(id))
+ info := &PageInfo{
+ ID: id,
+ Count: int(p.count),
+ OverflowCount: int(p.overflow),
+ }
+
+ // Determine the type (or if it's free).
+ if tx.db.freelist.freed(pgid(id)) {
+ info.Type = "free"
+ } else {
+ info.Type = p.typ()
+ }
+
+ return info, nil
+}
+
+// TxStats represents statistics about the actions performed by the transaction.
+type TxStats struct {
+ // Page statistics.
+ PageCount int // number of page allocations
+ PageAlloc int // total bytes allocated
+
+ // Cursor statistics.
+ CursorCount int // number of cursors created
+
+ // Node statistics
+ NodeCount int // number of node allocations
+ NodeDeref int // number of node dereferences
+
+ // Rebalance statistics.
+ Rebalance int // number of node rebalances
+ RebalanceTime time.Duration // total time spent rebalancing
+
+ // Split/Spill statistics.
+ Split int // number of nodes split
+ Spill int // number of nodes spilled
+ SpillTime time.Duration // total time spent spilling
+
+ // Write statistics.
+ Write int // number of writes performed
+ WriteTime time.Duration // total time spent writing to disk
+}
+
+func (s *TxStats) add(other *TxStats) {
+ s.PageCount += other.PageCount
+ s.PageAlloc += other.PageAlloc
+ s.CursorCount += other.CursorCount
+ s.NodeCount += other.NodeCount
+ s.NodeDeref += other.NodeDeref
+ s.Rebalance += other.Rebalance
+ s.RebalanceTime += other.RebalanceTime
+ s.Split += other.Split
+ s.Spill += other.Spill
+ s.SpillTime += other.SpillTime
+ s.Write += other.Write
+ s.WriteTime += other.WriteTime
+}
+
+// Sub calculates and returns the difference between two sets of transaction stats.
+// This is useful when obtaining stats at two different points and time and
+// you need the performance counters that occurred within that time span.
+func (s *TxStats) Sub(other *TxStats) TxStats {
+ var diff TxStats
+ diff.PageCount = s.PageCount - other.PageCount
+ diff.PageAlloc = s.PageAlloc - other.PageAlloc
+ diff.CursorCount = s.CursorCount - other.CursorCount
+ diff.NodeCount = s.NodeCount - other.NodeCount
+ diff.NodeDeref = s.NodeDeref - other.NodeDeref
+ diff.Rebalance = s.Rebalance - other.Rebalance
+ diff.RebalanceTime = s.RebalanceTime - other.RebalanceTime
+ diff.Split = s.Split - other.Split
+ diff.Spill = s.Spill - other.Spill
+ diff.SpillTime = s.SpillTime - other.SpillTime
+ diff.Write = s.Write - other.Write
+ diff.WriteTime = s.WriteTime - other.WriteTime
+ return diff
+}
diff --git a/vendor/github.com/coreos/etcd/Documentation/README.md b/vendor/github.com/coreos/etcd/Documentation/README.md
new file mode 120000
index 00000000..8828313f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/Documentation/README.md
@@ -0,0 +1 @@
+docs.md
\ No newline at end of file
diff --git a/vendor/github.com/coreos/etcd/LICENSE b/vendor/github.com/coreos/etcd/LICENSE
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/coreos/etcd/NOTICE b/vendor/github.com/coreos/etcd/NOTICE
new file mode 100644
index 00000000..b39ddfa5
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/NOTICE
@@ -0,0 +1,5 @@
+CoreOS Project
+Copyright 2014 CoreOS, Inc
+
+This product includes software developed at CoreOS, Inc.
+(http://www.coreos.com/).
diff --git a/vendor/github.com/coreos/etcd/alarm/alarms.go b/vendor/github.com/coreos/etcd/alarm/alarms.go
new file mode 100644
index 00000000..4f0ebe93
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/alarm/alarms.go
@@ -0,0 +1,152 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package alarm manages health status alarms in etcd.
+package alarm
+
+import (
+ "sync"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ alarmBucketName = []byte("alarm")
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "alarm")
+)
+
+type BackendGetter interface {
+ Backend() backend.Backend
+}
+
+type alarmSet map[types.ID]*pb.AlarmMember
+
+// AlarmStore persists alarms to the backend.
+type AlarmStore struct {
+ mu sync.Mutex
+ types map[pb.AlarmType]alarmSet
+
+ bg BackendGetter
+}
+
+func NewAlarmStore(bg BackendGetter) (*AlarmStore, error) {
+ ret := &AlarmStore{types: make(map[pb.AlarmType]alarmSet), bg: bg}
+ err := ret.restore()
+ return ret, err
+}
+
+func (a *AlarmStore) Activate(id types.ID, at pb.AlarmType) *pb.AlarmMember {
+ a.mu.Lock()
+ defer a.mu.Unlock()
+
+ newAlarm := &pb.AlarmMember{MemberID: uint64(id), Alarm: at}
+ if m := a.addToMap(newAlarm); m != newAlarm {
+ return m
+ }
+
+ v, err := newAlarm.Marshal()
+ if err != nil {
+ plog.Panicf("failed to marshal alarm member")
+ }
+
+ b := a.bg.Backend()
+ b.BatchTx().Lock()
+ b.BatchTx().UnsafePut(alarmBucketName, v, nil)
+ b.BatchTx().Unlock()
+
+ return newAlarm
+}
+
+func (a *AlarmStore) Deactivate(id types.ID, at pb.AlarmType) *pb.AlarmMember {
+ a.mu.Lock()
+ defer a.mu.Unlock()
+
+ t := a.types[at]
+ if t == nil {
+ t = make(alarmSet)
+ a.types[at] = t
+ }
+ m := t[id]
+ if m == nil {
+ return nil
+ }
+
+ delete(t, id)
+
+ v, err := m.Marshal()
+ if err != nil {
+ plog.Panicf("failed to marshal alarm member")
+ }
+
+ b := a.bg.Backend()
+ b.BatchTx().Lock()
+ b.BatchTx().UnsafeDelete(alarmBucketName, v)
+ b.BatchTx().Unlock()
+
+ return m
+}
+
+func (a *AlarmStore) Get(at pb.AlarmType) (ret []*pb.AlarmMember) {
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if at == pb.AlarmType_NONE {
+ for _, t := range a.types {
+ for _, m := range t {
+ ret = append(ret, m)
+ }
+ }
+ return ret
+ }
+ for _, m := range a.types[at] {
+ ret = append(ret, m)
+ }
+ return ret
+}
+
+func (a *AlarmStore) restore() error {
+ b := a.bg.Backend()
+ tx := b.BatchTx()
+
+ tx.Lock()
+ tx.UnsafeCreateBucket(alarmBucketName)
+ err := tx.UnsafeForEach(alarmBucketName, func(k, v []byte) error {
+ var m pb.AlarmMember
+ if err := m.Unmarshal(k); err != nil {
+ return err
+ }
+ a.addToMap(&m)
+ return nil
+ })
+ tx.Unlock()
+
+ b.ForceCommit()
+ return err
+}
+
+func (a *AlarmStore) addToMap(newAlarm *pb.AlarmMember) *pb.AlarmMember {
+ t := a.types[newAlarm.Alarm]
+ if t == nil {
+ t = make(alarmSet)
+ a.types[newAlarm.Alarm] = t
+ }
+ m := t[types.ID(newAlarm.MemberID)]
+ if m != nil {
+ return m
+ }
+ t[types.ID(newAlarm.MemberID)] = newAlarm
+ return newAlarm
+}
diff --git a/vendor/github.com/coreos/etcd/auth/authpb/auth.pb.go b/vendor/github.com/coreos/etcd/auth/authpb/auth.pb.go
new file mode 100644
index 00000000..1a940c39
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/auth/authpb/auth.pb.go
@@ -0,0 +1,807 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: auth.proto
+
+/*
+ Package authpb is a generated protocol buffer package.
+
+ It is generated from these files:
+ auth.proto
+
+ It has these top-level messages:
+ User
+ Permission
+ Role
+*/
+package authpb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Permission_Type int32
+
+const (
+ READ Permission_Type = 0
+ WRITE Permission_Type = 1
+ READWRITE Permission_Type = 2
+)
+
+var Permission_Type_name = map[int32]string{
+ 0: "READ",
+ 1: "WRITE",
+ 2: "READWRITE",
+}
+var Permission_Type_value = map[string]int32{
+ "READ": 0,
+ "WRITE": 1,
+ "READWRITE": 2,
+}
+
+func (x Permission_Type) String() string {
+ return proto.EnumName(Permission_Type_name, int32(x))
+}
+func (Permission_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptorAuth, []int{1, 0} }
+
+// User is a single entry in the bucket authUsers
+type User struct {
+ Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Password []byte `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+ Roles []string `protobuf:"bytes,3,rep,name=roles" json:"roles,omitempty"`
+}
+
+func (m *User) Reset() { *m = User{} }
+func (m *User) String() string { return proto.CompactTextString(m) }
+func (*User) ProtoMessage() {}
+func (*User) Descriptor() ([]byte, []int) { return fileDescriptorAuth, []int{0} }
+
+// Permission is a single entity
+type Permission struct {
+ PermType Permission_Type `protobuf:"varint,1,opt,name=permType,proto3,enum=authpb.Permission_Type" json:"permType,omitempty"`
+ Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
+ RangeEnd []byte `protobuf:"bytes,3,opt,name=range_end,json=rangeEnd,proto3" json:"range_end,omitempty"`
+}
+
+func (m *Permission) Reset() { *m = Permission{} }
+func (m *Permission) String() string { return proto.CompactTextString(m) }
+func (*Permission) ProtoMessage() {}
+func (*Permission) Descriptor() ([]byte, []int) { return fileDescriptorAuth, []int{1} }
+
+// Role is a single entry in the bucket authRoles
+type Role struct {
+ Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ KeyPermission []*Permission `protobuf:"bytes,2,rep,name=keyPermission" json:"keyPermission,omitempty"`
+}
+
+func (m *Role) Reset() { *m = Role{} }
+func (m *Role) String() string { return proto.CompactTextString(m) }
+func (*Role) ProtoMessage() {}
+func (*Role) Descriptor() ([]byte, []int) { return fileDescriptorAuth, []int{2} }
+
+func init() {
+ proto.RegisterType((*User)(nil), "authpb.User")
+ proto.RegisterType((*Permission)(nil), "authpb.Permission")
+ proto.RegisterType((*Role)(nil), "authpb.Role")
+ proto.RegisterEnum("authpb.Permission_Type", Permission_Type_name, Permission_Type_value)
+}
+func (m *User) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *User) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintAuth(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.Password) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintAuth(dAtA, i, uint64(len(m.Password)))
+ i += copy(dAtA[i:], m.Password)
+ }
+ if len(m.Roles) > 0 {
+ for _, s := range m.Roles {
+ dAtA[i] = 0x1a
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func (m *Permission) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Permission) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.PermType != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintAuth(dAtA, i, uint64(m.PermType))
+ }
+ if len(m.Key) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintAuth(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if len(m.RangeEnd) > 0 {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintAuth(dAtA, i, uint64(len(m.RangeEnd)))
+ i += copy(dAtA[i:], m.RangeEnd)
+ }
+ return i, nil
+}
+
+func (m *Role) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Role) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintAuth(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.KeyPermission) > 0 {
+ for _, msg := range m.KeyPermission {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintAuth(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func encodeVarintAuth(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *User) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovAuth(uint64(l))
+ }
+ l = len(m.Password)
+ if l > 0 {
+ n += 1 + l + sovAuth(uint64(l))
+ }
+ if len(m.Roles) > 0 {
+ for _, s := range m.Roles {
+ l = len(s)
+ n += 1 + l + sovAuth(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *Permission) Size() (n int) {
+ var l int
+ _ = l
+ if m.PermType != 0 {
+ n += 1 + sovAuth(uint64(m.PermType))
+ }
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovAuth(uint64(l))
+ }
+ l = len(m.RangeEnd)
+ if l > 0 {
+ n += 1 + l + sovAuth(uint64(l))
+ }
+ return n
+}
+
+func (m *Role) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovAuth(uint64(l))
+ }
+ if len(m.KeyPermission) > 0 {
+ for _, e := range m.KeyPermission {
+ l = e.Size()
+ n += 1 + l + sovAuth(uint64(l))
+ }
+ }
+ return n
+}
+
+func sovAuth(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozAuth(x uint64) (n int) {
+ return sovAuth(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *User) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: User: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: User: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthAuth
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = append(m.Name[:0], dAtA[iNdEx:postIndex]...)
+ if m.Name == nil {
+ m.Name = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthAuth
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Password = append(m.Password[:0], dAtA[iNdEx:postIndex]...)
+ if m.Password == nil {
+ m.Password = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthAuth
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Roles = append(m.Roles, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipAuth(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthAuth
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Permission) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Permission: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Permission: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PermType", wireType)
+ }
+ m.PermType = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.PermType |= (Permission_Type(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthAuth
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RangeEnd", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthAuth
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.RangeEnd = append(m.RangeEnd[:0], dAtA[iNdEx:postIndex]...)
+ if m.RangeEnd == nil {
+ m.RangeEnd = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipAuth(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthAuth
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Role) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Role: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Role: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthAuth
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = append(m.Name[:0], dAtA[iNdEx:postIndex]...)
+ if m.Name == nil {
+ m.Name = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field KeyPermission", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthAuth
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.KeyPermission = append(m.KeyPermission, &Permission{})
+ if err := m.KeyPermission[len(m.KeyPermission)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipAuth(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthAuth
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipAuth(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthAuth
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowAuth
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipAuth(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthAuth = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowAuth = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("auth.proto", fileDescriptorAuth) }
+
+var fileDescriptorAuth = []byte{
+ // 288 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xc1, 0x4a, 0xc3, 0x30,
+ 0x1c, 0xc6, 0x9b, 0xb6, 0x1b, 0xed, 0x5f, 0x27, 0x25, 0x0c, 0x0c, 0x13, 0x42, 0xe9, 0xa9, 0x78,
+ 0xa8, 0xb0, 0x5d, 0xbc, 0x2a, 0xf6, 0x20, 0x78, 0x90, 0x50, 0xf1, 0x28, 0x1d, 0x0d, 0x75, 0x6c,
+ 0x6d, 0x4a, 0x32, 0x91, 0xbe, 0x89, 0x07, 0x1f, 0x68, 0xc7, 0x3d, 0x82, 0xab, 0x2f, 0x22, 0x4d,
+ 0x64, 0x43, 0xdc, 0xed, 0xfb, 0xbe, 0xff, 0x97, 0xe4, 0x97, 0x3f, 0x40, 0xfe, 0xb6, 0x7e, 0x4d,
+ 0x1a, 0x29, 0xd6, 0x02, 0x0f, 0x7b, 0xdd, 0xcc, 0x27, 0xe3, 0x52, 0x94, 0x42, 0x47, 0x57, 0xbd,
+ 0x32, 0xd3, 0xe8, 0x01, 0xdc, 0x27, 0xc5, 0x25, 0xc6, 0xe0, 0xd6, 0x79, 0xc5, 0x09, 0x0a, 0x51,
+ 0x7c, 0xca, 0xb4, 0xc6, 0x13, 0xf0, 0x9a, 0x5c, 0xa9, 0x77, 0x21, 0x0b, 0x62, 0xeb, 0x7c, 0xef,
+ 0xf1, 0x18, 0x06, 0x52, 0xac, 0xb8, 0x22, 0x4e, 0xe8, 0xc4, 0x3e, 0x33, 0x26, 0xfa, 0x44, 0x00,
+ 0x8f, 0x5c, 0x56, 0x0b, 0xa5, 0x16, 0xa2, 0xc6, 0x33, 0xf0, 0x1a, 0x2e, 0xab, 0xac, 0x6d, 0xcc,
+ 0xc5, 0x67, 0xd3, 0xf3, 0xc4, 0xd0, 0x24, 0x87, 0x56, 0xd2, 0x8f, 0xd9, 0xbe, 0x88, 0x03, 0x70,
+ 0x96, 0xbc, 0xfd, 0x7d, 0xb0, 0x97, 0xf8, 0x02, 0x7c, 0x99, 0xd7, 0x25, 0x7f, 0xe1, 0x75, 0x41,
+ 0x1c, 0x03, 0xa2, 0x83, 0xb4, 0x2e, 0xa2, 0x4b, 0x70, 0xf5, 0x31, 0x0f, 0x5c, 0x96, 0xde, 0xdc,
+ 0x05, 0x16, 0xf6, 0x61, 0xf0, 0xcc, 0xee, 0xb3, 0x34, 0x40, 0x78, 0x04, 0x7e, 0x1f, 0x1a, 0x6b,
+ 0x47, 0x19, 0xb8, 0x4c, 0xac, 0xf8, 0xd1, 0xcf, 0x5e, 0xc3, 0x68, 0xc9, 0xdb, 0x03, 0x16, 0xb1,
+ 0x43, 0x27, 0x3e, 0x99, 0xe2, 0xff, 0xc0, 0xec, 0x6f, 0xf1, 0x96, 0x6c, 0x76, 0xd4, 0xda, 0xee,
+ 0xa8, 0xb5, 0xe9, 0x28, 0xda, 0x76, 0x14, 0x7d, 0x75, 0x14, 0x7d, 0x7c, 0x53, 0x6b, 0x3e, 0xd4,
+ 0x3b, 0x9e, 0xfd, 0x04, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x76, 0x8d, 0x4f, 0x8f, 0x01, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/auth/doc.go b/vendor/github.com/coreos/etcd/auth/doc.go
new file mode 100644
index 00000000..72741a10
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/auth/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package auth provides client role authentication for accessing keys in etcd.
+package auth
diff --git a/vendor/github.com/coreos/etcd/auth/jwt.go b/vendor/github.com/coreos/etcd/auth/jwt.go
new file mode 100644
index 00000000..99b2d6b5
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/auth/jwt.go
@@ -0,0 +1,139 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package auth
+
+import (
+ "context"
+ "crypto/rsa"
+ "io/ioutil"
+
+ jwt "github.com/dgrijalva/jwt-go"
+)
+
+type tokenJWT struct {
+ signMethod string
+ signKey *rsa.PrivateKey
+ verifyKey *rsa.PublicKey
+}
+
+func (t *tokenJWT) enable() {}
+func (t *tokenJWT) disable() {}
+func (t *tokenJWT) invalidateUser(string) {}
+func (t *tokenJWT) genTokenPrefix() (string, error) { return "", nil }
+
+func (t *tokenJWT) info(ctx context.Context, token string, rev uint64) (*AuthInfo, bool) {
+ // rev isn't used in JWT, it is only used in simple token
+ var (
+ username string
+ revision uint64
+ )
+
+ parsed, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
+ return t.verifyKey, nil
+ })
+
+ switch err.(type) {
+ case nil:
+ if !parsed.Valid {
+ plog.Warningf("invalid jwt token: %s", token)
+ return nil, false
+ }
+
+ claims := parsed.Claims.(jwt.MapClaims)
+
+ username = claims["username"].(string)
+ revision = uint64(claims["revision"].(float64))
+ default:
+ plog.Warningf("failed to parse jwt token: %s", err)
+ return nil, false
+ }
+
+ return &AuthInfo{Username: username, Revision: revision}, true
+}
+
+func (t *tokenJWT) assign(ctx context.Context, username string, revision uint64) (string, error) {
+ // Future work: let a jwt token include permission information would be useful for
+ // permission checking in proxy side.
+ tk := jwt.NewWithClaims(jwt.GetSigningMethod(t.signMethod),
+ jwt.MapClaims{
+ "username": username,
+ "revision": revision,
+ })
+
+ token, err := tk.SignedString(t.signKey)
+ if err != nil {
+ plog.Debugf("failed to sign jwt token: %s", err)
+ return "", err
+ }
+
+ plog.Debugf("jwt token: %s", token)
+
+ return token, err
+}
+
+func prepareOpts(opts map[string]string) (jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath string, err error) {
+ for k, v := range opts {
+ switch k {
+ case "sign-method":
+ jwtSignMethod = v
+ case "pub-key":
+ jwtPubKeyPath = v
+ case "priv-key":
+ jwtPrivKeyPath = v
+ default:
+ plog.Errorf("unknown token specific option: %s", k)
+ return "", "", "", ErrInvalidAuthOpts
+ }
+ }
+ if len(jwtSignMethod) == 0 {
+ return "", "", "", ErrInvalidAuthOpts
+ }
+ return jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath, nil
+}
+
+func newTokenProviderJWT(opts map[string]string) (*tokenJWT, error) {
+ jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath, err := prepareOpts(opts)
+ if err != nil {
+ return nil, ErrInvalidAuthOpts
+ }
+
+ t := &tokenJWT{}
+
+ t.signMethod = jwtSignMethod
+
+ verifyBytes, err := ioutil.ReadFile(jwtPubKeyPath)
+ if err != nil {
+ plog.Errorf("failed to read public key (%s) for jwt: %s", jwtPubKeyPath, err)
+ return nil, err
+ }
+ t.verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes)
+ if err != nil {
+ plog.Errorf("failed to parse public key (%s): %s", jwtPubKeyPath, err)
+ return nil, err
+ }
+
+ signBytes, err := ioutil.ReadFile(jwtPrivKeyPath)
+ if err != nil {
+ plog.Errorf("failed to read private key (%s) for jwt: %s", jwtPrivKeyPath, err)
+ return nil, err
+ }
+ t.signKey, err = jwt.ParseRSAPrivateKeyFromPEM(signBytes)
+ if err != nil {
+ plog.Errorf("failed to parse private key (%s): %s", jwtPrivKeyPath, err)
+ return nil, err
+ }
+
+ return t, nil
+}
diff --git a/vendor/github.com/coreos/etcd/auth/nop.go b/vendor/github.com/coreos/etcd/auth/nop.go
new file mode 100644
index 00000000..d4378747
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/auth/nop.go
@@ -0,0 +1,35 @@
+// Copyright 2018 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package auth
+
+import (
+ "context"
+)
+
+type tokenNop struct{}
+
+func (t *tokenNop) enable() {}
+func (t *tokenNop) disable() {}
+func (t *tokenNop) invalidateUser(string) {}
+func (t *tokenNop) genTokenPrefix() (string, error) { return "", nil }
+func (t *tokenNop) info(ctx context.Context, token string, rev uint64) (*AuthInfo, bool) {
+ return nil, false
+}
+func (t *tokenNop) assign(ctx context.Context, username string, revision uint64) (string, error) {
+ return "", ErrAuthFailed
+}
+func newTokenProviderNop() (*tokenNop, error) {
+ return &tokenNop{}, nil
+}
diff --git a/vendor/github.com/coreos/etcd/auth/range_perm_cache.go b/vendor/github.com/coreos/etcd/auth/range_perm_cache.go
new file mode 100644
index 00000000..691b65ba
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/auth/range_perm_cache.go
@@ -0,0 +1,133 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package auth
+
+import (
+ "github.com/coreos/etcd/auth/authpb"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/pkg/adt"
+)
+
+func getMergedPerms(tx backend.BatchTx, userName string) *unifiedRangePermissions {
+ user := getUser(tx, userName)
+ if user == nil {
+ plog.Errorf("invalid user name %s", userName)
+ return nil
+ }
+
+ readPerms := &adt.IntervalTree{}
+ writePerms := &adt.IntervalTree{}
+
+ for _, roleName := range user.Roles {
+ role := getRole(tx, roleName)
+ if role == nil {
+ continue
+ }
+
+ for _, perm := range role.KeyPermission {
+ var ivl adt.Interval
+ var rangeEnd []byte
+
+ if len(perm.RangeEnd) != 1 || perm.RangeEnd[0] != 0 {
+ rangeEnd = perm.RangeEnd
+ }
+
+ if len(perm.RangeEnd) != 0 {
+ ivl = adt.NewBytesAffineInterval(perm.Key, rangeEnd)
+ } else {
+ ivl = adt.NewBytesAffinePoint(perm.Key)
+ }
+
+ switch perm.PermType {
+ case authpb.READWRITE:
+ readPerms.Insert(ivl, struct{}{})
+ writePerms.Insert(ivl, struct{}{})
+
+ case authpb.READ:
+ readPerms.Insert(ivl, struct{}{})
+
+ case authpb.WRITE:
+ writePerms.Insert(ivl, struct{}{})
+ }
+ }
+ }
+
+ return &unifiedRangePermissions{
+ readPerms: readPerms,
+ writePerms: writePerms,
+ }
+}
+
+func checkKeyInterval(cachedPerms *unifiedRangePermissions, key, rangeEnd []byte, permtyp authpb.Permission_Type) bool {
+ if len(rangeEnd) == 1 && rangeEnd[0] == 0 {
+ rangeEnd = nil
+ }
+
+ ivl := adt.NewBytesAffineInterval(key, rangeEnd)
+ switch permtyp {
+ case authpb.READ:
+ return cachedPerms.readPerms.Contains(ivl)
+ case authpb.WRITE:
+ return cachedPerms.writePerms.Contains(ivl)
+ default:
+ plog.Panicf("unknown auth type: %v", permtyp)
+ }
+ return false
+}
+
+func checkKeyPoint(cachedPerms *unifiedRangePermissions, key []byte, permtyp authpb.Permission_Type) bool {
+ pt := adt.NewBytesAffinePoint(key)
+ switch permtyp {
+ case authpb.READ:
+ return cachedPerms.readPerms.Intersects(pt)
+ case authpb.WRITE:
+ return cachedPerms.writePerms.Intersects(pt)
+ default:
+ plog.Panicf("unknown auth type: %v", permtyp)
+ }
+ return false
+}
+
+func (as *authStore) isRangeOpPermitted(tx backend.BatchTx, userName string, key, rangeEnd []byte, permtyp authpb.Permission_Type) bool {
+ // assumption: tx is Lock()ed
+ _, ok := as.rangePermCache[userName]
+ if !ok {
+ perms := getMergedPerms(tx, userName)
+ if perms == nil {
+ plog.Errorf("failed to create a unified permission of user %s", userName)
+ return false
+ }
+ as.rangePermCache[userName] = perms
+ }
+
+ if len(rangeEnd) == 0 {
+ return checkKeyPoint(as.rangePermCache[userName], key, permtyp)
+ }
+
+ return checkKeyInterval(as.rangePermCache[userName], key, rangeEnd, permtyp)
+}
+
+func (as *authStore) clearCachedPerm() {
+ as.rangePermCache = make(map[string]*unifiedRangePermissions)
+}
+
+func (as *authStore) invalidateCachedPerm(userName string) {
+ delete(as.rangePermCache, userName)
+}
+
+type unifiedRangePermissions struct {
+ readPerms *adt.IntervalTree
+ writePerms *adt.IntervalTree
+}
diff --git a/vendor/github.com/coreos/etcd/auth/simple_token.go b/vendor/github.com/coreos/etcd/auth/simple_token.go
new file mode 100644
index 00000000..ac55ad7f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/auth/simple_token.go
@@ -0,0 +1,223 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package auth
+
+// CAUTION: This randum number based token mechanism is only for testing purpose.
+// JWT based mechanism will be added in the near future.
+
+import (
+ "context"
+ "crypto/rand"
+ "fmt"
+ "math/big"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ defaultSimpleTokenLength = 16
+)
+
+// var for testing purposes
+var (
+ simpleTokenTTL = 5 * time.Minute
+ simpleTokenTTLResolution = 1 * time.Second
+)
+
+type simpleTokenTTLKeeper struct {
+ tokens map[string]time.Time
+ donec chan struct{}
+ stopc chan struct{}
+ deleteTokenFunc func(string)
+ mu *sync.Mutex
+}
+
+func (tm *simpleTokenTTLKeeper) stop() {
+ select {
+ case tm.stopc <- struct{}{}:
+ case <-tm.donec:
+ }
+ <-tm.donec
+}
+
+func (tm *simpleTokenTTLKeeper) addSimpleToken(token string) {
+ tm.tokens[token] = time.Now().Add(simpleTokenTTL)
+}
+
+func (tm *simpleTokenTTLKeeper) resetSimpleToken(token string) {
+ if _, ok := tm.tokens[token]; ok {
+ tm.tokens[token] = time.Now().Add(simpleTokenTTL)
+ }
+}
+
+func (tm *simpleTokenTTLKeeper) deleteSimpleToken(token string) {
+ delete(tm.tokens, token)
+}
+
+func (tm *simpleTokenTTLKeeper) run() {
+ tokenTicker := time.NewTicker(simpleTokenTTLResolution)
+ defer func() {
+ tokenTicker.Stop()
+ close(tm.donec)
+ }()
+ for {
+ select {
+ case <-tokenTicker.C:
+ nowtime := time.Now()
+ tm.mu.Lock()
+ for t, tokenendtime := range tm.tokens {
+ if nowtime.After(tokenendtime) {
+ tm.deleteTokenFunc(t)
+ delete(tm.tokens, t)
+ }
+ }
+ tm.mu.Unlock()
+ case <-tm.stopc:
+ return
+ }
+ }
+}
+
+type tokenSimple struct {
+ indexWaiter func(uint64) <-chan struct{}
+ simpleTokenKeeper *simpleTokenTTLKeeper
+ simpleTokensMu sync.Mutex
+ simpleTokens map[string]string // token -> username
+}
+
+func (t *tokenSimple) genTokenPrefix() (string, error) {
+ ret := make([]byte, defaultSimpleTokenLength)
+
+ for i := 0; i < defaultSimpleTokenLength; i++ {
+ bInt, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
+ if err != nil {
+ return "", err
+ }
+
+ ret[i] = letters[bInt.Int64()]
+ }
+
+ return string(ret), nil
+}
+
+func (t *tokenSimple) assignSimpleTokenToUser(username, token string) {
+ t.simpleTokensMu.Lock()
+ defer t.simpleTokensMu.Unlock()
+ if t.simpleTokenKeeper == nil {
+ return
+ }
+
+ _, ok := t.simpleTokens[token]
+ if ok {
+ plog.Panicf("token %s is alredy used", token)
+ }
+
+ t.simpleTokens[token] = username
+ t.simpleTokenKeeper.addSimpleToken(token)
+}
+
+func (t *tokenSimple) invalidateUser(username string) {
+ if t.simpleTokenKeeper == nil {
+ return
+ }
+ t.simpleTokensMu.Lock()
+ for token, name := range t.simpleTokens {
+ if strings.Compare(name, username) == 0 {
+ delete(t.simpleTokens, token)
+ t.simpleTokenKeeper.deleteSimpleToken(token)
+ }
+ }
+ t.simpleTokensMu.Unlock()
+}
+
+func (t *tokenSimple) enable() {
+ delf := func(tk string) {
+ if username, ok := t.simpleTokens[tk]; ok {
+ plog.Infof("deleting token %s for user %s", tk, username)
+ delete(t.simpleTokens, tk)
+ }
+ }
+ t.simpleTokenKeeper = &simpleTokenTTLKeeper{
+ tokens: make(map[string]time.Time),
+ donec: make(chan struct{}),
+ stopc: make(chan struct{}),
+ deleteTokenFunc: delf,
+ mu: &t.simpleTokensMu,
+ }
+ go t.simpleTokenKeeper.run()
+}
+
+func (t *tokenSimple) disable() {
+ t.simpleTokensMu.Lock()
+ tk := t.simpleTokenKeeper
+ t.simpleTokenKeeper = nil
+ t.simpleTokens = make(map[string]string) // invalidate all tokens
+ t.simpleTokensMu.Unlock()
+ if tk != nil {
+ tk.stop()
+ }
+}
+
+func (t *tokenSimple) info(ctx context.Context, token string, revision uint64) (*AuthInfo, bool) {
+ if !t.isValidSimpleToken(ctx, token) {
+ return nil, false
+ }
+ t.simpleTokensMu.Lock()
+ username, ok := t.simpleTokens[token]
+ if ok && t.simpleTokenKeeper != nil {
+ t.simpleTokenKeeper.resetSimpleToken(token)
+ }
+ t.simpleTokensMu.Unlock()
+ return &AuthInfo{Username: username, Revision: revision}, ok
+}
+
+func (t *tokenSimple) assign(ctx context.Context, username string, rev uint64) (string, error) {
+ // rev isn't used in simple token, it is only used in JWT
+ index := ctx.Value(AuthenticateParamIndex{}).(uint64)
+ simpleTokenPrefix := ctx.Value(AuthenticateParamSimpleTokenPrefix{}).(string)
+ token := fmt.Sprintf("%s.%d", simpleTokenPrefix, index)
+ t.assignSimpleTokenToUser(username, token)
+
+ return token, nil
+}
+
+func (t *tokenSimple) isValidSimpleToken(ctx context.Context, token string) bool {
+ splitted := strings.Split(token, ".")
+ if len(splitted) != 2 {
+ return false
+ }
+ index, err := strconv.Atoi(splitted[1])
+ if err != nil {
+ return false
+ }
+
+ select {
+ case <-t.indexWaiter(uint64(index)):
+ return true
+ case <-ctx.Done():
+ }
+
+ return false
+}
+
+func newTokenProviderSimple(indexWaiter func(uint64) <-chan struct{}) *tokenSimple {
+ return &tokenSimple{
+ simpleTokens: make(map[string]string),
+ indexWaiter: indexWaiter,
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/auth/store.go b/vendor/github.com/coreos/etcd/auth/store.go
new file mode 100644
index 00000000..c2455a90
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/auth/store.go
@@ -0,0 +1,1123 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package auth
+
+import (
+ "bytes"
+ "context"
+ "encoding/binary"
+ "errors"
+ "sort"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ "github.com/coreos/etcd/auth/authpb"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/mvcc/backend"
+
+ "github.com/coreos/pkg/capnslog"
+ "golang.org/x/crypto/bcrypt"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+)
+
+var (
+ enableFlagKey = []byte("authEnabled")
+ authEnabled = []byte{1}
+ authDisabled = []byte{0}
+
+ revisionKey = []byte("authRevision")
+
+ authBucketName = []byte("auth")
+ authUsersBucketName = []byte("authUsers")
+ authRolesBucketName = []byte("authRoles")
+
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "auth")
+
+ ErrRootUserNotExist = errors.New("auth: root user does not exist")
+ ErrRootRoleNotExist = errors.New("auth: root user does not have root role")
+ ErrUserAlreadyExist = errors.New("auth: user already exists")
+ ErrUserEmpty = errors.New("auth: user name is empty")
+ ErrUserNotFound = errors.New("auth: user not found")
+ ErrRoleAlreadyExist = errors.New("auth: role already exists")
+ ErrRoleNotFound = errors.New("auth: role not found")
+ ErrAuthFailed = errors.New("auth: authentication failed, invalid user ID or password")
+ ErrPermissionDenied = errors.New("auth: permission denied")
+ ErrRoleNotGranted = errors.New("auth: role is not granted to the user")
+ ErrPermissionNotGranted = errors.New("auth: permission is not granted to the role")
+ ErrAuthNotEnabled = errors.New("auth: authentication is not enabled")
+ ErrAuthOldRevision = errors.New("auth: revision in header is old")
+ ErrInvalidAuthToken = errors.New("auth: invalid auth token")
+ ErrInvalidAuthOpts = errors.New("auth: invalid auth options")
+ ErrInvalidAuthMgmt = errors.New("auth: invalid auth management")
+
+ // BcryptCost is the algorithm cost / strength for hashing auth passwords
+ BcryptCost = bcrypt.DefaultCost
+)
+
+const (
+ rootUser = "root"
+ rootRole = "root"
+
+ tokenTypeSimple = "simple"
+ tokenTypeJWT = "jwt"
+
+ revBytesLen = 8
+)
+
+type AuthInfo struct {
+ Username string
+ Revision uint64
+}
+
+// AuthenticateParamIndex is used for a key of context in the parameters of Authenticate()
+type AuthenticateParamIndex struct{}
+
+// AuthenticateParamSimpleTokenPrefix is used for a key of context in the parameters of Authenticate()
+type AuthenticateParamSimpleTokenPrefix struct{}
+
+type AuthStore interface {
+ // AuthEnable turns on the authentication feature
+ AuthEnable() error
+
+ // AuthDisable turns off the authentication feature
+ AuthDisable()
+
+ // Authenticate does authentication based on given user name and password
+ Authenticate(ctx context.Context, username, password string) (*pb.AuthenticateResponse, error)
+
+ // Recover recovers the state of auth store from the given backend
+ Recover(b backend.Backend)
+
+ // UserAdd adds a new user
+ UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error)
+
+ // UserDelete deletes a user
+ UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error)
+
+ // UserChangePassword changes a password of a user
+ UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error)
+
+ // UserGrantRole grants a role to the user
+ UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error)
+
+ // UserGet gets the detailed information of a users
+ UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error)
+
+ // UserRevokeRole revokes a role of a user
+ UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error)
+
+ // RoleAdd adds a new role
+ RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
+
+ // RoleGrantPermission grants a permission to a role
+ RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error)
+
+ // RoleGet gets the detailed information of a role
+ RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error)
+
+ // RoleRevokePermission gets the detailed information of a role
+ RoleRevokePermission(r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error)
+
+ // RoleDelete gets the detailed information of a role
+ RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error)
+
+ // UserList gets a list of all users
+ UserList(r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error)
+
+ // RoleList gets a list of all roles
+ RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error)
+
+ // IsPutPermitted checks put permission of the user
+ IsPutPermitted(authInfo *AuthInfo, key []byte) error
+
+ // IsRangePermitted checks range permission of the user
+ IsRangePermitted(authInfo *AuthInfo, key, rangeEnd []byte) error
+
+ // IsDeleteRangePermitted checks delete-range permission of the user
+ IsDeleteRangePermitted(authInfo *AuthInfo, key, rangeEnd []byte) error
+
+ // IsAdminPermitted checks admin permission of the user
+ IsAdminPermitted(authInfo *AuthInfo) error
+
+ // GenTokenPrefix produces a random string in a case of simple token
+ // in a case of JWT, it produces an empty string
+ GenTokenPrefix() (string, error)
+
+ // Revision gets current revision of authStore
+ Revision() uint64
+
+ // CheckPassword checks a given pair of username and password is correct
+ CheckPassword(username, password string) (uint64, error)
+
+ // Close does cleanup of AuthStore
+ Close() error
+
+ // AuthInfoFromCtx gets AuthInfo from gRPC's context
+ AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error)
+
+ // AuthInfoFromTLS gets AuthInfo from TLS info of gRPC's context
+ AuthInfoFromTLS(ctx context.Context) *AuthInfo
+
+ // WithRoot generates and installs a token that can be used as a root credential
+ WithRoot(ctx context.Context) context.Context
+
+ // HasRole checks that user has role
+ HasRole(user, role string) bool
+}
+
+type TokenProvider interface {
+ info(ctx context.Context, token string, revision uint64) (*AuthInfo, bool)
+ assign(ctx context.Context, username string, revision uint64) (string, error)
+ enable()
+ disable()
+
+ invalidateUser(string)
+ genTokenPrefix() (string, error)
+}
+
+type authStore struct {
+ // atomic operations; need 64-bit align, or 32-bit tests will crash
+ revision uint64
+
+ be backend.Backend
+ enabled bool
+ enabledMu sync.RWMutex
+
+ rangePermCache map[string]*unifiedRangePermissions // username -> unifiedRangePermissions
+
+ tokenProvider TokenProvider
+}
+
+func (as *authStore) AuthEnable() error {
+ as.enabledMu.Lock()
+ defer as.enabledMu.Unlock()
+ if as.enabled {
+ plog.Noticef("Authentication already enabled")
+ return nil
+ }
+ b := as.be
+ tx := b.BatchTx()
+ tx.Lock()
+ defer func() {
+ tx.Unlock()
+ b.ForceCommit()
+ }()
+
+ u := getUser(tx, rootUser)
+ if u == nil {
+ return ErrRootUserNotExist
+ }
+
+ if !hasRootRole(u) {
+ return ErrRootRoleNotExist
+ }
+
+ tx.UnsafePut(authBucketName, enableFlagKey, authEnabled)
+
+ as.enabled = true
+ as.tokenProvider.enable()
+
+ as.rangePermCache = make(map[string]*unifiedRangePermissions)
+
+ as.setRevision(getRevision(tx))
+
+ plog.Noticef("Authentication enabled")
+
+ return nil
+}
+
+func (as *authStore) AuthDisable() {
+ as.enabledMu.Lock()
+ defer as.enabledMu.Unlock()
+ if !as.enabled {
+ return
+ }
+ b := as.be
+ tx := b.BatchTx()
+ tx.Lock()
+ tx.UnsafePut(authBucketName, enableFlagKey, authDisabled)
+ as.commitRevision(tx)
+ tx.Unlock()
+ b.ForceCommit()
+
+ as.enabled = false
+ as.tokenProvider.disable()
+
+ plog.Noticef("Authentication disabled")
+}
+
+func (as *authStore) Close() error {
+ as.enabledMu.Lock()
+ defer as.enabledMu.Unlock()
+ if !as.enabled {
+ return nil
+ }
+ as.tokenProvider.disable()
+ return nil
+}
+
+func (as *authStore) Authenticate(ctx context.Context, username, password string) (*pb.AuthenticateResponse, error) {
+ if !as.isAuthEnabled() {
+ return nil, ErrAuthNotEnabled
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, username)
+ if user == nil {
+ return nil, ErrAuthFailed
+ }
+
+ // Password checking is already performed in the API layer, so we don't need to check for now.
+ // Staleness of password can be detected with OCC in the API layer, too.
+
+ token, err := as.tokenProvider.assign(ctx, username, as.Revision())
+ if err != nil {
+ return nil, err
+ }
+
+ plog.Debugf("authorized %s, token is %s", username, token)
+ return &pb.AuthenticateResponse{Token: token}, nil
+}
+
+func (as *authStore) CheckPassword(username, password string) (uint64, error) {
+ if !as.isAuthEnabled() {
+ return 0, ErrAuthNotEnabled
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, username)
+ if user == nil {
+ return 0, ErrAuthFailed
+ }
+
+ if bcrypt.CompareHashAndPassword(user.Password, []byte(password)) != nil {
+ plog.Noticef("authentication failed, invalid password for user %s", username)
+ return 0, ErrAuthFailed
+ }
+
+ return getRevision(tx), nil
+}
+
+func (as *authStore) Recover(be backend.Backend) {
+ enabled := false
+ as.be = be
+ tx := be.BatchTx()
+ tx.Lock()
+ _, vs := tx.UnsafeRange(authBucketName, enableFlagKey, nil, 0)
+ if len(vs) == 1 {
+ if bytes.Equal(vs[0], authEnabled) {
+ enabled = true
+ }
+ }
+
+ as.setRevision(getRevision(tx))
+
+ tx.Unlock()
+
+ as.enabledMu.Lock()
+ as.enabled = enabled
+ as.enabledMu.Unlock()
+}
+
+func (as *authStore) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
+ if len(r.Name) == 0 {
+ return nil, ErrUserEmpty
+ }
+
+ hashed, err := bcrypt.GenerateFromPassword([]byte(r.Password), BcryptCost)
+ if err != nil {
+ plog.Errorf("failed to hash password: %s", err)
+ return nil, err
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, r.Name)
+ if user != nil {
+ return nil, ErrUserAlreadyExist
+ }
+
+ newUser := &authpb.User{
+ Name: []byte(r.Name),
+ Password: hashed,
+ }
+
+ putUser(tx, newUser)
+
+ as.commitRevision(tx)
+
+ plog.Noticef("added a new user: %s", r.Name)
+
+ return &pb.AuthUserAddResponse{}, nil
+}
+
+func (as *authStore) UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) {
+ if as.enabled && strings.Compare(r.Name, rootUser) == 0 {
+ plog.Errorf("the user root must not be deleted")
+ return nil, ErrInvalidAuthMgmt
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, r.Name)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ delUser(tx, r.Name)
+
+ as.commitRevision(tx)
+
+ as.invalidateCachedPerm(r.Name)
+ as.tokenProvider.invalidateUser(r.Name)
+
+ plog.Noticef("deleted a user: %s", r.Name)
+
+ return &pb.AuthUserDeleteResponse{}, nil
+}
+
+func (as *authStore) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) {
+ // TODO(mitake): measure the cost of bcrypt.GenerateFromPassword()
+ // If the cost is too high, we should move the encryption to outside of the raft
+ hashed, err := bcrypt.GenerateFromPassword([]byte(r.Password), BcryptCost)
+ if err != nil {
+ plog.Errorf("failed to hash password: %s", err)
+ return nil, err
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, r.Name)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ updatedUser := &authpb.User{
+ Name: []byte(r.Name),
+ Roles: user.Roles,
+ Password: hashed,
+ }
+
+ putUser(tx, updatedUser)
+
+ as.commitRevision(tx)
+
+ as.invalidateCachedPerm(r.Name)
+ as.tokenProvider.invalidateUser(r.Name)
+
+ plog.Noticef("changed a password of a user: %s", r.Name)
+
+ return &pb.AuthUserChangePasswordResponse{}, nil
+}
+
+func (as *authStore) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, r.User)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ if r.Role != rootRole {
+ role := getRole(tx, r.Role)
+ if role == nil {
+ return nil, ErrRoleNotFound
+ }
+ }
+
+ idx := sort.SearchStrings(user.Roles, r.Role)
+ if idx < len(user.Roles) && strings.Compare(user.Roles[idx], r.Role) == 0 {
+ plog.Warningf("user %s is already granted role %s", r.User, r.Role)
+ return &pb.AuthUserGrantRoleResponse{}, nil
+ }
+
+ user.Roles = append(user.Roles, r.Role)
+ sort.Strings(user.Roles)
+
+ putUser(tx, user)
+
+ as.invalidateCachedPerm(r.User)
+
+ as.commitRevision(tx)
+
+ plog.Noticef("granted role %s to user %s", r.Role, r.User)
+ return &pb.AuthUserGrantRoleResponse{}, nil
+}
+
+func (as *authStore) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ user := getUser(tx, r.Name)
+ tx.Unlock()
+
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ var resp pb.AuthUserGetResponse
+ resp.Roles = append(resp.Roles, user.Roles...)
+ return &resp, nil
+}
+
+func (as *authStore) UserList(r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ users := getAllUsers(tx)
+ tx.Unlock()
+
+ resp := &pb.AuthUserListResponse{Users: make([]string, len(users))}
+ for i := range users {
+ resp.Users[i] = string(users[i].Name)
+ }
+ return resp, nil
+}
+
+func (as *authStore) UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) {
+ if as.enabled && strings.Compare(r.Name, rootUser) == 0 && strings.Compare(r.Role, rootRole) == 0 {
+ plog.Errorf("the role root must not be revoked from the user root")
+ return nil, ErrInvalidAuthMgmt
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, r.Name)
+ if user == nil {
+ return nil, ErrUserNotFound
+ }
+
+ updatedUser := &authpb.User{
+ Name: user.Name,
+ Password: user.Password,
+ }
+
+ for _, role := range user.Roles {
+ if strings.Compare(role, r.Role) != 0 {
+ updatedUser.Roles = append(updatedUser.Roles, role)
+ }
+ }
+
+ if len(updatedUser.Roles) == len(user.Roles) {
+ return nil, ErrRoleNotGranted
+ }
+
+ putUser(tx, updatedUser)
+
+ as.invalidateCachedPerm(r.Name)
+
+ as.commitRevision(tx)
+
+ plog.Noticef("revoked role %s from user %s", r.Role, r.Name)
+ return &pb.AuthUserRevokeRoleResponse{}, nil
+}
+
+func (as *authStore) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ var resp pb.AuthRoleGetResponse
+
+ role := getRole(tx, r.Role)
+ if role == nil {
+ return nil, ErrRoleNotFound
+ }
+ resp.Perm = append(resp.Perm, role.KeyPermission...)
+ return &resp, nil
+}
+
+func (as *authStore) RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ roles := getAllRoles(tx)
+ tx.Unlock()
+
+ resp := &pb.AuthRoleListResponse{Roles: make([]string, len(roles))}
+ for i := range roles {
+ resp.Roles[i] = string(roles[i].Name)
+ }
+ return resp, nil
+}
+
+func (as *authStore) RoleRevokePermission(r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ role := getRole(tx, r.Role)
+ if role == nil {
+ return nil, ErrRoleNotFound
+ }
+
+ updatedRole := &authpb.Role{
+ Name: role.Name,
+ }
+
+ for _, perm := range role.KeyPermission {
+ if !bytes.Equal(perm.Key, []byte(r.Key)) || !bytes.Equal(perm.RangeEnd, []byte(r.RangeEnd)) {
+ updatedRole.KeyPermission = append(updatedRole.KeyPermission, perm)
+ }
+ }
+
+ if len(role.KeyPermission) == len(updatedRole.KeyPermission) {
+ return nil, ErrPermissionNotGranted
+ }
+
+ putRole(tx, updatedRole)
+
+ // TODO(mitake): currently single role update invalidates every cache
+ // It should be optimized.
+ as.clearCachedPerm()
+
+ as.commitRevision(tx)
+
+ plog.Noticef("revoked key %s from role %s", r.Key, r.Role)
+ return &pb.AuthRoleRevokePermissionResponse{}, nil
+}
+
+func (as *authStore) RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) {
+ if as.enabled && strings.Compare(r.Role, rootRole) == 0 {
+ plog.Errorf("the role root must not be deleted")
+ return nil, ErrInvalidAuthMgmt
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ role := getRole(tx, r.Role)
+ if role == nil {
+ return nil, ErrRoleNotFound
+ }
+
+ delRole(tx, r.Role)
+
+ users := getAllUsers(tx)
+ for _, user := range users {
+ updatedUser := &authpb.User{
+ Name: user.Name,
+ Password: user.Password,
+ }
+
+ for _, role := range user.Roles {
+ if strings.Compare(role, r.Role) != 0 {
+ updatedUser.Roles = append(updatedUser.Roles, role)
+ }
+ }
+
+ if len(updatedUser.Roles) == len(user.Roles) {
+ continue
+ }
+
+ putUser(tx, updatedUser)
+
+ as.invalidateCachedPerm(string(user.Name))
+ }
+
+ as.commitRevision(tx)
+
+ plog.Noticef("deleted role %s", r.Role)
+ return &pb.AuthRoleDeleteResponse{}, nil
+}
+
+func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ role := getRole(tx, r.Name)
+ if role != nil {
+ return nil, ErrRoleAlreadyExist
+ }
+
+ newRole := &authpb.Role{
+ Name: []byte(r.Name),
+ }
+
+ putRole(tx, newRole)
+
+ as.commitRevision(tx)
+
+ plog.Noticef("Role %s is created", r.Name)
+
+ return &pb.AuthRoleAddResponse{}, nil
+}
+
+func (as *authStore) authInfoFromToken(ctx context.Context, token string) (*AuthInfo, bool) {
+ return as.tokenProvider.info(ctx, token, as.Revision())
+}
+
+type permSlice []*authpb.Permission
+
+func (perms permSlice) Len() int {
+ return len(perms)
+}
+
+func (perms permSlice) Less(i, j int) bool {
+ return bytes.Compare(perms[i].Key, perms[j].Key) < 0
+}
+
+func (perms permSlice) Swap(i, j int) {
+ perms[i], perms[j] = perms[j], perms[i]
+}
+
+func (as *authStore) RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ role := getRole(tx, r.Name)
+ if role == nil {
+ return nil, ErrRoleNotFound
+ }
+
+ idx := sort.Search(len(role.KeyPermission), func(i int) bool {
+ return bytes.Compare(role.KeyPermission[i].Key, []byte(r.Perm.Key)) >= 0
+ })
+
+ if idx < len(role.KeyPermission) && bytes.Equal(role.KeyPermission[idx].Key, r.Perm.Key) && bytes.Equal(role.KeyPermission[idx].RangeEnd, r.Perm.RangeEnd) {
+ // update existing permission
+ role.KeyPermission[idx].PermType = r.Perm.PermType
+ } else {
+ // append new permission to the role
+ newPerm := &authpb.Permission{
+ Key: []byte(r.Perm.Key),
+ RangeEnd: []byte(r.Perm.RangeEnd),
+ PermType: r.Perm.PermType,
+ }
+
+ role.KeyPermission = append(role.KeyPermission, newPerm)
+ sort.Sort(permSlice(role.KeyPermission))
+ }
+
+ putRole(tx, role)
+
+ // TODO(mitake): currently single role update invalidates every cache
+ // It should be optimized.
+ as.clearCachedPerm()
+
+ as.commitRevision(tx)
+
+ plog.Noticef("role %s's permission of key %s is updated as %s", r.Name, r.Perm.Key, authpb.Permission_Type_name[int32(r.Perm.PermType)])
+
+ return &pb.AuthRoleGrantPermissionResponse{}, nil
+}
+
+func (as *authStore) isOpPermitted(userName string, revision uint64, key, rangeEnd []byte, permTyp authpb.Permission_Type) error {
+ // TODO(mitake): this function would be costly so we need a caching mechanism
+ if !as.isAuthEnabled() {
+ return nil
+ }
+
+ // only gets rev == 0 when passed AuthInfo{}; no user given
+ if revision == 0 {
+ return ErrUserEmpty
+ }
+
+ if revision < as.Revision() {
+ return ErrAuthOldRevision
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ user := getUser(tx, userName)
+ if user == nil {
+ plog.Errorf("invalid user name %s for permission checking", userName)
+ return ErrPermissionDenied
+ }
+
+ // root role should have permission on all ranges
+ if hasRootRole(user) {
+ return nil
+ }
+
+ if as.isRangeOpPermitted(tx, userName, key, rangeEnd, permTyp) {
+ return nil
+ }
+
+ return ErrPermissionDenied
+}
+
+func (as *authStore) IsPutPermitted(authInfo *AuthInfo, key []byte) error {
+ return as.isOpPermitted(authInfo.Username, authInfo.Revision, key, nil, authpb.WRITE)
+}
+
+func (as *authStore) IsRangePermitted(authInfo *AuthInfo, key, rangeEnd []byte) error {
+ return as.isOpPermitted(authInfo.Username, authInfo.Revision, key, rangeEnd, authpb.READ)
+}
+
+func (as *authStore) IsDeleteRangePermitted(authInfo *AuthInfo, key, rangeEnd []byte) error {
+ return as.isOpPermitted(authInfo.Username, authInfo.Revision, key, rangeEnd, authpb.WRITE)
+}
+
+func (as *authStore) IsAdminPermitted(authInfo *AuthInfo) error {
+ if !as.isAuthEnabled() {
+ return nil
+ }
+ if authInfo == nil {
+ return ErrUserEmpty
+ }
+
+ tx := as.be.BatchTx()
+ tx.Lock()
+ u := getUser(tx, authInfo.Username)
+ tx.Unlock()
+
+ if u == nil {
+ return ErrUserNotFound
+ }
+
+ if !hasRootRole(u) {
+ return ErrPermissionDenied
+ }
+
+ return nil
+}
+
+func getUser(tx backend.BatchTx, username string) *authpb.User {
+ _, vs := tx.UnsafeRange(authUsersBucketName, []byte(username), nil, 0)
+ if len(vs) == 0 {
+ return nil
+ }
+
+ user := &authpb.User{}
+ err := user.Unmarshal(vs[0])
+ if err != nil {
+ plog.Panicf("failed to unmarshal user struct (name: %s): %s", username, err)
+ }
+ return user
+}
+
+func getAllUsers(tx backend.BatchTx) []*authpb.User {
+ _, vs := tx.UnsafeRange(authUsersBucketName, []byte{0}, []byte{0xff}, -1)
+ if len(vs) == 0 {
+ return nil
+ }
+
+ users := make([]*authpb.User, len(vs))
+ for i := range vs {
+ user := &authpb.User{}
+ err := user.Unmarshal(vs[i])
+ if err != nil {
+ plog.Panicf("failed to unmarshal user struct: %s", err)
+ }
+ users[i] = user
+ }
+ return users
+}
+
+func putUser(tx backend.BatchTx, user *authpb.User) {
+ b, err := user.Marshal()
+ if err != nil {
+ plog.Panicf("failed to marshal user struct (name: %s): %s", user.Name, err)
+ }
+ tx.UnsafePut(authUsersBucketName, user.Name, b)
+}
+
+func delUser(tx backend.BatchTx, username string) {
+ tx.UnsafeDelete(authUsersBucketName, []byte(username))
+}
+
+func getRole(tx backend.BatchTx, rolename string) *authpb.Role {
+ _, vs := tx.UnsafeRange(authRolesBucketName, []byte(rolename), nil, 0)
+ if len(vs) == 0 {
+ return nil
+ }
+
+ role := &authpb.Role{}
+ err := role.Unmarshal(vs[0])
+ if err != nil {
+ plog.Panicf("failed to unmarshal role struct (name: %s): %s", rolename, err)
+ }
+ return role
+}
+
+func getAllRoles(tx backend.BatchTx) []*authpb.Role {
+ _, vs := tx.UnsafeRange(authRolesBucketName, []byte{0}, []byte{0xff}, -1)
+ if len(vs) == 0 {
+ return nil
+ }
+
+ roles := make([]*authpb.Role, len(vs))
+ for i := range vs {
+ role := &authpb.Role{}
+ err := role.Unmarshal(vs[i])
+ if err != nil {
+ plog.Panicf("failed to unmarshal role struct: %s", err)
+ }
+ roles[i] = role
+ }
+ return roles
+}
+
+func putRole(tx backend.BatchTx, role *authpb.Role) {
+ b, err := role.Marshal()
+ if err != nil {
+ plog.Panicf("failed to marshal role struct (name: %s): %s", role.Name, err)
+ }
+
+ tx.UnsafePut(authRolesBucketName, []byte(role.Name), b)
+}
+
+func delRole(tx backend.BatchTx, rolename string) {
+ tx.UnsafeDelete(authRolesBucketName, []byte(rolename))
+}
+
+func (as *authStore) isAuthEnabled() bool {
+ as.enabledMu.RLock()
+ defer as.enabledMu.RUnlock()
+ return as.enabled
+}
+
+func NewAuthStore(be backend.Backend, tp TokenProvider) *authStore {
+ tx := be.BatchTx()
+ tx.Lock()
+
+ tx.UnsafeCreateBucket(authBucketName)
+ tx.UnsafeCreateBucket(authUsersBucketName)
+ tx.UnsafeCreateBucket(authRolesBucketName)
+
+ enabled := false
+ _, vs := tx.UnsafeRange(authBucketName, enableFlagKey, nil, 0)
+ if len(vs) == 1 {
+ if bytes.Equal(vs[0], authEnabled) {
+ enabled = true
+ }
+ }
+
+ as := &authStore{
+ be: be,
+ revision: getRevision(tx),
+ enabled: enabled,
+ rangePermCache: make(map[string]*unifiedRangePermissions),
+ tokenProvider: tp,
+ }
+
+ if enabled {
+ as.tokenProvider.enable()
+ }
+
+ if as.Revision() == 0 {
+ as.commitRevision(tx)
+ }
+
+ tx.Unlock()
+ be.ForceCommit()
+
+ return as
+}
+
+func hasRootRole(u *authpb.User) bool {
+ // u.Roles is sorted in UserGrantRole(), so we can use binary search.
+ idx := sort.SearchStrings(u.Roles, rootRole)
+ return idx != len(u.Roles) && u.Roles[idx] == rootRole
+}
+
+func (as *authStore) commitRevision(tx backend.BatchTx) {
+ atomic.AddUint64(&as.revision, 1)
+ revBytes := make([]byte, revBytesLen)
+ binary.BigEndian.PutUint64(revBytes, as.Revision())
+ tx.UnsafePut(authBucketName, revisionKey, revBytes)
+}
+
+func getRevision(tx backend.BatchTx) uint64 {
+ _, vs := tx.UnsafeRange(authBucketName, []byte(revisionKey), nil, 0)
+ if len(vs) != 1 {
+ // this can happen in the initialization phase
+ return 0
+ }
+
+ return binary.BigEndian.Uint64(vs[0])
+}
+
+func (as *authStore) setRevision(rev uint64) {
+ atomic.StoreUint64(&as.revision, rev)
+}
+
+func (as *authStore) Revision() uint64 {
+ return atomic.LoadUint64(&as.revision)
+}
+
+func (as *authStore) AuthInfoFromTLS(ctx context.Context) *AuthInfo {
+ peer, ok := peer.FromContext(ctx)
+ if !ok || peer == nil || peer.AuthInfo == nil {
+ return nil
+ }
+
+ tlsInfo := peer.AuthInfo.(credentials.TLSInfo)
+ for _, chains := range tlsInfo.State.VerifiedChains {
+ for _, chain := range chains {
+ cn := chain.Subject.CommonName
+ plog.Debugf("found common name %s", cn)
+
+ return &AuthInfo{
+ Username: cn,
+ Revision: as.Revision(),
+ }
+ }
+ }
+
+ return nil
+}
+
+func (as *authStore) AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error) {
+ md, ok := metadata.FromIncomingContext(ctx)
+ if !ok {
+ return nil, nil
+ }
+
+ //TODO(mitake|hexfusion) review unifying key names
+ ts, ok := md["token"]
+ if !ok {
+ ts, ok = md["authorization"]
+ }
+ if !ok {
+ return nil, nil
+ }
+
+ token := ts[0]
+ authInfo, uok := as.authInfoFromToken(ctx, token)
+ if !uok {
+ plog.Warningf("invalid auth token: %s", token)
+ return nil, ErrInvalidAuthToken
+ }
+
+ return authInfo, nil
+}
+
+func (as *authStore) GenTokenPrefix() (string, error) {
+ return as.tokenProvider.genTokenPrefix()
+}
+
+func decomposeOpts(optstr string) (string, map[string]string, error) {
+ opts := strings.Split(optstr, ",")
+ tokenType := opts[0]
+
+ typeSpecificOpts := make(map[string]string)
+ for i := 1; i < len(opts); i++ {
+ pair := strings.Split(opts[i], "=")
+
+ if len(pair) != 2 {
+ plog.Errorf("invalid token specific option: %s", optstr)
+ return "", nil, ErrInvalidAuthOpts
+ }
+
+ if _, ok := typeSpecificOpts[pair[0]]; ok {
+ plog.Errorf("invalid token specific option, duplicated parameters (%s): %s", pair[0], optstr)
+ return "", nil, ErrInvalidAuthOpts
+ }
+
+ typeSpecificOpts[pair[0]] = pair[1]
+ }
+
+ return tokenType, typeSpecificOpts, nil
+
+}
+
+func NewTokenProvider(tokenOpts string, indexWaiter func(uint64) <-chan struct{}) (TokenProvider, error) {
+ tokenType, typeSpecificOpts, err := decomposeOpts(tokenOpts)
+ if err != nil {
+ return nil, ErrInvalidAuthOpts
+ }
+
+ switch tokenType {
+ case tokenTypeSimple:
+ plog.Warningf("simple token is not cryptographically signed")
+ return newTokenProviderSimple(indexWaiter), nil
+
+ case tokenTypeJWT:
+ return newTokenProviderJWT(typeSpecificOpts)
+
+ case "":
+ return newTokenProviderNop()
+ default:
+ plog.Errorf("unknown token type: %s", tokenType)
+ return nil, ErrInvalidAuthOpts
+ }
+}
+
+func (as *authStore) WithRoot(ctx context.Context) context.Context {
+ if !as.isAuthEnabled() {
+ return ctx
+ }
+
+ var ctxForAssign context.Context
+ if ts, ok := as.tokenProvider.(*tokenSimple); ok && ts != nil {
+ ctx1 := context.WithValue(ctx, AuthenticateParamIndex{}, uint64(0))
+ prefix, err := ts.genTokenPrefix()
+ if err != nil {
+ plog.Errorf("failed to generate prefix of internally used token")
+ return ctx
+ }
+ ctxForAssign = context.WithValue(ctx1, AuthenticateParamSimpleTokenPrefix{}, prefix)
+ } else {
+ ctxForAssign = ctx
+ }
+
+ token, err := as.tokenProvider.assign(ctxForAssign, "root", as.Revision())
+ if err != nil {
+ // this must not happen
+ plog.Errorf("failed to assign token for lease revoking: %s", err)
+ return ctx
+ }
+
+ mdMap := map[string]string{
+ "token": token,
+ }
+ tokenMD := metadata.New(mdMap)
+
+ // use "mdIncomingKey{}" since it's called from local etcdserver
+ return metadata.NewIncomingContext(ctx, tokenMD)
+}
+
+func (as *authStore) HasRole(user, role string) bool {
+ tx := as.be.BatchTx()
+ tx.Lock()
+ u := getUser(tx, user)
+ tx.Unlock()
+
+ if u == nil {
+ plog.Warningf("tried to check user %s has role %s, but user %s doesn't exist", user, role, user)
+ return false
+ }
+
+ for _, r := range u.Roles {
+ if role == r {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/github.com/coreos/etcd/client/auth_role.go b/vendor/github.com/coreos/etcd/client/auth_role.go
new file mode 100644
index 00000000..b6ba7e15
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/auth_role.go
@@ -0,0 +1,236 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/url"
+)
+
+type Role struct {
+ Role string `json:"role"`
+ Permissions Permissions `json:"permissions"`
+ Grant *Permissions `json:"grant,omitempty"`
+ Revoke *Permissions `json:"revoke,omitempty"`
+}
+
+type Permissions struct {
+ KV rwPermission `json:"kv"`
+}
+
+type rwPermission struct {
+ Read []string `json:"read"`
+ Write []string `json:"write"`
+}
+
+type PermissionType int
+
+const (
+ ReadPermission PermissionType = iota
+ WritePermission
+ ReadWritePermission
+)
+
+// NewAuthRoleAPI constructs a new AuthRoleAPI that uses HTTP to
+// interact with etcd's role creation and modification features.
+func NewAuthRoleAPI(c Client) AuthRoleAPI {
+ return &httpAuthRoleAPI{
+ client: c,
+ }
+}
+
+type AuthRoleAPI interface {
+ // AddRole adds a role.
+ AddRole(ctx context.Context, role string) error
+
+ // RemoveRole removes a role.
+ RemoveRole(ctx context.Context, role string) error
+
+ // GetRole retrieves role details.
+ GetRole(ctx context.Context, role string) (*Role, error)
+
+ // GrantRoleKV grants a role some permission prefixes for the KV store.
+ GrantRoleKV(ctx context.Context, role string, prefixes []string, permType PermissionType) (*Role, error)
+
+ // RevokeRoleKV revokes some permission prefixes for a role on the KV store.
+ RevokeRoleKV(ctx context.Context, role string, prefixes []string, permType PermissionType) (*Role, error)
+
+ // ListRoles lists roles.
+ ListRoles(ctx context.Context) ([]string, error)
+}
+
+type httpAuthRoleAPI struct {
+ client httpClient
+}
+
+type authRoleAPIAction struct {
+ verb string
+ name string
+ role *Role
+}
+
+type authRoleAPIList struct{}
+
+func (list *authRoleAPIList) HTTPRequest(ep url.URL) *http.Request {
+ u := v2AuthURL(ep, "roles", "")
+ req, _ := http.NewRequest("GET", u.String(), nil)
+ req.Header.Set("Content-Type", "application/json")
+ return req
+}
+
+func (l *authRoleAPIAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2AuthURL(ep, "roles", l.name)
+ if l.role == nil {
+ req, _ := http.NewRequest(l.verb, u.String(), nil)
+ return req
+ }
+ b, err := json.Marshal(l.role)
+ if err != nil {
+ panic(err)
+ }
+ body := bytes.NewReader(b)
+ req, _ := http.NewRequest(l.verb, u.String(), body)
+ req.Header.Set("Content-Type", "application/json")
+ return req
+}
+
+func (r *httpAuthRoleAPI) ListRoles(ctx context.Context) ([]string, error) {
+ resp, body, err := r.client.Do(ctx, &authRoleAPIList{})
+ if err != nil {
+ return nil, err
+ }
+ if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
+ return nil, err
+ }
+ var roleList struct {
+ Roles []Role `json:"roles"`
+ }
+ if err = json.Unmarshal(body, &roleList); err != nil {
+ return nil, err
+ }
+ ret := make([]string, 0, len(roleList.Roles))
+ for _, r := range roleList.Roles {
+ ret = append(ret, r.Role)
+ }
+ return ret, nil
+}
+
+func (r *httpAuthRoleAPI) AddRole(ctx context.Context, rolename string) error {
+ role := &Role{
+ Role: rolename,
+ }
+ return r.addRemoveRole(ctx, &authRoleAPIAction{
+ verb: "PUT",
+ name: rolename,
+ role: role,
+ })
+}
+
+func (r *httpAuthRoleAPI) RemoveRole(ctx context.Context, rolename string) error {
+ return r.addRemoveRole(ctx, &authRoleAPIAction{
+ verb: "DELETE",
+ name: rolename,
+ })
+}
+
+func (r *httpAuthRoleAPI) addRemoveRole(ctx context.Context, req *authRoleAPIAction) error {
+ resp, body, err := r.client.Do(ctx, req)
+ if err != nil {
+ return err
+ }
+ if err := assertStatusCode(resp.StatusCode, http.StatusOK, http.StatusCreated); err != nil {
+ var sec authError
+ err := json.Unmarshal(body, &sec)
+ if err != nil {
+ return err
+ }
+ return sec
+ }
+ return nil
+}
+
+func (r *httpAuthRoleAPI) GetRole(ctx context.Context, rolename string) (*Role, error) {
+ return r.modRole(ctx, &authRoleAPIAction{
+ verb: "GET",
+ name: rolename,
+ })
+}
+
+func buildRWPermission(prefixes []string, permType PermissionType) rwPermission {
+ var out rwPermission
+ switch permType {
+ case ReadPermission:
+ out.Read = prefixes
+ case WritePermission:
+ out.Write = prefixes
+ case ReadWritePermission:
+ out.Read = prefixes
+ out.Write = prefixes
+ }
+ return out
+}
+
+func (r *httpAuthRoleAPI) GrantRoleKV(ctx context.Context, rolename string, prefixes []string, permType PermissionType) (*Role, error) {
+ rwp := buildRWPermission(prefixes, permType)
+ role := &Role{
+ Role: rolename,
+ Grant: &Permissions{
+ KV: rwp,
+ },
+ }
+ return r.modRole(ctx, &authRoleAPIAction{
+ verb: "PUT",
+ name: rolename,
+ role: role,
+ })
+}
+
+func (r *httpAuthRoleAPI) RevokeRoleKV(ctx context.Context, rolename string, prefixes []string, permType PermissionType) (*Role, error) {
+ rwp := buildRWPermission(prefixes, permType)
+ role := &Role{
+ Role: rolename,
+ Revoke: &Permissions{
+ KV: rwp,
+ },
+ }
+ return r.modRole(ctx, &authRoleAPIAction{
+ verb: "PUT",
+ name: rolename,
+ role: role,
+ })
+}
+
+func (r *httpAuthRoleAPI) modRole(ctx context.Context, req *authRoleAPIAction) (*Role, error) {
+ resp, body, err := r.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+ if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
+ var sec authError
+ err = json.Unmarshal(body, &sec)
+ if err != nil {
+ return nil, err
+ }
+ return nil, sec
+ }
+ var role Role
+ if err = json.Unmarshal(body, &role); err != nil {
+ return nil, err
+ }
+ return &role, nil
+}
diff --git a/vendor/github.com/coreos/etcd/client/auth_user.go b/vendor/github.com/coreos/etcd/client/auth_user.go
new file mode 100644
index 00000000..8e7e2efe
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/auth_user.go
@@ -0,0 +1,319 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/url"
+ "path"
+)
+
+var (
+ defaultV2AuthPrefix = "/v2/auth"
+)
+
+type User struct {
+ User string `json:"user"`
+ Password string `json:"password,omitempty"`
+ Roles []string `json:"roles"`
+ Grant []string `json:"grant,omitempty"`
+ Revoke []string `json:"revoke,omitempty"`
+}
+
+// userListEntry is the user representation given by the server for ListUsers
+type userListEntry struct {
+ User string `json:"user"`
+ Roles []Role `json:"roles"`
+}
+
+type UserRoles struct {
+ User string `json:"user"`
+ Roles []Role `json:"roles"`
+}
+
+func v2AuthURL(ep url.URL, action string, name string) *url.URL {
+ if name != "" {
+ ep.Path = path.Join(ep.Path, defaultV2AuthPrefix, action, name)
+ return &ep
+ }
+ ep.Path = path.Join(ep.Path, defaultV2AuthPrefix, action)
+ return &ep
+}
+
+// NewAuthAPI constructs a new AuthAPI that uses HTTP to
+// interact with etcd's general auth features.
+func NewAuthAPI(c Client) AuthAPI {
+ return &httpAuthAPI{
+ client: c,
+ }
+}
+
+type AuthAPI interface {
+ // Enable auth.
+ Enable(ctx context.Context) error
+
+ // Disable auth.
+ Disable(ctx context.Context) error
+}
+
+type httpAuthAPI struct {
+ client httpClient
+}
+
+func (s *httpAuthAPI) Enable(ctx context.Context) error {
+ return s.enableDisable(ctx, &authAPIAction{"PUT"})
+}
+
+func (s *httpAuthAPI) Disable(ctx context.Context) error {
+ return s.enableDisable(ctx, &authAPIAction{"DELETE"})
+}
+
+func (s *httpAuthAPI) enableDisable(ctx context.Context, req httpAction) error {
+ resp, body, err := s.client.Do(ctx, req)
+ if err != nil {
+ return err
+ }
+ if err = assertStatusCode(resp.StatusCode, http.StatusOK, http.StatusCreated); err != nil {
+ var sec authError
+ err = json.Unmarshal(body, &sec)
+ if err != nil {
+ return err
+ }
+ return sec
+ }
+ return nil
+}
+
+type authAPIAction struct {
+ verb string
+}
+
+func (l *authAPIAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2AuthURL(ep, "enable", "")
+ req, _ := http.NewRequest(l.verb, u.String(), nil)
+ return req
+}
+
+type authError struct {
+ Message string `json:"message"`
+ Code int `json:"-"`
+}
+
+func (e authError) Error() string {
+ return e.Message
+}
+
+// NewAuthUserAPI constructs a new AuthUserAPI that uses HTTP to
+// interact with etcd's user creation and modification features.
+func NewAuthUserAPI(c Client) AuthUserAPI {
+ return &httpAuthUserAPI{
+ client: c,
+ }
+}
+
+type AuthUserAPI interface {
+ // AddUser adds a user.
+ AddUser(ctx context.Context, username string, password string) error
+
+ // RemoveUser removes a user.
+ RemoveUser(ctx context.Context, username string) error
+
+ // GetUser retrieves user details.
+ GetUser(ctx context.Context, username string) (*User, error)
+
+ // GrantUser grants a user some permission roles.
+ GrantUser(ctx context.Context, username string, roles []string) (*User, error)
+
+ // RevokeUser revokes some permission roles from a user.
+ RevokeUser(ctx context.Context, username string, roles []string) (*User, error)
+
+ // ChangePassword changes the user's password.
+ ChangePassword(ctx context.Context, username string, password string) (*User, error)
+
+ // ListUsers lists the users.
+ ListUsers(ctx context.Context) ([]string, error)
+}
+
+type httpAuthUserAPI struct {
+ client httpClient
+}
+
+type authUserAPIAction struct {
+ verb string
+ username string
+ user *User
+}
+
+type authUserAPIList struct{}
+
+func (list *authUserAPIList) HTTPRequest(ep url.URL) *http.Request {
+ u := v2AuthURL(ep, "users", "")
+ req, _ := http.NewRequest("GET", u.String(), nil)
+ req.Header.Set("Content-Type", "application/json")
+ return req
+}
+
+func (l *authUserAPIAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2AuthURL(ep, "users", l.username)
+ if l.user == nil {
+ req, _ := http.NewRequest(l.verb, u.String(), nil)
+ return req
+ }
+ b, err := json.Marshal(l.user)
+ if err != nil {
+ panic(err)
+ }
+ body := bytes.NewReader(b)
+ req, _ := http.NewRequest(l.verb, u.String(), body)
+ req.Header.Set("Content-Type", "application/json")
+ return req
+}
+
+func (u *httpAuthUserAPI) ListUsers(ctx context.Context) ([]string, error) {
+ resp, body, err := u.client.Do(ctx, &authUserAPIList{})
+ if err != nil {
+ return nil, err
+ }
+ if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
+ var sec authError
+ err = json.Unmarshal(body, &sec)
+ if err != nil {
+ return nil, err
+ }
+ return nil, sec
+ }
+
+ var userList struct {
+ Users []userListEntry `json:"users"`
+ }
+
+ if err = json.Unmarshal(body, &userList); err != nil {
+ return nil, err
+ }
+
+ ret := make([]string, 0, len(userList.Users))
+ for _, u := range userList.Users {
+ ret = append(ret, u.User)
+ }
+ return ret, nil
+}
+
+func (u *httpAuthUserAPI) AddUser(ctx context.Context, username string, password string) error {
+ user := &User{
+ User: username,
+ Password: password,
+ }
+ return u.addRemoveUser(ctx, &authUserAPIAction{
+ verb: "PUT",
+ username: username,
+ user: user,
+ })
+}
+
+func (u *httpAuthUserAPI) RemoveUser(ctx context.Context, username string) error {
+ return u.addRemoveUser(ctx, &authUserAPIAction{
+ verb: "DELETE",
+ username: username,
+ })
+}
+
+func (u *httpAuthUserAPI) addRemoveUser(ctx context.Context, req *authUserAPIAction) error {
+ resp, body, err := u.client.Do(ctx, req)
+ if err != nil {
+ return err
+ }
+ if err = assertStatusCode(resp.StatusCode, http.StatusOK, http.StatusCreated); err != nil {
+ var sec authError
+ err = json.Unmarshal(body, &sec)
+ if err != nil {
+ return err
+ }
+ return sec
+ }
+ return nil
+}
+
+func (u *httpAuthUserAPI) GetUser(ctx context.Context, username string) (*User, error) {
+ return u.modUser(ctx, &authUserAPIAction{
+ verb: "GET",
+ username: username,
+ })
+}
+
+func (u *httpAuthUserAPI) GrantUser(ctx context.Context, username string, roles []string) (*User, error) {
+ user := &User{
+ User: username,
+ Grant: roles,
+ }
+ return u.modUser(ctx, &authUserAPIAction{
+ verb: "PUT",
+ username: username,
+ user: user,
+ })
+}
+
+func (u *httpAuthUserAPI) RevokeUser(ctx context.Context, username string, roles []string) (*User, error) {
+ user := &User{
+ User: username,
+ Revoke: roles,
+ }
+ return u.modUser(ctx, &authUserAPIAction{
+ verb: "PUT",
+ username: username,
+ user: user,
+ })
+}
+
+func (u *httpAuthUserAPI) ChangePassword(ctx context.Context, username string, password string) (*User, error) {
+ user := &User{
+ User: username,
+ Password: password,
+ }
+ return u.modUser(ctx, &authUserAPIAction{
+ verb: "PUT",
+ username: username,
+ user: user,
+ })
+}
+
+func (u *httpAuthUserAPI) modUser(ctx context.Context, req *authUserAPIAction) (*User, error) {
+ resp, body, err := u.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+ if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
+ var sec authError
+ err = json.Unmarshal(body, &sec)
+ if err != nil {
+ return nil, err
+ }
+ return nil, sec
+ }
+ var user User
+ if err = json.Unmarshal(body, &user); err != nil {
+ var userR UserRoles
+ if urerr := json.Unmarshal(body, &userR); urerr != nil {
+ return nil, err
+ }
+ user.User = userR.User
+ for _, r := range userR.Roles {
+ user.Roles = append(user.Roles, r.Role)
+ }
+ }
+ return &user, nil
+}
diff --git a/vendor/github.com/coreos/etcd/client/cancelreq.go b/vendor/github.com/coreos/etcd/client/cancelreq.go
new file mode 100644
index 00000000..76d1f040
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/cancelreq.go
@@ -0,0 +1,18 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// borrowed from golang/net/context/ctxhttp/cancelreq.go
+
+package client
+
+import "net/http"
+
+func requestCanceler(tr CancelableTransport, req *http.Request) func() {
+ ch := make(chan struct{})
+ req.Cancel = ch
+
+ return func() {
+ close(ch)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/client/client.go b/vendor/github.com/coreos/etcd/client/client.go
new file mode 100644
index 00000000..e6874505
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/client.go
@@ -0,0 +1,710 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "math/rand"
+ "net"
+ "net/http"
+ "net/url"
+ "sort"
+ "strconv"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/version"
+)
+
+var (
+ ErrNoEndpoints = errors.New("client: no endpoints available")
+ ErrTooManyRedirects = errors.New("client: too many redirects")
+ ErrClusterUnavailable = errors.New("client: etcd cluster is unavailable or misconfigured")
+ ErrNoLeaderEndpoint = errors.New("client: no leader endpoint available")
+ errTooManyRedirectChecks = errors.New("client: too many redirect checks")
+
+ // oneShotCtxValue is set on a context using WithValue(&oneShotValue) so
+ // that Do() will not retry a request
+ oneShotCtxValue interface{}
+)
+
+var DefaultRequestTimeout = 5 * time.Second
+
+var DefaultTransport CancelableTransport = &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ Dial: (&net.Dialer{
+ Timeout: 30 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }).Dial,
+ TLSHandshakeTimeout: 10 * time.Second,
+}
+
+type EndpointSelectionMode int
+
+const (
+ // EndpointSelectionRandom is the default value of the 'SelectionMode'.
+ // As the name implies, the client object will pick a node from the members
+ // of the cluster in a random fashion. If the cluster has three members, A, B,
+ // and C, the client picks any node from its three members as its request
+ // destination.
+ EndpointSelectionRandom EndpointSelectionMode = iota
+
+ // If 'SelectionMode' is set to 'EndpointSelectionPrioritizeLeader',
+ // requests are sent directly to the cluster leader. This reduces
+ // forwarding roundtrips compared to making requests to etcd followers
+ // who then forward them to the cluster leader. In the event of a leader
+ // failure, however, clients configured this way cannot prioritize among
+ // the remaining etcd followers. Therefore, when a client sets 'SelectionMode'
+ // to 'EndpointSelectionPrioritizeLeader', it must use 'client.AutoSync()' to
+ // maintain its knowledge of current cluster state.
+ //
+ // This mode should be used with Client.AutoSync().
+ EndpointSelectionPrioritizeLeader
+)
+
+type Config struct {
+ // Endpoints defines a set of URLs (schemes, hosts and ports only)
+ // that can be used to communicate with a logical etcd cluster. For
+ // example, a three-node cluster could be provided like so:
+ //
+ // Endpoints: []string{
+ // "http://node1.example.com:2379",
+ // "http://node2.example.com:2379",
+ // "http://node3.example.com:2379",
+ // }
+ //
+ // If multiple endpoints are provided, the Client will attempt to
+ // use them all in the event that one or more of them are unusable.
+ //
+ // If Client.Sync is ever called, the Client may cache an alternate
+ // set of endpoints to continue operation.
+ Endpoints []string
+
+ // Transport is used by the Client to drive HTTP requests. If not
+ // provided, DefaultTransport will be used.
+ Transport CancelableTransport
+
+ // CheckRedirect specifies the policy for handling HTTP redirects.
+ // If CheckRedirect is not nil, the Client calls it before
+ // following an HTTP redirect. The sole argument is the number of
+ // requests that have already been made. If CheckRedirect returns
+ // an error, Client.Do will not make any further requests and return
+ // the error back it to the caller.
+ //
+ // If CheckRedirect is nil, the Client uses its default policy,
+ // which is to stop after 10 consecutive requests.
+ CheckRedirect CheckRedirectFunc
+
+ // Username specifies the user credential to add as an authorization header
+ Username string
+
+ // Password is the password for the specified user to add as an authorization header
+ // to the request.
+ Password string
+
+ // HeaderTimeoutPerRequest specifies the time limit to wait for response
+ // header in a single request made by the Client. The timeout includes
+ // connection time, any redirects, and header wait time.
+ //
+ // For non-watch GET request, server returns the response body immediately.
+ // For PUT/POST/DELETE request, server will attempt to commit request
+ // before responding, which is expected to take `100ms + 2 * RTT`.
+ // For watch request, server returns the header immediately to notify Client
+ // watch start. But if server is behind some kind of proxy, the response
+ // header may be cached at proxy, and Client cannot rely on this behavior.
+ //
+ // Especially, wait request will ignore this timeout.
+ //
+ // One API call may send multiple requests to different etcd servers until it
+ // succeeds. Use context of the API to specify the overall timeout.
+ //
+ // A HeaderTimeoutPerRequest of zero means no timeout.
+ HeaderTimeoutPerRequest time.Duration
+
+ // SelectionMode is an EndpointSelectionMode enum that specifies the
+ // policy for choosing the etcd cluster node to which requests are sent.
+ SelectionMode EndpointSelectionMode
+}
+
+func (cfg *Config) transport() CancelableTransport {
+ if cfg.Transport == nil {
+ return DefaultTransport
+ }
+ return cfg.Transport
+}
+
+func (cfg *Config) checkRedirect() CheckRedirectFunc {
+ if cfg.CheckRedirect == nil {
+ return DefaultCheckRedirect
+ }
+ return cfg.CheckRedirect
+}
+
+// CancelableTransport mimics net/http.Transport, but requires that
+// the object also support request cancellation.
+type CancelableTransport interface {
+ http.RoundTripper
+ CancelRequest(req *http.Request)
+}
+
+type CheckRedirectFunc func(via int) error
+
+// DefaultCheckRedirect follows up to 10 redirects, but no more.
+var DefaultCheckRedirect CheckRedirectFunc = func(via int) error {
+ if via > 10 {
+ return ErrTooManyRedirects
+ }
+ return nil
+}
+
+type Client interface {
+ // Sync updates the internal cache of the etcd cluster's membership.
+ Sync(context.Context) error
+
+ // AutoSync periodically calls Sync() every given interval.
+ // The recommended sync interval is 10 seconds to 1 minute, which does
+ // not bring too much overhead to server and makes client catch up the
+ // cluster change in time.
+ //
+ // The example to use it:
+ //
+ // for {
+ // err := client.AutoSync(ctx, 10*time.Second)
+ // if err == context.DeadlineExceeded || err == context.Canceled {
+ // break
+ // }
+ // log.Print(err)
+ // }
+ AutoSync(context.Context, time.Duration) error
+
+ // Endpoints returns a copy of the current set of API endpoints used
+ // by Client to resolve HTTP requests. If Sync has ever been called,
+ // this may differ from the initial Endpoints provided in the Config.
+ Endpoints() []string
+
+ // SetEndpoints sets the set of API endpoints used by Client to resolve
+ // HTTP requests. If the given endpoints are not valid, an error will be
+ // returned
+ SetEndpoints(eps []string) error
+
+ // GetVersion retrieves the current etcd server and cluster version
+ GetVersion(ctx context.Context) (*version.Versions, error)
+
+ httpClient
+}
+
+func New(cfg Config) (Client, error) {
+ c := &httpClusterClient{
+ clientFactory: newHTTPClientFactory(cfg.transport(), cfg.checkRedirect(), cfg.HeaderTimeoutPerRequest),
+ rand: rand.New(rand.NewSource(int64(time.Now().Nanosecond()))),
+ selectionMode: cfg.SelectionMode,
+ }
+ if cfg.Username != "" {
+ c.credentials = &credentials{
+ username: cfg.Username,
+ password: cfg.Password,
+ }
+ }
+ if err := c.SetEndpoints(cfg.Endpoints); err != nil {
+ return nil, err
+ }
+ return c, nil
+}
+
+type httpClient interface {
+ Do(context.Context, httpAction) (*http.Response, []byte, error)
+}
+
+func newHTTPClientFactory(tr CancelableTransport, cr CheckRedirectFunc, headerTimeout time.Duration) httpClientFactory {
+ return func(ep url.URL) httpClient {
+ return &redirectFollowingHTTPClient{
+ checkRedirect: cr,
+ client: &simpleHTTPClient{
+ transport: tr,
+ endpoint: ep,
+ headerTimeout: headerTimeout,
+ },
+ }
+ }
+}
+
+type credentials struct {
+ username string
+ password string
+}
+
+type httpClientFactory func(url.URL) httpClient
+
+type httpAction interface {
+ HTTPRequest(url.URL) *http.Request
+}
+
+type httpClusterClient struct {
+ clientFactory httpClientFactory
+ endpoints []url.URL
+ pinned int
+ credentials *credentials
+ sync.RWMutex
+ rand *rand.Rand
+ selectionMode EndpointSelectionMode
+}
+
+func (c *httpClusterClient) getLeaderEndpoint(ctx context.Context, eps []url.URL) (string, error) {
+ ceps := make([]url.URL, len(eps))
+ copy(ceps, eps)
+
+ // To perform a lookup on the new endpoint list without using the current
+ // client, we'll copy it
+ clientCopy := &httpClusterClient{
+ clientFactory: c.clientFactory,
+ credentials: c.credentials,
+ rand: c.rand,
+
+ pinned: 0,
+ endpoints: ceps,
+ }
+
+ mAPI := NewMembersAPI(clientCopy)
+ leader, err := mAPI.Leader(ctx)
+ if err != nil {
+ return "", err
+ }
+ if len(leader.ClientURLs) == 0 {
+ return "", ErrNoLeaderEndpoint
+ }
+
+ return leader.ClientURLs[0], nil // TODO: how to handle multiple client URLs?
+}
+
+func (c *httpClusterClient) parseEndpoints(eps []string) ([]url.URL, error) {
+ if len(eps) == 0 {
+ return []url.URL{}, ErrNoEndpoints
+ }
+
+ neps := make([]url.URL, len(eps))
+ for i, ep := range eps {
+ u, err := url.Parse(ep)
+ if err != nil {
+ return []url.URL{}, err
+ }
+ neps[i] = *u
+ }
+ return neps, nil
+}
+
+func (c *httpClusterClient) SetEndpoints(eps []string) error {
+ neps, err := c.parseEndpoints(eps)
+ if err != nil {
+ return err
+ }
+
+ c.Lock()
+ defer c.Unlock()
+
+ c.endpoints = shuffleEndpoints(c.rand, neps)
+ // We're not doing anything for PrioritizeLeader here. This is
+ // due to not having a context meaning we can't call getLeaderEndpoint
+ // However, if you're using PrioritizeLeader, you've already been told
+ // to regularly call sync, where we do have a ctx, and can figure the
+ // leader. PrioritizeLeader is also quite a loose guarantee, so deal
+ // with it
+ c.pinned = 0
+
+ return nil
+}
+
+func (c *httpClusterClient) Do(ctx context.Context, act httpAction) (*http.Response, []byte, error) {
+ action := act
+ c.RLock()
+ leps := len(c.endpoints)
+ eps := make([]url.URL, leps)
+ n := copy(eps, c.endpoints)
+ pinned := c.pinned
+
+ if c.credentials != nil {
+ action = &authedAction{
+ act: act,
+ credentials: *c.credentials,
+ }
+ }
+ c.RUnlock()
+
+ if leps == 0 {
+ return nil, nil, ErrNoEndpoints
+ }
+
+ if leps != n {
+ return nil, nil, errors.New("unable to pick endpoint: copy failed")
+ }
+
+ var resp *http.Response
+ var body []byte
+ var err error
+ cerr := &ClusterError{}
+ isOneShot := ctx.Value(&oneShotCtxValue) != nil
+
+ for i := pinned; i < leps+pinned; i++ {
+ k := i % leps
+ hc := c.clientFactory(eps[k])
+ resp, body, err = hc.Do(ctx, action)
+ if err != nil {
+ cerr.Errors = append(cerr.Errors, err)
+ if err == ctx.Err() {
+ return nil, nil, ctx.Err()
+ }
+ if err == context.Canceled || err == context.DeadlineExceeded {
+ return nil, nil, err
+ }
+ } else if resp.StatusCode/100 == 5 {
+ switch resp.StatusCode {
+ case http.StatusInternalServerError, http.StatusServiceUnavailable:
+ // TODO: make sure this is a no leader response
+ cerr.Errors = append(cerr.Errors, fmt.Errorf("client: etcd member %s has no leader", eps[k].String()))
+ default:
+ cerr.Errors = append(cerr.Errors, fmt.Errorf("client: etcd member %s returns server error [%s]", eps[k].String(), http.StatusText(resp.StatusCode)))
+ }
+ err = cerr.Errors[0]
+ }
+ if err != nil {
+ if !isOneShot {
+ continue
+ }
+ c.Lock()
+ c.pinned = (k + 1) % leps
+ c.Unlock()
+ return nil, nil, err
+ }
+ if k != pinned {
+ c.Lock()
+ c.pinned = k
+ c.Unlock()
+ }
+ return resp, body, nil
+ }
+
+ return nil, nil, cerr
+}
+
+func (c *httpClusterClient) Endpoints() []string {
+ c.RLock()
+ defer c.RUnlock()
+
+ eps := make([]string, len(c.endpoints))
+ for i, ep := range c.endpoints {
+ eps[i] = ep.String()
+ }
+
+ return eps
+}
+
+func (c *httpClusterClient) Sync(ctx context.Context) error {
+ mAPI := NewMembersAPI(c)
+ ms, err := mAPI.List(ctx)
+ if err != nil {
+ return err
+ }
+
+ var eps []string
+ for _, m := range ms {
+ eps = append(eps, m.ClientURLs...)
+ }
+
+ neps, err := c.parseEndpoints(eps)
+ if err != nil {
+ return err
+ }
+
+ npin := 0
+
+ switch c.selectionMode {
+ case EndpointSelectionRandom:
+ c.RLock()
+ eq := endpointsEqual(c.endpoints, neps)
+ c.RUnlock()
+
+ if eq {
+ return nil
+ }
+ // When items in the endpoint list changes, we choose a new pin
+ neps = shuffleEndpoints(c.rand, neps)
+ case EndpointSelectionPrioritizeLeader:
+ nle, err := c.getLeaderEndpoint(ctx, neps)
+ if err != nil {
+ return ErrNoLeaderEndpoint
+ }
+
+ for i, n := range neps {
+ if n.String() == nle {
+ npin = i
+ break
+ }
+ }
+ default:
+ return fmt.Errorf("invalid endpoint selection mode: %d", c.selectionMode)
+ }
+
+ c.Lock()
+ defer c.Unlock()
+ c.endpoints = neps
+ c.pinned = npin
+
+ return nil
+}
+
+func (c *httpClusterClient) AutoSync(ctx context.Context, interval time.Duration) error {
+ ticker := time.NewTicker(interval)
+ defer ticker.Stop()
+ for {
+ err := c.Sync(ctx)
+ if err != nil {
+ return err
+ }
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-ticker.C:
+ }
+ }
+}
+
+func (c *httpClusterClient) GetVersion(ctx context.Context) (*version.Versions, error) {
+ act := &getAction{Prefix: "/version"}
+
+ resp, body, err := c.Do(ctx, act)
+ if err != nil {
+ return nil, err
+ }
+
+ switch resp.StatusCode {
+ case http.StatusOK:
+ if len(body) == 0 {
+ return nil, ErrEmptyBody
+ }
+ var vresp version.Versions
+ if err := json.Unmarshal(body, &vresp); err != nil {
+ return nil, ErrInvalidJSON
+ }
+ return &vresp, nil
+ default:
+ var etcdErr Error
+ if err := json.Unmarshal(body, &etcdErr); err != nil {
+ return nil, ErrInvalidJSON
+ }
+ return nil, etcdErr
+ }
+}
+
+type roundTripResponse struct {
+ resp *http.Response
+ err error
+}
+
+type simpleHTTPClient struct {
+ transport CancelableTransport
+ endpoint url.URL
+ headerTimeout time.Duration
+}
+
+func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Response, []byte, error) {
+ req := act.HTTPRequest(c.endpoint)
+
+ if err := printcURL(req); err != nil {
+ return nil, nil, err
+ }
+
+ isWait := false
+ if req != nil && req.URL != nil {
+ ws := req.URL.Query().Get("wait")
+ if len(ws) != 0 {
+ var err error
+ isWait, err = strconv.ParseBool(ws)
+ if err != nil {
+ return nil, nil, fmt.Errorf("wrong wait value %s (%v for %+v)", ws, err, req)
+ }
+ }
+ }
+
+ var hctx context.Context
+ var hcancel context.CancelFunc
+ if !isWait && c.headerTimeout > 0 {
+ hctx, hcancel = context.WithTimeout(ctx, c.headerTimeout)
+ } else {
+ hctx, hcancel = context.WithCancel(ctx)
+ }
+ defer hcancel()
+
+ reqcancel := requestCanceler(c.transport, req)
+
+ rtchan := make(chan roundTripResponse, 1)
+ go func() {
+ resp, err := c.transport.RoundTrip(req)
+ rtchan <- roundTripResponse{resp: resp, err: err}
+ close(rtchan)
+ }()
+
+ var resp *http.Response
+ var err error
+
+ select {
+ case rtresp := <-rtchan:
+ resp, err = rtresp.resp, rtresp.err
+ case <-hctx.Done():
+ // cancel and wait for request to actually exit before continuing
+ reqcancel()
+ rtresp := <-rtchan
+ resp = rtresp.resp
+ switch {
+ case ctx.Err() != nil:
+ err = ctx.Err()
+ case hctx.Err() != nil:
+ err = fmt.Errorf("client: endpoint %s exceeded header timeout", c.endpoint.String())
+ default:
+ panic("failed to get error from context")
+ }
+ }
+
+ // always check for resp nil-ness to deal with possible
+ // race conditions between channels above
+ defer func() {
+ if resp != nil {
+ resp.Body.Close()
+ }
+ }()
+
+ if err != nil {
+ return nil, nil, err
+ }
+
+ var body []byte
+ done := make(chan struct{})
+ go func() {
+ body, err = ioutil.ReadAll(resp.Body)
+ done <- struct{}{}
+ }()
+
+ select {
+ case <-ctx.Done():
+ resp.Body.Close()
+ <-done
+ return nil, nil, ctx.Err()
+ case <-done:
+ }
+
+ return resp, body, err
+}
+
+type authedAction struct {
+ act httpAction
+ credentials credentials
+}
+
+func (a *authedAction) HTTPRequest(url url.URL) *http.Request {
+ r := a.act.HTTPRequest(url)
+ r.SetBasicAuth(a.credentials.username, a.credentials.password)
+ return r
+}
+
+type redirectFollowingHTTPClient struct {
+ client httpClient
+ checkRedirect CheckRedirectFunc
+}
+
+func (r *redirectFollowingHTTPClient) Do(ctx context.Context, act httpAction) (*http.Response, []byte, error) {
+ next := act
+ for i := 0; i < 100; i++ {
+ if i > 0 {
+ if err := r.checkRedirect(i); err != nil {
+ return nil, nil, err
+ }
+ }
+ resp, body, err := r.client.Do(ctx, next)
+ if err != nil {
+ return nil, nil, err
+ }
+ if resp.StatusCode/100 == 3 {
+ hdr := resp.Header.Get("Location")
+ if hdr == "" {
+ return nil, nil, fmt.Errorf("Location header not set")
+ }
+ loc, err := url.Parse(hdr)
+ if err != nil {
+ return nil, nil, fmt.Errorf("Location header not valid URL: %s", hdr)
+ }
+ next = &redirectedHTTPAction{
+ action: act,
+ location: *loc,
+ }
+ continue
+ }
+ return resp, body, nil
+ }
+
+ return nil, nil, errTooManyRedirectChecks
+}
+
+type redirectedHTTPAction struct {
+ action httpAction
+ location url.URL
+}
+
+func (r *redirectedHTTPAction) HTTPRequest(ep url.URL) *http.Request {
+ orig := r.action.HTTPRequest(ep)
+ orig.URL = &r.location
+ return orig
+}
+
+func shuffleEndpoints(r *rand.Rand, eps []url.URL) []url.URL {
+ // copied from Go 1.9<= rand.Rand.Perm
+ n := len(eps)
+ p := make([]int, n)
+ for i := 0; i < n; i++ {
+ j := r.Intn(i + 1)
+ p[i] = p[j]
+ p[j] = i
+ }
+ neps := make([]url.URL, n)
+ for i, k := range p {
+ neps[i] = eps[k]
+ }
+ return neps
+}
+
+func endpointsEqual(left, right []url.URL) bool {
+ if len(left) != len(right) {
+ return false
+ }
+
+ sLeft := make([]string, len(left))
+ sRight := make([]string, len(right))
+ for i, l := range left {
+ sLeft[i] = l.String()
+ }
+ for i, r := range right {
+ sRight[i] = r.String()
+ }
+
+ sort.Strings(sLeft)
+ sort.Strings(sRight)
+ for i := range sLeft {
+ if sLeft[i] != sRight[i] {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/coreos/etcd/client/cluster_error.go b/vendor/github.com/coreos/etcd/client/cluster_error.go
new file mode 100644
index 00000000..34618cdb
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/cluster_error.go
@@ -0,0 +1,37 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import "fmt"
+
+type ClusterError struct {
+ Errors []error
+}
+
+func (ce *ClusterError) Error() string {
+ s := ErrClusterUnavailable.Error()
+ for i, e := range ce.Errors {
+ s += fmt.Sprintf("; error #%d: %s\n", i, e)
+ }
+ return s
+}
+
+func (ce *ClusterError) Detail() string {
+ s := ""
+ for i, e := range ce.Errors {
+ s += fmt.Sprintf("error #%d: %s\n", i, e)
+ }
+ return s
+}
diff --git a/vendor/github.com/coreos/etcd/client/curl.go b/vendor/github.com/coreos/etcd/client/curl.go
new file mode 100644
index 00000000..c8bc9fba
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/curl.go
@@ -0,0 +1,70 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "os"
+)
+
+var (
+ cURLDebug = false
+)
+
+func EnablecURLDebug() {
+ cURLDebug = true
+}
+
+func DisablecURLDebug() {
+ cURLDebug = false
+}
+
+// printcURL prints the cURL equivalent request to stderr.
+// It returns an error if the body of the request cannot
+// be read.
+// The caller MUST cancel the request if there is an error.
+func printcURL(req *http.Request) error {
+ if !cURLDebug {
+ return nil
+ }
+ var (
+ command string
+ b []byte
+ err error
+ )
+
+ if req.URL != nil {
+ command = fmt.Sprintf("curl -X %s %s", req.Method, req.URL.String())
+ }
+
+ if req.Body != nil {
+ b, err = ioutil.ReadAll(req.Body)
+ if err != nil {
+ return err
+ }
+ command += fmt.Sprintf(" -d %q", string(b))
+ }
+
+ fmt.Fprintf(os.Stderr, "cURL Command: %s\n", command)
+
+ // reset body
+ body := bytes.NewBuffer(b)
+ req.Body = ioutil.NopCloser(body)
+
+ return nil
+}
diff --git a/vendor/github.com/coreos/etcd/client/discover.go b/vendor/github.com/coreos/etcd/client/discover.go
new file mode 100644
index 00000000..442e35fe
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/discover.go
@@ -0,0 +1,40 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "github.com/coreos/etcd/pkg/srv"
+)
+
+// Discoverer is an interface that wraps the Discover method.
+type Discoverer interface {
+ // Discover looks up the etcd servers for the domain.
+ Discover(domain string) ([]string, error)
+}
+
+type srvDiscover struct{}
+
+// NewSRVDiscover constructs a new Discoverer that uses the stdlib to lookup SRV records.
+func NewSRVDiscover() Discoverer {
+ return &srvDiscover{}
+}
+
+func (d *srvDiscover) Discover(domain string) ([]string, error) {
+ srvs, err := srv.GetClient("etcd-client", domain)
+ if err != nil {
+ return nil, err
+ }
+ return srvs.Endpoints, nil
+}
diff --git a/vendor/github.com/coreos/etcd/client/doc.go b/vendor/github.com/coreos/etcd/client/doc.go
new file mode 100644
index 00000000..ad4eca4e
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/doc.go
@@ -0,0 +1,73 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+Package client provides bindings for the etcd APIs.
+
+Create a Config and exchange it for a Client:
+
+ import (
+ "net/http"
+ "context"
+
+ "github.com/coreos/etcd/client"
+ )
+
+ cfg := client.Config{
+ Endpoints: []string{"http://127.0.0.1:2379"},
+ Transport: DefaultTransport,
+ }
+
+ c, err := client.New(cfg)
+ if err != nil {
+ // handle error
+ }
+
+Clients are safe for concurrent use by multiple goroutines.
+
+Create a KeysAPI using the Client, then use it to interact with etcd:
+
+ kAPI := client.NewKeysAPI(c)
+
+ // create a new key /foo with the value "bar"
+ _, err = kAPI.Create(context.Background(), "/foo", "bar")
+ if err != nil {
+ // handle error
+ }
+
+ // delete the newly created key only if the value is still "bar"
+ _, err = kAPI.Delete(context.Background(), "/foo", &DeleteOptions{PrevValue: "bar"})
+ if err != nil {
+ // handle error
+ }
+
+Use a custom context to set timeouts on your operations:
+
+ import "time"
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ // set a new key, ignoring its previous state
+ _, err := kAPI.Set(ctx, "/ping", "pong", nil)
+ if err != nil {
+ if err == context.DeadlineExceeded {
+ // request took longer than 5s
+ } else {
+ // handle error
+ }
+ }
+
+*/
+package client
diff --git a/vendor/github.com/coreos/etcd/client/keys.generated.go b/vendor/github.com/coreos/etcd/client/keys.generated.go
new file mode 100644
index 00000000..237fdbe8
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/keys.generated.go
@@ -0,0 +1,5218 @@
+// ************************************************************
+// DO NOT EDIT.
+// THIS FILE IS AUTO-GENERATED BY codecgen.
+// ************************************************************
+
+package client
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "runtime"
+ time "time"
+
+ codec1978 "github.com/ugorji/go/codec"
+)
+
+const (
+ // ----- content types ----
+ codecSelferC_UTF87612 = 1
+ codecSelferC_RAW7612 = 0
+ // ----- value types used ----
+ codecSelferValueTypeArray7612 = 10
+ codecSelferValueTypeMap7612 = 9
+ // ----- containerStateValues ----
+ codecSelfer_containerMapKey7612 = 2
+ codecSelfer_containerMapValue7612 = 3
+ codecSelfer_containerMapEnd7612 = 4
+ codecSelfer_containerArrayElem7612 = 6
+ codecSelfer_containerArrayEnd7612 = 7
+)
+
+var (
+ codecSelferBitsize7612 = uint8(reflect.TypeOf(uint(0)).Bits())
+ codecSelferOnlyMapOrArrayEncodeToStructErr7612 = errors.New(`only encoded map or array can be decoded into a struct`)
+)
+
+type codecSelfer7612 struct{}
+
+func init() {
+ if codec1978.GenVersion != 8 {
+ _, file, _, _ := runtime.Caller(0)
+ err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v",
+ 8, codec1978.GenVersion, file)
+ panic(err)
+ }
+ if false { // reference the types, but skip this branch at build/run time
+ var v0 time.Duration
+ _ = v0
+ }
+}
+
+func (x *Error) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(4)
+ } else {
+ r.WriteMapStart(4)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeInt(int64(x.Code))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("errorCode"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeInt(int64(x.Code))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Message))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("message"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Message))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Cause))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("cause"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Cause))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.Index))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("index"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.Index))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *Error) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *Error) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "errorCode":
+ if r.TryDecodeAsNil() {
+ x.Code = 0
+ } else {
+ yyv4 := &x.Code
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*int)(yyv4)) = int(r.DecodeInt(codecSelferBitsize7612))
+ }
+ }
+ case "message":
+ if r.TryDecodeAsNil() {
+ x.Message = ""
+ } else {
+ yyv6 := &x.Message
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*string)(yyv6)) = r.DecodeString()
+ }
+ }
+ case "cause":
+ if r.TryDecodeAsNil() {
+ x.Cause = ""
+ } else {
+ yyv8 := &x.Cause
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*string)(yyv8)) = r.DecodeString()
+ }
+ }
+ case "index":
+ if r.TryDecodeAsNil() {
+ x.Index = 0
+ } else {
+ yyv10 := &x.Index
+ yym11 := z.DecBinary()
+ _ = yym11
+ if false {
+ } else {
+ *((*uint64)(yyv10)) = uint64(r.DecodeUint(64))
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *Error) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj12 int
+ var yyb12 bool
+ var yyhl12 bool = l >= 0
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Code = 0
+ } else {
+ yyv13 := &x.Code
+ yym14 := z.DecBinary()
+ _ = yym14
+ if false {
+ } else {
+ *((*int)(yyv13)) = int(r.DecodeInt(codecSelferBitsize7612))
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Message = ""
+ } else {
+ yyv15 := &x.Message
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else {
+ *((*string)(yyv15)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Cause = ""
+ } else {
+ yyv17 := &x.Cause
+ yym18 := z.DecBinary()
+ _ = yym18
+ if false {
+ } else {
+ *((*string)(yyv17)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Index = 0
+ } else {
+ yyv19 := &x.Index
+ yym20 := z.DecBinary()
+ _ = yym20
+ if false {
+ } else {
+ *((*uint64)(yyv19)) = uint64(r.DecodeUint(64))
+ }
+ }
+ for {
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj12-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x PrevExistType) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x))
+ }
+}
+
+func (x *PrevExistType) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ *((*string)(x)) = r.DecodeString()
+ }
+}
+
+func (x *WatcherOptions) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(2)
+ } else {
+ r.WriteMapStart(2)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.AfterIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("AfterIndex"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.AfterIndex))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Recursive"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *WatcherOptions) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *WatcherOptions) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "AfterIndex":
+ if r.TryDecodeAsNil() {
+ x.AfterIndex = 0
+ } else {
+ yyv4 := &x.AfterIndex
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*uint64)(yyv4)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "Recursive":
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv6 := &x.Recursive
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*bool)(yyv6)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *WatcherOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj8 int
+ var yyb8 bool
+ var yyhl8 bool = l >= 0
+ yyj8++
+ if yyhl8 {
+ yyb8 = yyj8 > l
+ } else {
+ yyb8 = r.CheckBreak()
+ }
+ if yyb8 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.AfterIndex = 0
+ } else {
+ yyv9 := &x.AfterIndex
+ yym10 := z.DecBinary()
+ _ = yym10
+ if false {
+ } else {
+ *((*uint64)(yyv9)) = uint64(r.DecodeUint(64))
+ }
+ }
+ yyj8++
+ if yyhl8 {
+ yyb8 = yyj8 > l
+ } else {
+ yyb8 = r.CheckBreak()
+ }
+ if yyb8 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv11 := &x.Recursive
+ yym12 := z.DecBinary()
+ _ = yym12
+ if false {
+ } else {
+ *((*bool)(yyv11)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj8++
+ if yyhl8 {
+ yyb8 = yyj8 > l
+ } else {
+ yyb8 = r.CheckBreak()
+ }
+ if yyb8 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj8-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *CreateInOrderOptions) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(1)
+ } else {
+ r.WriteMapStart(1)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("TTL"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *CreateInOrderOptions) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *CreateInOrderOptions) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "TTL":
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv4 := &x.TTL
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv4) {
+ } else {
+ *((*int64)(yyv4)) = int64(r.DecodeInt(64))
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *CreateInOrderOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj6 int
+ var yyb6 bool
+ var yyhl6 bool = l >= 0
+ yyj6++
+ if yyhl6 {
+ yyb6 = yyj6 > l
+ } else {
+ yyb6 = r.CheckBreak()
+ }
+ if yyb6 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv7 := &x.TTL
+ yym8 := z.DecBinary()
+ _ = yym8
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv7) {
+ } else {
+ *((*int64)(yyv7)) = int64(r.DecodeInt(64))
+ }
+ }
+ for {
+ yyj6++
+ if yyhl6 {
+ yyb6 = yyj6 > l
+ } else {
+ yyb6 = r.CheckBreak()
+ }
+ if yyb6 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj6-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *SetOptions) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(7)
+ } else {
+ r.WriteMapStart(7)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevValue"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevIndex"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ x.PrevExist.CodecEncodeSelf(e)
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevExist"))
+ r.WriteMapElemValue()
+ x.PrevExist.CodecEncodeSelf(e)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("TTL"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym16 := z.EncBinary()
+ _ = yym16
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Refresh))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Refresh"))
+ r.WriteMapElemValue()
+ yym17 := z.EncBinary()
+ _ = yym17
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Refresh))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym19 := z.EncBinary()
+ _ = yym19
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Dir"))
+ r.WriteMapElemValue()
+ yym20 := z.EncBinary()
+ _ = yym20
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym22 := z.EncBinary()
+ _ = yym22
+ if false {
+ } else {
+ r.EncodeBool(bool(x.NoValueOnSuccess))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("NoValueOnSuccess"))
+ r.WriteMapElemValue()
+ yym23 := z.EncBinary()
+ _ = yym23
+ if false {
+ } else {
+ r.EncodeBool(bool(x.NoValueOnSuccess))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *SetOptions) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *SetOptions) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "PrevValue":
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv4 := &x.PrevValue
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "PrevIndex":
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv6 := &x.PrevIndex
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*uint64)(yyv6)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "PrevExist":
+ if r.TryDecodeAsNil() {
+ x.PrevExist = ""
+ } else {
+ yyv8 := &x.PrevExist
+ yyv8.CodecDecodeSelf(d)
+ }
+ case "TTL":
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv9 := &x.TTL
+ yym10 := z.DecBinary()
+ _ = yym10
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv9) {
+ } else {
+ *((*int64)(yyv9)) = int64(r.DecodeInt(64))
+ }
+ }
+ case "Refresh":
+ if r.TryDecodeAsNil() {
+ x.Refresh = false
+ } else {
+ yyv11 := &x.Refresh
+ yym12 := z.DecBinary()
+ _ = yym12
+ if false {
+ } else {
+ *((*bool)(yyv11)) = r.DecodeBool()
+ }
+ }
+ case "Dir":
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv13 := &x.Dir
+ yym14 := z.DecBinary()
+ _ = yym14
+ if false {
+ } else {
+ *((*bool)(yyv13)) = r.DecodeBool()
+ }
+ }
+ case "NoValueOnSuccess":
+ if r.TryDecodeAsNil() {
+ x.NoValueOnSuccess = false
+ } else {
+ yyv15 := &x.NoValueOnSuccess
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else {
+ *((*bool)(yyv15)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *SetOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj17 int
+ var yyb17 bool
+ var yyhl17 bool = l >= 0
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv18 := &x.PrevValue
+ yym19 := z.DecBinary()
+ _ = yym19
+ if false {
+ } else {
+ *((*string)(yyv18)) = r.DecodeString()
+ }
+ }
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv20 := &x.PrevIndex
+ yym21 := z.DecBinary()
+ _ = yym21
+ if false {
+ } else {
+ *((*uint64)(yyv20)) = uint64(r.DecodeUint(64))
+ }
+ }
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevExist = ""
+ } else {
+ yyv22 := &x.PrevExist
+ yyv22.CodecDecodeSelf(d)
+ }
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv23 := &x.TTL
+ yym24 := z.DecBinary()
+ _ = yym24
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv23) {
+ } else {
+ *((*int64)(yyv23)) = int64(r.DecodeInt(64))
+ }
+ }
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Refresh = false
+ } else {
+ yyv25 := &x.Refresh
+ yym26 := z.DecBinary()
+ _ = yym26
+ if false {
+ } else {
+ *((*bool)(yyv25)) = r.DecodeBool()
+ }
+ }
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv27 := &x.Dir
+ yym28 := z.DecBinary()
+ _ = yym28
+ if false {
+ } else {
+ *((*bool)(yyv27)) = r.DecodeBool()
+ }
+ }
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.NoValueOnSuccess = false
+ } else {
+ yyv29 := &x.NoValueOnSuccess
+ yym30 := z.DecBinary()
+ _ = yym30
+ if false {
+ } else {
+ *((*bool)(yyv29)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj17++
+ if yyhl17 {
+ yyb17 = yyj17 > l
+ } else {
+ yyb17 = r.CheckBreak()
+ }
+ if yyb17 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj17-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *GetOptions) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(3)
+ } else {
+ r.WriteMapStart(3)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Recursive"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Sort))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Sort"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Sort))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Quorum))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Quorum"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Quorum))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *GetOptions) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *GetOptions) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "Recursive":
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv4 := &x.Recursive
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*bool)(yyv4)) = r.DecodeBool()
+ }
+ }
+ case "Sort":
+ if r.TryDecodeAsNil() {
+ x.Sort = false
+ } else {
+ yyv6 := &x.Sort
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*bool)(yyv6)) = r.DecodeBool()
+ }
+ }
+ case "Quorum":
+ if r.TryDecodeAsNil() {
+ x.Quorum = false
+ } else {
+ yyv8 := &x.Quorum
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*bool)(yyv8)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *GetOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj10 int
+ var yyb10 bool
+ var yyhl10 bool = l >= 0
+ yyj10++
+ if yyhl10 {
+ yyb10 = yyj10 > l
+ } else {
+ yyb10 = r.CheckBreak()
+ }
+ if yyb10 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv11 := &x.Recursive
+ yym12 := z.DecBinary()
+ _ = yym12
+ if false {
+ } else {
+ *((*bool)(yyv11)) = r.DecodeBool()
+ }
+ }
+ yyj10++
+ if yyhl10 {
+ yyb10 = yyj10 > l
+ } else {
+ yyb10 = r.CheckBreak()
+ }
+ if yyb10 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Sort = false
+ } else {
+ yyv13 := &x.Sort
+ yym14 := z.DecBinary()
+ _ = yym14
+ if false {
+ } else {
+ *((*bool)(yyv13)) = r.DecodeBool()
+ }
+ }
+ yyj10++
+ if yyhl10 {
+ yyb10 = yyj10 > l
+ } else {
+ yyb10 = r.CheckBreak()
+ }
+ if yyb10 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Quorum = false
+ } else {
+ yyv15 := &x.Quorum
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else {
+ *((*bool)(yyv15)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj10++
+ if yyhl10 {
+ yyb10 = yyj10 > l
+ } else {
+ yyb10 = r.CheckBreak()
+ }
+ if yyb10 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj10-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *DeleteOptions) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(4)
+ } else {
+ r.WriteMapStart(4)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevValue"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevIndex"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Recursive"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Dir"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *DeleteOptions) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *DeleteOptions) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "PrevValue":
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv4 := &x.PrevValue
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "PrevIndex":
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv6 := &x.PrevIndex
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*uint64)(yyv6)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "Recursive":
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv8 := &x.Recursive
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*bool)(yyv8)) = r.DecodeBool()
+ }
+ }
+ case "Dir":
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv10 := &x.Dir
+ yym11 := z.DecBinary()
+ _ = yym11
+ if false {
+ } else {
+ *((*bool)(yyv10)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *DeleteOptions) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj12 int
+ var yyb12 bool
+ var yyhl12 bool = l >= 0
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv13 := &x.PrevValue
+ yym14 := z.DecBinary()
+ _ = yym14
+ if false {
+ } else {
+ *((*string)(yyv13)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv15 := &x.PrevIndex
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else {
+ *((*uint64)(yyv15)) = uint64(r.DecodeUint(64))
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv17 := &x.Recursive
+ yym18 := z.DecBinary()
+ _ = yym18
+ if false {
+ } else {
+ *((*bool)(yyv17)) = r.DecodeBool()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv19 := &x.Dir
+ yym20 := z.DecBinary()
+ _ = yym20
+ if false {
+ } else {
+ *((*bool)(yyv19)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj12-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(3)
+ } else {
+ r.WriteMapStart(3)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Action))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("action"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Action))
+ }
+ }
+ var yyn6 bool
+ if x.Node == nil {
+ yyn6 = true
+ goto LABEL6
+ }
+ LABEL6:
+ if yyr2 || yy2arr2 {
+ if yyn6 {
+ r.WriteArrayElem()
+ r.EncodeNil()
+ } else {
+ r.WriteArrayElem()
+ if x.Node == nil {
+ r.EncodeNil()
+ } else {
+ x.Node.CodecEncodeSelf(e)
+ }
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("node"))
+ r.WriteMapElemValue()
+ if yyn6 {
+ r.EncodeNil()
+ } else {
+ if x.Node == nil {
+ r.EncodeNil()
+ } else {
+ x.Node.CodecEncodeSelf(e)
+ }
+ }
+ }
+ var yyn9 bool
+ if x.PrevNode == nil {
+ yyn9 = true
+ goto LABEL9
+ }
+ LABEL9:
+ if yyr2 || yy2arr2 {
+ if yyn9 {
+ r.WriteArrayElem()
+ r.EncodeNil()
+ } else {
+ r.WriteArrayElem()
+ if x.PrevNode == nil {
+ r.EncodeNil()
+ } else {
+ x.PrevNode.CodecEncodeSelf(e)
+ }
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("prevNode"))
+ r.WriteMapElemValue()
+ if yyn9 {
+ r.EncodeNil()
+ } else {
+ if x.PrevNode == nil {
+ r.EncodeNil()
+ } else {
+ x.PrevNode.CodecEncodeSelf(e)
+ }
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *Response) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *Response) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "action":
+ if r.TryDecodeAsNil() {
+ x.Action = ""
+ } else {
+ yyv4 := &x.Action
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "node":
+ if x.Node == nil {
+ x.Node = new(Node)
+ }
+ if r.TryDecodeAsNil() {
+ if x.Node != nil {
+ x.Node = nil
+ }
+ } else {
+ if x.Node == nil {
+ x.Node = new(Node)
+ }
+ x.Node.CodecDecodeSelf(d)
+ }
+ case "prevNode":
+ if x.PrevNode == nil {
+ x.PrevNode = new(Node)
+ }
+ if r.TryDecodeAsNil() {
+ if x.PrevNode != nil {
+ x.PrevNode = nil
+ }
+ } else {
+ if x.PrevNode == nil {
+ x.PrevNode = new(Node)
+ }
+ x.PrevNode.CodecDecodeSelf(d)
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *Response) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj8 int
+ var yyb8 bool
+ var yyhl8 bool = l >= 0
+ yyj8++
+ if yyhl8 {
+ yyb8 = yyj8 > l
+ } else {
+ yyb8 = r.CheckBreak()
+ }
+ if yyb8 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Action = ""
+ } else {
+ yyv9 := &x.Action
+ yym10 := z.DecBinary()
+ _ = yym10
+ if false {
+ } else {
+ *((*string)(yyv9)) = r.DecodeString()
+ }
+ }
+ if x.Node == nil {
+ x.Node = new(Node)
+ }
+ yyj8++
+ if yyhl8 {
+ yyb8 = yyj8 > l
+ } else {
+ yyb8 = r.CheckBreak()
+ }
+ if yyb8 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ if x.Node != nil {
+ x.Node = nil
+ }
+ } else {
+ if x.Node == nil {
+ x.Node = new(Node)
+ }
+ x.Node.CodecDecodeSelf(d)
+ }
+ if x.PrevNode == nil {
+ x.PrevNode = new(Node)
+ }
+ yyj8++
+ if yyhl8 {
+ yyb8 = yyj8 > l
+ } else {
+ yyb8 = r.CheckBreak()
+ }
+ if yyb8 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ if x.PrevNode != nil {
+ x.PrevNode = nil
+ }
+ } else {
+ if x.PrevNode == nil {
+ x.PrevNode = new(Node)
+ }
+ x.PrevNode.CodecDecodeSelf(d)
+ }
+ for {
+ yyj8++
+ if yyhl8 {
+ yyb8 = yyj8 > l
+ } else {
+ yyb8 = r.CheckBreak()
+ }
+ if yyb8 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj8-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *Node) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ var yyq2 [8]bool
+ _ = yyq2
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ yyq2[1] = x.Dir != false
+ yyq2[6] = x.Expiration != nil
+ yyq2[7] = x.TTL != 0
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(8)
+ } else {
+ var yynn2 = 5
+ for _, b := range yyq2 {
+ if b {
+ yynn2++
+ }
+ }
+ r.WriteMapStart(yynn2)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("key"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ if yyq2[1] {
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ } else {
+ r.EncodeBool(false)
+ }
+ } else {
+ if yyq2[1] {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("dir"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Value))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("value"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Value))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ if x.Nodes == nil {
+ r.EncodeNil()
+ } else {
+ x.Nodes.CodecEncodeSelf(e)
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("nodes"))
+ r.WriteMapElemValue()
+ if x.Nodes == nil {
+ r.EncodeNil()
+ } else {
+ x.Nodes.CodecEncodeSelf(e)
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym16 := z.EncBinary()
+ _ = yym16
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.CreatedIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("createdIndex"))
+ r.WriteMapElemValue()
+ yym17 := z.EncBinary()
+ _ = yym17
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.CreatedIndex))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym19 := z.EncBinary()
+ _ = yym19
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.ModifiedIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("modifiedIndex"))
+ r.WriteMapElemValue()
+ yym20 := z.EncBinary()
+ _ = yym20
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.ModifiedIndex))
+ }
+ }
+ var yyn21 bool
+ if x.Expiration == nil {
+ yyn21 = true
+ goto LABEL21
+ }
+ LABEL21:
+ if yyr2 || yy2arr2 {
+ if yyn21 {
+ r.WriteArrayElem()
+ r.EncodeNil()
+ } else {
+ r.WriteArrayElem()
+ if yyq2[6] {
+ if x.Expiration == nil {
+ r.EncodeNil()
+ } else {
+ yym22 := z.EncBinary()
+ _ = yym22
+ if false {
+ } else if yym23 := z.TimeRtidIfBinc(); yym23 != 0 {
+ r.EncodeBuiltin(yym23, x.Expiration)
+ } else if z.HasExtensions() && z.EncExt(x.Expiration) {
+ } else if yym22 {
+ z.EncBinaryMarshal(x.Expiration)
+ } else if !yym22 && z.IsJSONHandle() {
+ z.EncJSONMarshal(x.Expiration)
+ } else {
+ z.EncFallback(x.Expiration)
+ }
+ }
+ } else {
+ r.EncodeNil()
+ }
+ }
+ } else {
+ if yyq2[6] {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("expiration"))
+ r.WriteMapElemValue()
+ if yyn21 {
+ r.EncodeNil()
+ } else {
+ if x.Expiration == nil {
+ r.EncodeNil()
+ } else {
+ yym24 := z.EncBinary()
+ _ = yym24
+ if false {
+ } else if yym25 := z.TimeRtidIfBinc(); yym25 != 0 {
+ r.EncodeBuiltin(yym25, x.Expiration)
+ } else if z.HasExtensions() && z.EncExt(x.Expiration) {
+ } else if yym24 {
+ z.EncBinaryMarshal(x.Expiration)
+ } else if !yym24 && z.IsJSONHandle() {
+ z.EncJSONMarshal(x.Expiration)
+ } else {
+ z.EncFallback(x.Expiration)
+ }
+ }
+ }
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ if yyq2[7] {
+ yym27 := z.EncBinary()
+ _ = yym27
+ if false {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ } else {
+ r.EncodeInt(0)
+ }
+ } else {
+ if yyq2[7] {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("ttl"))
+ r.WriteMapElemValue()
+ yym28 := z.EncBinary()
+ _ = yym28
+ if false {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *Node) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *Node) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "key":
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv4 := &x.Key
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "dir":
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv6 := &x.Dir
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*bool)(yyv6)) = r.DecodeBool()
+ }
+ }
+ case "value":
+ if r.TryDecodeAsNil() {
+ x.Value = ""
+ } else {
+ yyv8 := &x.Value
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*string)(yyv8)) = r.DecodeString()
+ }
+ }
+ case "nodes":
+ if r.TryDecodeAsNil() {
+ x.Nodes = nil
+ } else {
+ yyv10 := &x.Nodes
+ yyv10.CodecDecodeSelf(d)
+ }
+ case "createdIndex":
+ if r.TryDecodeAsNil() {
+ x.CreatedIndex = 0
+ } else {
+ yyv11 := &x.CreatedIndex
+ yym12 := z.DecBinary()
+ _ = yym12
+ if false {
+ } else {
+ *((*uint64)(yyv11)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "modifiedIndex":
+ if r.TryDecodeAsNil() {
+ x.ModifiedIndex = 0
+ } else {
+ yyv13 := &x.ModifiedIndex
+ yym14 := z.DecBinary()
+ _ = yym14
+ if false {
+ } else {
+ *((*uint64)(yyv13)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "expiration":
+ if x.Expiration == nil {
+ x.Expiration = new(time.Time)
+ }
+ if r.TryDecodeAsNil() {
+ if x.Expiration != nil {
+ x.Expiration = nil
+ }
+ } else {
+ if x.Expiration == nil {
+ x.Expiration = new(time.Time)
+ }
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else if yym17 := z.TimeRtidIfBinc(); yym17 != 0 {
+ r.DecodeBuiltin(yym17, x.Expiration)
+ } else if z.HasExtensions() && z.DecExt(x.Expiration) {
+ } else if yym16 {
+ z.DecBinaryUnmarshal(x.Expiration)
+ } else if !yym16 && z.IsJSONHandle() {
+ z.DecJSONUnmarshal(x.Expiration)
+ } else {
+ z.DecFallback(x.Expiration, false)
+ }
+ }
+ case "ttl":
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv18 := &x.TTL
+ yym19 := z.DecBinary()
+ _ = yym19
+ if false {
+ } else {
+ *((*int64)(yyv18)) = int64(r.DecodeInt(64))
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *Node) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj20 int
+ var yyb20 bool
+ var yyhl20 bool = l >= 0
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv21 := &x.Key
+ yym22 := z.DecBinary()
+ _ = yym22
+ if false {
+ } else {
+ *((*string)(yyv21)) = r.DecodeString()
+ }
+ }
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv23 := &x.Dir
+ yym24 := z.DecBinary()
+ _ = yym24
+ if false {
+ } else {
+ *((*bool)(yyv23)) = r.DecodeBool()
+ }
+ }
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Value = ""
+ } else {
+ yyv25 := &x.Value
+ yym26 := z.DecBinary()
+ _ = yym26
+ if false {
+ } else {
+ *((*string)(yyv25)) = r.DecodeString()
+ }
+ }
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Nodes = nil
+ } else {
+ yyv27 := &x.Nodes
+ yyv27.CodecDecodeSelf(d)
+ }
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.CreatedIndex = 0
+ } else {
+ yyv28 := &x.CreatedIndex
+ yym29 := z.DecBinary()
+ _ = yym29
+ if false {
+ } else {
+ *((*uint64)(yyv28)) = uint64(r.DecodeUint(64))
+ }
+ }
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.ModifiedIndex = 0
+ } else {
+ yyv30 := &x.ModifiedIndex
+ yym31 := z.DecBinary()
+ _ = yym31
+ if false {
+ } else {
+ *((*uint64)(yyv30)) = uint64(r.DecodeUint(64))
+ }
+ }
+ if x.Expiration == nil {
+ x.Expiration = new(time.Time)
+ }
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ if x.Expiration != nil {
+ x.Expiration = nil
+ }
+ } else {
+ if x.Expiration == nil {
+ x.Expiration = new(time.Time)
+ }
+ yym33 := z.DecBinary()
+ _ = yym33
+ if false {
+ } else if yym34 := z.TimeRtidIfBinc(); yym34 != 0 {
+ r.DecodeBuiltin(yym34, x.Expiration)
+ } else if z.HasExtensions() && z.DecExt(x.Expiration) {
+ } else if yym33 {
+ z.DecBinaryUnmarshal(x.Expiration)
+ } else if !yym33 && z.IsJSONHandle() {
+ z.DecJSONUnmarshal(x.Expiration)
+ } else {
+ z.DecFallback(x.Expiration, false)
+ }
+ }
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv35 := &x.TTL
+ yym36 := z.DecBinary()
+ _ = yym36
+ if false {
+ } else {
+ *((*int64)(yyv35)) = int64(r.DecodeInt(64))
+ }
+ }
+ for {
+ yyj20++
+ if yyhl20 {
+ yyb20 = yyj20 > l
+ } else {
+ yyb20 = r.CheckBreak()
+ }
+ if yyb20 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj20-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x Nodes) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ h.encNodes((Nodes)(x), e)
+ }
+ }
+}
+
+func (x *Nodes) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ h.decNodes((*Nodes)(x), d)
+ }
+}
+
+func (x *httpKeysAPI) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(0)
+ } else {
+ r.WriteMapStart(0)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *httpKeysAPI) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *httpKeysAPI) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *httpKeysAPI) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj4 int
+ var yyb4 bool
+ var yyhl4 bool = l >= 0
+ for {
+ yyj4++
+ if yyhl4 {
+ yyb4 = yyj4 > l
+ } else {
+ yyb4 = r.CheckBreak()
+ }
+ if yyb4 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj4-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *httpWatcher) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(0)
+ } else {
+ r.WriteMapStart(0)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *httpWatcher) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *httpWatcher) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *httpWatcher) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj4 int
+ var yyb4 bool
+ var yyhl4 bool = l >= 0
+ for {
+ yyj4++
+ if yyhl4 {
+ yyb4 = yyj4 > l
+ } else {
+ yyb4 = r.CheckBreak()
+ }
+ if yyb4 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj4-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *getAction) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(5)
+ } else {
+ r.WriteMapStart(5)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Prefix"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Key"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Recursive"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Sorted))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Sorted"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Sorted))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym16 := z.EncBinary()
+ _ = yym16
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Quorum))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Quorum"))
+ r.WriteMapElemValue()
+ yym17 := z.EncBinary()
+ _ = yym17
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Quorum))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *getAction) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *getAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "Prefix":
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv4 := &x.Prefix
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "Key":
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv6 := &x.Key
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*string)(yyv6)) = r.DecodeString()
+ }
+ }
+ case "Recursive":
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv8 := &x.Recursive
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*bool)(yyv8)) = r.DecodeBool()
+ }
+ }
+ case "Sorted":
+ if r.TryDecodeAsNil() {
+ x.Sorted = false
+ } else {
+ yyv10 := &x.Sorted
+ yym11 := z.DecBinary()
+ _ = yym11
+ if false {
+ } else {
+ *((*bool)(yyv10)) = r.DecodeBool()
+ }
+ }
+ case "Quorum":
+ if r.TryDecodeAsNil() {
+ x.Quorum = false
+ } else {
+ yyv12 := &x.Quorum
+ yym13 := z.DecBinary()
+ _ = yym13
+ if false {
+ } else {
+ *((*bool)(yyv12)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *getAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj14 int
+ var yyb14 bool
+ var yyhl14 bool = l >= 0
+ yyj14++
+ if yyhl14 {
+ yyb14 = yyj14 > l
+ } else {
+ yyb14 = r.CheckBreak()
+ }
+ if yyb14 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv15 := &x.Prefix
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else {
+ *((*string)(yyv15)) = r.DecodeString()
+ }
+ }
+ yyj14++
+ if yyhl14 {
+ yyb14 = yyj14 > l
+ } else {
+ yyb14 = r.CheckBreak()
+ }
+ if yyb14 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv17 := &x.Key
+ yym18 := z.DecBinary()
+ _ = yym18
+ if false {
+ } else {
+ *((*string)(yyv17)) = r.DecodeString()
+ }
+ }
+ yyj14++
+ if yyhl14 {
+ yyb14 = yyj14 > l
+ } else {
+ yyb14 = r.CheckBreak()
+ }
+ if yyb14 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv19 := &x.Recursive
+ yym20 := z.DecBinary()
+ _ = yym20
+ if false {
+ } else {
+ *((*bool)(yyv19)) = r.DecodeBool()
+ }
+ }
+ yyj14++
+ if yyhl14 {
+ yyb14 = yyj14 > l
+ } else {
+ yyb14 = r.CheckBreak()
+ }
+ if yyb14 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Sorted = false
+ } else {
+ yyv21 := &x.Sorted
+ yym22 := z.DecBinary()
+ _ = yym22
+ if false {
+ } else {
+ *((*bool)(yyv21)) = r.DecodeBool()
+ }
+ }
+ yyj14++
+ if yyhl14 {
+ yyb14 = yyj14 > l
+ } else {
+ yyb14 = r.CheckBreak()
+ }
+ if yyb14 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Quorum = false
+ } else {
+ yyv23 := &x.Quorum
+ yym24 := z.DecBinary()
+ _ = yym24
+ if false {
+ } else {
+ *((*bool)(yyv23)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj14++
+ if yyhl14 {
+ yyb14 = yyj14 > l
+ } else {
+ yyb14 = r.CheckBreak()
+ }
+ if yyb14 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj14-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *waitAction) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(4)
+ } else {
+ r.WriteMapStart(4)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Prefix"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Key"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.WaitIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("WaitIndex"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.WaitIndex))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Recursive"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *waitAction) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *waitAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "Prefix":
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv4 := &x.Prefix
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "Key":
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv6 := &x.Key
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*string)(yyv6)) = r.DecodeString()
+ }
+ }
+ case "WaitIndex":
+ if r.TryDecodeAsNil() {
+ x.WaitIndex = 0
+ } else {
+ yyv8 := &x.WaitIndex
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*uint64)(yyv8)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "Recursive":
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv10 := &x.Recursive
+ yym11 := z.DecBinary()
+ _ = yym11
+ if false {
+ } else {
+ *((*bool)(yyv10)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *waitAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj12 int
+ var yyb12 bool
+ var yyhl12 bool = l >= 0
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv13 := &x.Prefix
+ yym14 := z.DecBinary()
+ _ = yym14
+ if false {
+ } else {
+ *((*string)(yyv13)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv15 := &x.Key
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else {
+ *((*string)(yyv15)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.WaitIndex = 0
+ } else {
+ yyv17 := &x.WaitIndex
+ yym18 := z.DecBinary()
+ _ = yym18
+ if false {
+ } else {
+ *((*uint64)(yyv17)) = uint64(r.DecodeUint(64))
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv19 := &x.Recursive
+ yym20 := z.DecBinary()
+ _ = yym20
+ if false {
+ } else {
+ *((*bool)(yyv19)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj12-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *setAction) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(10)
+ } else {
+ r.WriteMapStart(10)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Prefix"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Key"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Value))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Value"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Value))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevValue"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym16 := z.EncBinary()
+ _ = yym16
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevIndex"))
+ r.WriteMapElemValue()
+ yym17 := z.EncBinary()
+ _ = yym17
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ x.PrevExist.CodecEncodeSelf(e)
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevExist"))
+ r.WriteMapElemValue()
+ x.PrevExist.CodecEncodeSelf(e)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym22 := z.EncBinary()
+ _ = yym22
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("TTL"))
+ r.WriteMapElemValue()
+ yym23 := z.EncBinary()
+ _ = yym23
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym25 := z.EncBinary()
+ _ = yym25
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Refresh))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Refresh"))
+ r.WriteMapElemValue()
+ yym26 := z.EncBinary()
+ _ = yym26
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Refresh))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym28 := z.EncBinary()
+ _ = yym28
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Dir"))
+ r.WriteMapElemValue()
+ yym29 := z.EncBinary()
+ _ = yym29
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym31 := z.EncBinary()
+ _ = yym31
+ if false {
+ } else {
+ r.EncodeBool(bool(x.NoValueOnSuccess))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("NoValueOnSuccess"))
+ r.WriteMapElemValue()
+ yym32 := z.EncBinary()
+ _ = yym32
+ if false {
+ } else {
+ r.EncodeBool(bool(x.NoValueOnSuccess))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *setAction) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *setAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "Prefix":
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv4 := &x.Prefix
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "Key":
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv6 := &x.Key
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*string)(yyv6)) = r.DecodeString()
+ }
+ }
+ case "Value":
+ if r.TryDecodeAsNil() {
+ x.Value = ""
+ } else {
+ yyv8 := &x.Value
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*string)(yyv8)) = r.DecodeString()
+ }
+ }
+ case "PrevValue":
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv10 := &x.PrevValue
+ yym11 := z.DecBinary()
+ _ = yym11
+ if false {
+ } else {
+ *((*string)(yyv10)) = r.DecodeString()
+ }
+ }
+ case "PrevIndex":
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv12 := &x.PrevIndex
+ yym13 := z.DecBinary()
+ _ = yym13
+ if false {
+ } else {
+ *((*uint64)(yyv12)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "PrevExist":
+ if r.TryDecodeAsNil() {
+ x.PrevExist = ""
+ } else {
+ yyv14 := &x.PrevExist
+ yyv14.CodecDecodeSelf(d)
+ }
+ case "TTL":
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv15 := &x.TTL
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv15) {
+ } else {
+ *((*int64)(yyv15)) = int64(r.DecodeInt(64))
+ }
+ }
+ case "Refresh":
+ if r.TryDecodeAsNil() {
+ x.Refresh = false
+ } else {
+ yyv17 := &x.Refresh
+ yym18 := z.DecBinary()
+ _ = yym18
+ if false {
+ } else {
+ *((*bool)(yyv17)) = r.DecodeBool()
+ }
+ }
+ case "Dir":
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv19 := &x.Dir
+ yym20 := z.DecBinary()
+ _ = yym20
+ if false {
+ } else {
+ *((*bool)(yyv19)) = r.DecodeBool()
+ }
+ }
+ case "NoValueOnSuccess":
+ if r.TryDecodeAsNil() {
+ x.NoValueOnSuccess = false
+ } else {
+ yyv21 := &x.NoValueOnSuccess
+ yym22 := z.DecBinary()
+ _ = yym22
+ if false {
+ } else {
+ *((*bool)(yyv21)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *setAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj23 int
+ var yyb23 bool
+ var yyhl23 bool = l >= 0
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv24 := &x.Prefix
+ yym25 := z.DecBinary()
+ _ = yym25
+ if false {
+ } else {
+ *((*string)(yyv24)) = r.DecodeString()
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv26 := &x.Key
+ yym27 := z.DecBinary()
+ _ = yym27
+ if false {
+ } else {
+ *((*string)(yyv26)) = r.DecodeString()
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Value = ""
+ } else {
+ yyv28 := &x.Value
+ yym29 := z.DecBinary()
+ _ = yym29
+ if false {
+ } else {
+ *((*string)(yyv28)) = r.DecodeString()
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv30 := &x.PrevValue
+ yym31 := z.DecBinary()
+ _ = yym31
+ if false {
+ } else {
+ *((*string)(yyv30)) = r.DecodeString()
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv32 := &x.PrevIndex
+ yym33 := z.DecBinary()
+ _ = yym33
+ if false {
+ } else {
+ *((*uint64)(yyv32)) = uint64(r.DecodeUint(64))
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevExist = ""
+ } else {
+ yyv34 := &x.PrevExist
+ yyv34.CodecDecodeSelf(d)
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv35 := &x.TTL
+ yym36 := z.DecBinary()
+ _ = yym36
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv35) {
+ } else {
+ *((*int64)(yyv35)) = int64(r.DecodeInt(64))
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Refresh = false
+ } else {
+ yyv37 := &x.Refresh
+ yym38 := z.DecBinary()
+ _ = yym38
+ if false {
+ } else {
+ *((*bool)(yyv37)) = r.DecodeBool()
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv39 := &x.Dir
+ yym40 := z.DecBinary()
+ _ = yym40
+ if false {
+ } else {
+ *((*bool)(yyv39)) = r.DecodeBool()
+ }
+ }
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.NoValueOnSuccess = false
+ } else {
+ yyv41 := &x.NoValueOnSuccess
+ yym42 := z.DecBinary()
+ _ = yym42
+ if false {
+ } else {
+ *((*bool)(yyv41)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj23++
+ if yyhl23 {
+ yyb23 = yyj23 > l
+ } else {
+ yyb23 = r.CheckBreak()
+ }
+ if yyb23 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj23-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *deleteAction) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(6)
+ } else {
+ r.WriteMapStart(6)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Prefix"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Key"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Key))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevValue"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.PrevValue))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("PrevIndex"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else {
+ r.EncodeUint(uint64(x.PrevIndex))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym16 := z.EncBinary()
+ _ = yym16
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Dir"))
+ r.WriteMapElemValue()
+ yym17 := z.EncBinary()
+ _ = yym17
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Dir))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym19 := z.EncBinary()
+ _ = yym19
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Recursive"))
+ r.WriteMapElemValue()
+ yym20 := z.EncBinary()
+ _ = yym20
+ if false {
+ } else {
+ r.EncodeBool(bool(x.Recursive))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *deleteAction) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *deleteAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "Prefix":
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv4 := &x.Prefix
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "Key":
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv6 := &x.Key
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*string)(yyv6)) = r.DecodeString()
+ }
+ }
+ case "PrevValue":
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv8 := &x.PrevValue
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*string)(yyv8)) = r.DecodeString()
+ }
+ }
+ case "PrevIndex":
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv10 := &x.PrevIndex
+ yym11 := z.DecBinary()
+ _ = yym11
+ if false {
+ } else {
+ *((*uint64)(yyv10)) = uint64(r.DecodeUint(64))
+ }
+ }
+ case "Dir":
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv12 := &x.Dir
+ yym13 := z.DecBinary()
+ _ = yym13
+ if false {
+ } else {
+ *((*bool)(yyv12)) = r.DecodeBool()
+ }
+ }
+ case "Recursive":
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv14 := &x.Recursive
+ yym15 := z.DecBinary()
+ _ = yym15
+ if false {
+ } else {
+ *((*bool)(yyv14)) = r.DecodeBool()
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *deleteAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj16 int
+ var yyb16 bool
+ var yyhl16 bool = l >= 0
+ yyj16++
+ if yyhl16 {
+ yyb16 = yyj16 > l
+ } else {
+ yyb16 = r.CheckBreak()
+ }
+ if yyb16 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv17 := &x.Prefix
+ yym18 := z.DecBinary()
+ _ = yym18
+ if false {
+ } else {
+ *((*string)(yyv17)) = r.DecodeString()
+ }
+ }
+ yyj16++
+ if yyhl16 {
+ yyb16 = yyj16 > l
+ } else {
+ yyb16 = r.CheckBreak()
+ }
+ if yyb16 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Key = ""
+ } else {
+ yyv19 := &x.Key
+ yym20 := z.DecBinary()
+ _ = yym20
+ if false {
+ } else {
+ *((*string)(yyv19)) = r.DecodeString()
+ }
+ }
+ yyj16++
+ if yyhl16 {
+ yyb16 = yyj16 > l
+ } else {
+ yyb16 = r.CheckBreak()
+ }
+ if yyb16 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevValue = ""
+ } else {
+ yyv21 := &x.PrevValue
+ yym22 := z.DecBinary()
+ _ = yym22
+ if false {
+ } else {
+ *((*string)(yyv21)) = r.DecodeString()
+ }
+ }
+ yyj16++
+ if yyhl16 {
+ yyb16 = yyj16 > l
+ } else {
+ yyb16 = r.CheckBreak()
+ }
+ if yyb16 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.PrevIndex = 0
+ } else {
+ yyv23 := &x.PrevIndex
+ yym24 := z.DecBinary()
+ _ = yym24
+ if false {
+ } else {
+ *((*uint64)(yyv23)) = uint64(r.DecodeUint(64))
+ }
+ }
+ yyj16++
+ if yyhl16 {
+ yyb16 = yyj16 > l
+ } else {
+ yyb16 = r.CheckBreak()
+ }
+ if yyb16 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Dir = false
+ } else {
+ yyv25 := &x.Dir
+ yym26 := z.DecBinary()
+ _ = yym26
+ if false {
+ } else {
+ *((*bool)(yyv25)) = r.DecodeBool()
+ }
+ }
+ yyj16++
+ if yyhl16 {
+ yyb16 = yyj16 > l
+ } else {
+ yyb16 = r.CheckBreak()
+ }
+ if yyb16 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Recursive = false
+ } else {
+ yyv27 := &x.Recursive
+ yym28 := z.DecBinary()
+ _ = yym28
+ if false {
+ } else {
+ *((*bool)(yyv27)) = r.DecodeBool()
+ }
+ }
+ for {
+ yyj16++
+ if yyhl16 {
+ yyb16 = yyj16 > l
+ } else {
+ yyb16 = r.CheckBreak()
+ }
+ if yyb16 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj16-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x *createInOrderAction) CodecEncodeSelf(e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ if x == nil {
+ r.EncodeNil()
+ } else {
+ yym1 := z.EncBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x) {
+ } else {
+ yysep2 := !z.EncBinary()
+ yy2arr2 := z.EncBasicHandle().StructToArray
+ _, _ = yysep2, yy2arr2
+ const yyr2 bool = false
+ if yyr2 || yy2arr2 {
+ r.WriteArrayStart(4)
+ } else {
+ r.WriteMapStart(4)
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym4 := z.EncBinary()
+ _ = yym4
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Prefix"))
+ r.WriteMapElemValue()
+ yym5 := z.EncBinary()
+ _ = yym5
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Prefix))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym7 := z.EncBinary()
+ _ = yym7
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Dir))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Dir"))
+ r.WriteMapElemValue()
+ yym8 := z.EncBinary()
+ _ = yym8
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Dir))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym10 := z.EncBinary()
+ _ = yym10
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Value))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("Value"))
+ r.WriteMapElemValue()
+ yym11 := z.EncBinary()
+ _ = yym11
+ if false {
+ } else {
+ r.EncodeString(codecSelferC_UTF87612, string(x.Value))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayElem()
+ yym13 := z.EncBinary()
+ _ = yym13
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ } else {
+ r.WriteMapElemKey()
+ r.EncodeString(codecSelferC_UTF87612, string("TTL"))
+ r.WriteMapElemValue()
+ yym14 := z.EncBinary()
+ _ = yym14
+ if false {
+ } else if z.HasExtensions() && z.EncExt(x.TTL) {
+ } else {
+ r.EncodeInt(int64(x.TTL))
+ }
+ }
+ if yyr2 || yy2arr2 {
+ r.WriteArrayEnd()
+ } else {
+ r.WriteMapEnd()
+ }
+ }
+ }
+}
+
+func (x *createInOrderAction) CodecDecodeSelf(d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ yym1 := z.DecBinary()
+ _ = yym1
+ if false {
+ } else if z.HasExtensions() && z.DecExt(x) {
+ } else {
+ yyct2 := r.ContainerType()
+ if yyct2 == codecSelferValueTypeMap7612 {
+ yyl2 := r.ReadMapStart()
+ if yyl2 == 0 {
+ r.ReadMapEnd()
+ } else {
+ x.codecDecodeSelfFromMap(yyl2, d)
+ }
+ } else if yyct2 == codecSelferValueTypeArray7612 {
+ yyl2 := r.ReadArrayStart()
+ if yyl2 == 0 {
+ r.ReadArrayEnd()
+ } else {
+ x.codecDecodeSelfFromArray(yyl2, d)
+ }
+ } else {
+ panic(codecSelferOnlyMapOrArrayEncodeToStructErr7612)
+ }
+ }
+}
+
+func (x *createInOrderAction) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yys3Slc = z.DecScratchBuffer() // default slice to decode into
+ _ = yys3Slc
+ var yyhl3 bool = l >= 0
+ for yyj3 := 0; ; yyj3++ {
+ if yyhl3 {
+ if yyj3 >= l {
+ break
+ }
+ } else {
+ if r.CheckBreak() {
+ break
+ }
+ }
+ r.ReadMapElemKey()
+ yys3Slc = r.DecodeStringAsBytes()
+ yys3 := string(yys3Slc)
+ r.ReadMapElemValue()
+ switch yys3 {
+ case "Prefix":
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv4 := &x.Prefix
+ yym5 := z.DecBinary()
+ _ = yym5
+ if false {
+ } else {
+ *((*string)(yyv4)) = r.DecodeString()
+ }
+ }
+ case "Dir":
+ if r.TryDecodeAsNil() {
+ x.Dir = ""
+ } else {
+ yyv6 := &x.Dir
+ yym7 := z.DecBinary()
+ _ = yym7
+ if false {
+ } else {
+ *((*string)(yyv6)) = r.DecodeString()
+ }
+ }
+ case "Value":
+ if r.TryDecodeAsNil() {
+ x.Value = ""
+ } else {
+ yyv8 := &x.Value
+ yym9 := z.DecBinary()
+ _ = yym9
+ if false {
+ } else {
+ *((*string)(yyv8)) = r.DecodeString()
+ }
+ }
+ case "TTL":
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv10 := &x.TTL
+ yym11 := z.DecBinary()
+ _ = yym11
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv10) {
+ } else {
+ *((*int64)(yyv10)) = int64(r.DecodeInt(64))
+ }
+ }
+ default:
+ z.DecStructFieldNotFound(-1, yys3)
+ } // end switch yys3
+ } // end for yyj3
+ r.ReadMapEnd()
+}
+
+func (x *createInOrderAction) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+ var yyj12 int
+ var yyb12 bool
+ var yyhl12 bool = l >= 0
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Prefix = ""
+ } else {
+ yyv13 := &x.Prefix
+ yym14 := z.DecBinary()
+ _ = yym14
+ if false {
+ } else {
+ *((*string)(yyv13)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Dir = ""
+ } else {
+ yyv15 := &x.Dir
+ yym16 := z.DecBinary()
+ _ = yym16
+ if false {
+ } else {
+ *((*string)(yyv15)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.Value = ""
+ } else {
+ yyv17 := &x.Value
+ yym18 := z.DecBinary()
+ _ = yym18
+ if false {
+ } else {
+ *((*string)(yyv17)) = r.DecodeString()
+ }
+ }
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ r.ReadArrayEnd()
+ return
+ }
+ r.ReadArrayElem()
+ if r.TryDecodeAsNil() {
+ x.TTL = 0
+ } else {
+ yyv19 := &x.TTL
+ yym20 := z.DecBinary()
+ _ = yym20
+ if false {
+ } else if z.HasExtensions() && z.DecExt(yyv19) {
+ } else {
+ *((*int64)(yyv19)) = int64(r.DecodeInt(64))
+ }
+ }
+ for {
+ yyj12++
+ if yyhl12 {
+ yyb12 = yyj12 > l
+ } else {
+ yyb12 = r.CheckBreak()
+ }
+ if yyb12 {
+ break
+ }
+ r.ReadArrayElem()
+ z.DecStructFieldNotFound(yyj12-1, "")
+ }
+ r.ReadArrayEnd()
+}
+
+func (x codecSelfer7612) encNodes(v Nodes, e *codec1978.Encoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperEncoder(e)
+ _, _, _ = h, z, r
+ r.WriteArrayStart(len(v))
+ for _, yyv1 := range v {
+ r.WriteArrayElem()
+ if yyv1 == nil {
+ r.EncodeNil()
+ } else {
+ yyv1.CodecEncodeSelf(e)
+ }
+ }
+ r.WriteArrayEnd()
+}
+
+func (x codecSelfer7612) decNodes(v *Nodes, d *codec1978.Decoder) {
+ var h codecSelfer7612
+ z, r := codec1978.GenHelperDecoder(d)
+ _, _, _ = h, z, r
+
+ yyv1 := *v
+ yyh1, yyl1 := z.DecSliceHelperStart()
+ var yyc1 bool
+ _ = yyc1
+ if yyl1 == 0 {
+ if yyv1 == nil {
+ yyv1 = []*Node{}
+ yyc1 = true
+ } else if len(yyv1) != 0 {
+ yyv1 = yyv1[:0]
+ yyc1 = true
+ }
+ } else {
+ yyhl1 := yyl1 > 0
+ var yyrl1 int
+ _ = yyrl1
+ if yyhl1 {
+ if yyl1 > cap(yyv1) {
+ yyrl1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 8)
+ if yyrl1 <= cap(yyv1) {
+ yyv1 = yyv1[:yyrl1]
+ } else {
+ yyv1 = make([]*Node, yyrl1)
+ }
+ yyc1 = true
+ } else if yyl1 != len(yyv1) {
+ yyv1 = yyv1[:yyl1]
+ yyc1 = true
+ }
+ }
+ var yyj1 int
+ // var yydn1 bool
+ for ; (yyhl1 && yyj1 < yyl1) || !(yyhl1 || r.CheckBreak()); yyj1++ {
+ if yyj1 == 0 && len(yyv1) == 0 {
+ if yyhl1 {
+ yyrl1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 8)
+ } else {
+ yyrl1 = 8
+ }
+ yyv1 = make([]*Node, yyrl1)
+ yyc1 = true
+ }
+ yyh1.ElemContainerState(yyj1)
+ // yydn1 = r.TryDecodeAsNil()
+
+ // if indefinite, etc, then expand the slice if necessary
+ var yydb1 bool
+ if yyj1 >= len(yyv1) {
+ yyv1 = append(yyv1, nil)
+ yyc1 = true
+
+ }
+ if yydb1 {
+ z.DecSwallow()
+ } else {
+ if r.TryDecodeAsNil() {
+ if yyv1[yyj1] != nil {
+ *yyv1[yyj1] = Node{}
+ }
+ } else {
+ if yyv1[yyj1] == nil {
+ yyv1[yyj1] = new(Node)
+ }
+ yyw2 := yyv1[yyj1]
+ yyw2.CodecDecodeSelf(d)
+ }
+
+ }
+
+ }
+ if yyj1 < len(yyv1) {
+ yyv1 = yyv1[:yyj1]
+ yyc1 = true
+ } else if yyj1 == 0 && yyv1 == nil {
+ yyv1 = make([]*Node, 0)
+ yyc1 = true
+ }
+ }
+ yyh1.End()
+ if yyc1 {
+ *v = yyv1
+ }
+
+}
diff --git a/vendor/github.com/coreos/etcd/client/keys.go b/vendor/github.com/coreos/etcd/client/keys.go
new file mode 100644
index 00000000..8b9fd3f8
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/keys.go
@@ -0,0 +1,681 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+//go:generate codecgen -d 1819 -r "Node|Response|Nodes" -o keys.generated.go keys.go
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/coreos/etcd/pkg/pathutil"
+ "github.com/ugorji/go/codec"
+)
+
+const (
+ ErrorCodeKeyNotFound = 100
+ ErrorCodeTestFailed = 101
+ ErrorCodeNotFile = 102
+ ErrorCodeNotDir = 104
+ ErrorCodeNodeExist = 105
+ ErrorCodeRootROnly = 107
+ ErrorCodeDirNotEmpty = 108
+ ErrorCodeUnauthorized = 110
+
+ ErrorCodePrevValueRequired = 201
+ ErrorCodeTTLNaN = 202
+ ErrorCodeIndexNaN = 203
+ ErrorCodeInvalidField = 209
+ ErrorCodeInvalidForm = 210
+
+ ErrorCodeRaftInternal = 300
+ ErrorCodeLeaderElect = 301
+
+ ErrorCodeWatcherCleared = 400
+ ErrorCodeEventIndexCleared = 401
+)
+
+type Error struct {
+ Code int `json:"errorCode"`
+ Message string `json:"message"`
+ Cause string `json:"cause"`
+ Index uint64 `json:"index"`
+}
+
+func (e Error) Error() string {
+ return fmt.Sprintf("%v: %v (%v) [%v]", e.Code, e.Message, e.Cause, e.Index)
+}
+
+var (
+ ErrInvalidJSON = errors.New("client: response is invalid json. The endpoint is probably not valid etcd cluster endpoint.")
+ ErrEmptyBody = errors.New("client: response body is empty")
+)
+
+// PrevExistType is used to define an existence condition when setting
+// or deleting Nodes.
+type PrevExistType string
+
+const (
+ PrevIgnore = PrevExistType("")
+ PrevExist = PrevExistType("true")
+ PrevNoExist = PrevExistType("false")
+)
+
+var (
+ defaultV2KeysPrefix = "/v2/keys"
+)
+
+// NewKeysAPI builds a KeysAPI that interacts with etcd's key-value
+// API over HTTP.
+func NewKeysAPI(c Client) KeysAPI {
+ return NewKeysAPIWithPrefix(c, defaultV2KeysPrefix)
+}
+
+// NewKeysAPIWithPrefix acts like NewKeysAPI, but allows the caller
+// to provide a custom base URL path. This should only be used in
+// very rare cases.
+func NewKeysAPIWithPrefix(c Client, p string) KeysAPI {
+ return &httpKeysAPI{
+ client: c,
+ prefix: p,
+ }
+}
+
+type KeysAPI interface {
+ // Get retrieves a set of Nodes from etcd
+ Get(ctx context.Context, key string, opts *GetOptions) (*Response, error)
+
+ // Set assigns a new value to a Node identified by a given key. The caller
+ // may define a set of conditions in the SetOptions. If SetOptions.Dir=true
+ // then value is ignored.
+ Set(ctx context.Context, key, value string, opts *SetOptions) (*Response, error)
+
+ // Delete removes a Node identified by the given key, optionally destroying
+ // all of its children as well. The caller may define a set of required
+ // conditions in an DeleteOptions object.
+ Delete(ctx context.Context, key string, opts *DeleteOptions) (*Response, error)
+
+ // Create is an alias for Set w/ PrevExist=false
+ Create(ctx context.Context, key, value string) (*Response, error)
+
+ // CreateInOrder is used to atomically create in-order keys within the given directory.
+ CreateInOrder(ctx context.Context, dir, value string, opts *CreateInOrderOptions) (*Response, error)
+
+ // Update is an alias for Set w/ PrevExist=true
+ Update(ctx context.Context, key, value string) (*Response, error)
+
+ // Watcher builds a new Watcher targeted at a specific Node identified
+ // by the given key. The Watcher may be configured at creation time
+ // through a WatcherOptions object. The returned Watcher is designed
+ // to emit events that happen to a Node, and optionally to its children.
+ Watcher(key string, opts *WatcherOptions) Watcher
+}
+
+type WatcherOptions struct {
+ // AfterIndex defines the index after-which the Watcher should
+ // start emitting events. For example, if a value of 5 is
+ // provided, the first event will have an index >= 6.
+ //
+ // Setting AfterIndex to 0 (default) means that the Watcher
+ // should start watching for events starting at the current
+ // index, whatever that may be.
+ AfterIndex uint64
+
+ // Recursive specifies whether or not the Watcher should emit
+ // events that occur in children of the given keyspace. If set
+ // to false (default), events will be limited to those that
+ // occur for the exact key.
+ Recursive bool
+}
+
+type CreateInOrderOptions struct {
+ // TTL defines a period of time after-which the Node should
+ // expire and no longer exist. Values <= 0 are ignored. Given
+ // that the zero-value is ignored, TTL cannot be used to set
+ // a TTL of 0.
+ TTL time.Duration
+}
+
+type SetOptions struct {
+ // PrevValue specifies what the current value of the Node must
+ // be in order for the Set operation to succeed.
+ //
+ // Leaving this field empty means that the caller wishes to
+ // ignore the current value of the Node. This cannot be used
+ // to compare the Node's current value to an empty string.
+ //
+ // PrevValue is ignored if Dir=true
+ PrevValue string
+
+ // PrevIndex indicates what the current ModifiedIndex of the
+ // Node must be in order for the Set operation to succeed.
+ //
+ // If PrevIndex is set to 0 (default), no comparison is made.
+ PrevIndex uint64
+
+ // PrevExist specifies whether the Node must currently exist
+ // (PrevExist) or not (PrevNoExist). If the caller does not
+ // care about existence, set PrevExist to PrevIgnore, or simply
+ // leave it unset.
+ PrevExist PrevExistType
+
+ // TTL defines a period of time after-which the Node should
+ // expire and no longer exist. Values <= 0 are ignored. Given
+ // that the zero-value is ignored, TTL cannot be used to set
+ // a TTL of 0.
+ TTL time.Duration
+
+ // Refresh set to true means a TTL value can be updated
+ // without firing a watch or changing the node value. A
+ // value must not be provided when refreshing a key.
+ Refresh bool
+
+ // Dir specifies whether or not this Node should be created as a directory.
+ Dir bool
+
+ // NoValueOnSuccess specifies whether the response contains the current value of the Node.
+ // If set, the response will only contain the current value when the request fails.
+ NoValueOnSuccess bool
+}
+
+type GetOptions struct {
+ // Recursive defines whether or not all children of the Node
+ // should be returned.
+ Recursive bool
+
+ // Sort instructs the server whether or not to sort the Nodes.
+ // If true, the Nodes are sorted alphabetically by key in
+ // ascending order (A to z). If false (default), the Nodes will
+ // not be sorted and the ordering used should not be considered
+ // predictable.
+ Sort bool
+
+ // Quorum specifies whether it gets the latest committed value that
+ // has been applied in quorum of members, which ensures external
+ // consistency (or linearizability).
+ Quorum bool
+}
+
+type DeleteOptions struct {
+ // PrevValue specifies what the current value of the Node must
+ // be in order for the Delete operation to succeed.
+ //
+ // Leaving this field empty means that the caller wishes to
+ // ignore the current value of the Node. This cannot be used
+ // to compare the Node's current value to an empty string.
+ PrevValue string
+
+ // PrevIndex indicates what the current ModifiedIndex of the
+ // Node must be in order for the Delete operation to succeed.
+ //
+ // If PrevIndex is set to 0 (default), no comparison is made.
+ PrevIndex uint64
+
+ // Recursive defines whether or not all children of the Node
+ // should be deleted. If set to true, all children of the Node
+ // identified by the given key will be deleted. If left unset
+ // or explicitly set to false, only a single Node will be
+ // deleted.
+ Recursive bool
+
+ // Dir specifies whether or not this Node should be removed as a directory.
+ Dir bool
+}
+
+type Watcher interface {
+ // Next blocks until an etcd event occurs, then returns a Response
+ // representing that event. The behavior of Next depends on the
+ // WatcherOptions used to construct the Watcher. Next is designed to
+ // be called repeatedly, each time blocking until a subsequent event
+ // is available.
+ //
+ // If the provided context is cancelled, Next will return a non-nil
+ // error. Any other failures encountered while waiting for the next
+ // event (connection issues, deserialization failures, etc) will
+ // also result in a non-nil error.
+ Next(context.Context) (*Response, error)
+}
+
+type Response struct {
+ // Action is the name of the operation that occurred. Possible values
+ // include get, set, delete, update, create, compareAndSwap,
+ // compareAndDelete and expire.
+ Action string `json:"action"`
+
+ // Node represents the state of the relevant etcd Node.
+ Node *Node `json:"node"`
+
+ // PrevNode represents the previous state of the Node. PrevNode is non-nil
+ // only if the Node existed before the action occurred and the action
+ // caused a change to the Node.
+ PrevNode *Node `json:"prevNode"`
+
+ // Index holds the cluster-level index at the time the Response was generated.
+ // This index is not tied to the Node(s) contained in this Response.
+ Index uint64 `json:"-"`
+
+ // ClusterID holds the cluster-level ID reported by the server. This
+ // should be different for different etcd clusters.
+ ClusterID string `json:"-"`
+}
+
+type Node struct {
+ // Key represents the unique location of this Node (e.g. "/foo/bar").
+ Key string `json:"key"`
+
+ // Dir reports whether node describes a directory.
+ Dir bool `json:"dir,omitempty"`
+
+ // Value is the current data stored on this Node. If this Node
+ // is a directory, Value will be empty.
+ Value string `json:"value"`
+
+ // Nodes holds the children of this Node, only if this Node is a directory.
+ // This slice of will be arbitrarily deep (children, grandchildren, great-
+ // grandchildren, etc.) if a recursive Get or Watch request were made.
+ Nodes Nodes `json:"nodes"`
+
+ // CreatedIndex is the etcd index at-which this Node was created.
+ CreatedIndex uint64 `json:"createdIndex"`
+
+ // ModifiedIndex is the etcd index at-which this Node was last modified.
+ ModifiedIndex uint64 `json:"modifiedIndex"`
+
+ // Expiration is the server side expiration time of the key.
+ Expiration *time.Time `json:"expiration,omitempty"`
+
+ // TTL is the time to live of the key in second.
+ TTL int64 `json:"ttl,omitempty"`
+}
+
+func (n *Node) String() string {
+ return fmt.Sprintf("{Key: %s, CreatedIndex: %d, ModifiedIndex: %d, TTL: %d}", n.Key, n.CreatedIndex, n.ModifiedIndex, n.TTL)
+}
+
+// TTLDuration returns the Node's TTL as a time.Duration object
+func (n *Node) TTLDuration() time.Duration {
+ return time.Duration(n.TTL) * time.Second
+}
+
+type Nodes []*Node
+
+// interfaces for sorting
+
+func (ns Nodes) Len() int { return len(ns) }
+func (ns Nodes) Less(i, j int) bool { return ns[i].Key < ns[j].Key }
+func (ns Nodes) Swap(i, j int) { ns[i], ns[j] = ns[j], ns[i] }
+
+type httpKeysAPI struct {
+ client httpClient
+ prefix string
+}
+
+func (k *httpKeysAPI) Set(ctx context.Context, key, val string, opts *SetOptions) (*Response, error) {
+ act := &setAction{
+ Prefix: k.prefix,
+ Key: key,
+ Value: val,
+ }
+
+ if opts != nil {
+ act.PrevValue = opts.PrevValue
+ act.PrevIndex = opts.PrevIndex
+ act.PrevExist = opts.PrevExist
+ act.TTL = opts.TTL
+ act.Refresh = opts.Refresh
+ act.Dir = opts.Dir
+ act.NoValueOnSuccess = opts.NoValueOnSuccess
+ }
+
+ doCtx := ctx
+ if act.PrevExist == PrevNoExist {
+ doCtx = context.WithValue(doCtx, &oneShotCtxValue, &oneShotCtxValue)
+ }
+ resp, body, err := k.client.Do(doCtx, act)
+ if err != nil {
+ return nil, err
+ }
+
+ return unmarshalHTTPResponse(resp.StatusCode, resp.Header, body)
+}
+
+func (k *httpKeysAPI) Create(ctx context.Context, key, val string) (*Response, error) {
+ return k.Set(ctx, key, val, &SetOptions{PrevExist: PrevNoExist})
+}
+
+func (k *httpKeysAPI) CreateInOrder(ctx context.Context, dir, val string, opts *CreateInOrderOptions) (*Response, error) {
+ act := &createInOrderAction{
+ Prefix: k.prefix,
+ Dir: dir,
+ Value: val,
+ }
+
+ if opts != nil {
+ act.TTL = opts.TTL
+ }
+
+ resp, body, err := k.client.Do(ctx, act)
+ if err != nil {
+ return nil, err
+ }
+
+ return unmarshalHTTPResponse(resp.StatusCode, resp.Header, body)
+}
+
+func (k *httpKeysAPI) Update(ctx context.Context, key, val string) (*Response, error) {
+ return k.Set(ctx, key, val, &SetOptions{PrevExist: PrevExist})
+}
+
+func (k *httpKeysAPI) Delete(ctx context.Context, key string, opts *DeleteOptions) (*Response, error) {
+ act := &deleteAction{
+ Prefix: k.prefix,
+ Key: key,
+ }
+
+ if opts != nil {
+ act.PrevValue = opts.PrevValue
+ act.PrevIndex = opts.PrevIndex
+ act.Dir = opts.Dir
+ act.Recursive = opts.Recursive
+ }
+
+ doCtx := context.WithValue(ctx, &oneShotCtxValue, &oneShotCtxValue)
+ resp, body, err := k.client.Do(doCtx, act)
+ if err != nil {
+ return nil, err
+ }
+
+ return unmarshalHTTPResponse(resp.StatusCode, resp.Header, body)
+}
+
+func (k *httpKeysAPI) Get(ctx context.Context, key string, opts *GetOptions) (*Response, error) {
+ act := &getAction{
+ Prefix: k.prefix,
+ Key: key,
+ }
+
+ if opts != nil {
+ act.Recursive = opts.Recursive
+ act.Sorted = opts.Sort
+ act.Quorum = opts.Quorum
+ }
+
+ resp, body, err := k.client.Do(ctx, act)
+ if err != nil {
+ return nil, err
+ }
+
+ return unmarshalHTTPResponse(resp.StatusCode, resp.Header, body)
+}
+
+func (k *httpKeysAPI) Watcher(key string, opts *WatcherOptions) Watcher {
+ act := waitAction{
+ Prefix: k.prefix,
+ Key: key,
+ }
+
+ if opts != nil {
+ act.Recursive = opts.Recursive
+ if opts.AfterIndex > 0 {
+ act.WaitIndex = opts.AfterIndex + 1
+ }
+ }
+
+ return &httpWatcher{
+ client: k.client,
+ nextWait: act,
+ }
+}
+
+type httpWatcher struct {
+ client httpClient
+ nextWait waitAction
+}
+
+func (hw *httpWatcher) Next(ctx context.Context) (*Response, error) {
+ for {
+ httpresp, body, err := hw.client.Do(ctx, &hw.nextWait)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := unmarshalHTTPResponse(httpresp.StatusCode, httpresp.Header, body)
+ if err != nil {
+ if err == ErrEmptyBody {
+ continue
+ }
+ return nil, err
+ }
+
+ hw.nextWait.WaitIndex = resp.Node.ModifiedIndex + 1
+ return resp, nil
+ }
+}
+
+// v2KeysURL forms a URL representing the location of a key.
+// The endpoint argument represents the base URL of an etcd
+// server. The prefix is the path needed to route from the
+// provided endpoint's path to the root of the keys API
+// (typically "/v2/keys").
+func v2KeysURL(ep url.URL, prefix, key string) *url.URL {
+ // We concatenate all parts together manually. We cannot use
+ // path.Join because it does not reserve trailing slash.
+ // We call CanonicalURLPath to further cleanup the path.
+ if prefix != "" && prefix[0] != '/' {
+ prefix = "/" + prefix
+ }
+ if key != "" && key[0] != '/' {
+ key = "/" + key
+ }
+ ep.Path = pathutil.CanonicalURLPath(ep.Path + prefix + key)
+ return &ep
+}
+
+type getAction struct {
+ Prefix string
+ Key string
+ Recursive bool
+ Sorted bool
+ Quorum bool
+}
+
+func (g *getAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2KeysURL(ep, g.Prefix, g.Key)
+
+ params := u.Query()
+ params.Set("recursive", strconv.FormatBool(g.Recursive))
+ params.Set("sorted", strconv.FormatBool(g.Sorted))
+ params.Set("quorum", strconv.FormatBool(g.Quorum))
+ u.RawQuery = params.Encode()
+
+ req, _ := http.NewRequest("GET", u.String(), nil)
+ return req
+}
+
+type waitAction struct {
+ Prefix string
+ Key string
+ WaitIndex uint64
+ Recursive bool
+}
+
+func (w *waitAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2KeysURL(ep, w.Prefix, w.Key)
+
+ params := u.Query()
+ params.Set("wait", "true")
+ params.Set("waitIndex", strconv.FormatUint(w.WaitIndex, 10))
+ params.Set("recursive", strconv.FormatBool(w.Recursive))
+ u.RawQuery = params.Encode()
+
+ req, _ := http.NewRequest("GET", u.String(), nil)
+ return req
+}
+
+type setAction struct {
+ Prefix string
+ Key string
+ Value string
+ PrevValue string
+ PrevIndex uint64
+ PrevExist PrevExistType
+ TTL time.Duration
+ Refresh bool
+ Dir bool
+ NoValueOnSuccess bool
+}
+
+func (a *setAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2KeysURL(ep, a.Prefix, a.Key)
+
+ params := u.Query()
+ form := url.Values{}
+
+ // we're either creating a directory or setting a key
+ if a.Dir {
+ params.Set("dir", strconv.FormatBool(a.Dir))
+ } else {
+ // These options are only valid for setting a key
+ if a.PrevValue != "" {
+ params.Set("prevValue", a.PrevValue)
+ }
+ form.Add("value", a.Value)
+ }
+
+ // Options which apply to both setting a key and creating a dir
+ if a.PrevIndex != 0 {
+ params.Set("prevIndex", strconv.FormatUint(a.PrevIndex, 10))
+ }
+ if a.PrevExist != PrevIgnore {
+ params.Set("prevExist", string(a.PrevExist))
+ }
+ if a.TTL > 0 {
+ form.Add("ttl", strconv.FormatUint(uint64(a.TTL.Seconds()), 10))
+ }
+
+ if a.Refresh {
+ form.Add("refresh", "true")
+ }
+ if a.NoValueOnSuccess {
+ params.Set("noValueOnSuccess", strconv.FormatBool(a.NoValueOnSuccess))
+ }
+
+ u.RawQuery = params.Encode()
+ body := strings.NewReader(form.Encode())
+
+ req, _ := http.NewRequest("PUT", u.String(), body)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+
+ return req
+}
+
+type deleteAction struct {
+ Prefix string
+ Key string
+ PrevValue string
+ PrevIndex uint64
+ Dir bool
+ Recursive bool
+}
+
+func (a *deleteAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2KeysURL(ep, a.Prefix, a.Key)
+
+ params := u.Query()
+ if a.PrevValue != "" {
+ params.Set("prevValue", a.PrevValue)
+ }
+ if a.PrevIndex != 0 {
+ params.Set("prevIndex", strconv.FormatUint(a.PrevIndex, 10))
+ }
+ if a.Dir {
+ params.Set("dir", "true")
+ }
+ if a.Recursive {
+ params.Set("recursive", "true")
+ }
+ u.RawQuery = params.Encode()
+
+ req, _ := http.NewRequest("DELETE", u.String(), nil)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+
+ return req
+}
+
+type createInOrderAction struct {
+ Prefix string
+ Dir string
+ Value string
+ TTL time.Duration
+}
+
+func (a *createInOrderAction) HTTPRequest(ep url.URL) *http.Request {
+ u := v2KeysURL(ep, a.Prefix, a.Dir)
+
+ form := url.Values{}
+ form.Add("value", a.Value)
+ if a.TTL > 0 {
+ form.Add("ttl", strconv.FormatUint(uint64(a.TTL.Seconds()), 10))
+ }
+ body := strings.NewReader(form.Encode())
+
+ req, _ := http.NewRequest("POST", u.String(), body)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ return req
+}
+
+func unmarshalHTTPResponse(code int, header http.Header, body []byte) (res *Response, err error) {
+ switch code {
+ case http.StatusOK, http.StatusCreated:
+ if len(body) == 0 {
+ return nil, ErrEmptyBody
+ }
+ res, err = unmarshalSuccessfulKeysResponse(header, body)
+ default:
+ err = unmarshalFailedKeysResponse(body)
+ }
+ return res, err
+}
+
+func unmarshalSuccessfulKeysResponse(header http.Header, body []byte) (*Response, error) {
+ var res Response
+ err := codec.NewDecoderBytes(body, new(codec.JsonHandle)).Decode(&res)
+ if err != nil {
+ return nil, ErrInvalidJSON
+ }
+ if header.Get("X-Etcd-Index") != "" {
+ res.Index, err = strconv.ParseUint(header.Get("X-Etcd-Index"), 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ }
+ res.ClusterID = header.Get("X-Etcd-Cluster-ID")
+ return &res, nil
+}
+
+func unmarshalFailedKeysResponse(body []byte) error {
+ var etcdErr Error
+ if err := json.Unmarshal(body, &etcdErr); err != nil {
+ return ErrInvalidJSON
+ }
+ return etcdErr
+}
diff --git a/vendor/github.com/coreos/etcd/client/members.go b/vendor/github.com/coreos/etcd/client/members.go
new file mode 100644
index 00000000..aafa3d1b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/members.go
@@ -0,0 +1,303 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "path"
+
+ "github.com/coreos/etcd/pkg/types"
+)
+
+var (
+ defaultV2MembersPrefix = "/v2/members"
+ defaultLeaderSuffix = "/leader"
+)
+
+type Member struct {
+ // ID is the unique identifier of this Member.
+ ID string `json:"id"`
+
+ // Name is a human-readable, non-unique identifier of this Member.
+ Name string `json:"name"`
+
+ // PeerURLs represents the HTTP(S) endpoints this Member uses to
+ // participate in etcd's consensus protocol.
+ PeerURLs []string `json:"peerURLs"`
+
+ // ClientURLs represents the HTTP(S) endpoints on which this Member
+ // serves its client-facing APIs.
+ ClientURLs []string `json:"clientURLs"`
+}
+
+type memberCollection []Member
+
+func (c *memberCollection) UnmarshalJSON(data []byte) error {
+ d := struct {
+ Members []Member
+ }{}
+
+ if err := json.Unmarshal(data, &d); err != nil {
+ return err
+ }
+
+ if d.Members == nil {
+ *c = make([]Member, 0)
+ return nil
+ }
+
+ *c = d.Members
+ return nil
+}
+
+type memberCreateOrUpdateRequest struct {
+ PeerURLs types.URLs
+}
+
+func (m *memberCreateOrUpdateRequest) MarshalJSON() ([]byte, error) {
+ s := struct {
+ PeerURLs []string `json:"peerURLs"`
+ }{
+ PeerURLs: make([]string, len(m.PeerURLs)),
+ }
+
+ for i, u := range m.PeerURLs {
+ s.PeerURLs[i] = u.String()
+ }
+
+ return json.Marshal(&s)
+}
+
+// NewMembersAPI constructs a new MembersAPI that uses HTTP to
+// interact with etcd's membership API.
+func NewMembersAPI(c Client) MembersAPI {
+ return &httpMembersAPI{
+ client: c,
+ }
+}
+
+type MembersAPI interface {
+ // List enumerates the current cluster membership.
+ List(ctx context.Context) ([]Member, error)
+
+ // Add instructs etcd to accept a new Member into the cluster.
+ Add(ctx context.Context, peerURL string) (*Member, error)
+
+ // Remove demotes an existing Member out of the cluster.
+ Remove(ctx context.Context, mID string) error
+
+ // Update instructs etcd to update an existing Member in the cluster.
+ Update(ctx context.Context, mID string, peerURLs []string) error
+
+ // Leader gets current leader of the cluster
+ Leader(ctx context.Context) (*Member, error)
+}
+
+type httpMembersAPI struct {
+ client httpClient
+}
+
+func (m *httpMembersAPI) List(ctx context.Context) ([]Member, error) {
+ req := &membersAPIActionList{}
+ resp, body, err := m.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
+ return nil, err
+ }
+
+ var mCollection memberCollection
+ if err := json.Unmarshal(body, &mCollection); err != nil {
+ return nil, err
+ }
+
+ return []Member(mCollection), nil
+}
+
+func (m *httpMembersAPI) Add(ctx context.Context, peerURL string) (*Member, error) {
+ urls, err := types.NewURLs([]string{peerURL})
+ if err != nil {
+ return nil, err
+ }
+
+ req := &membersAPIActionAdd{peerURLs: urls}
+ resp, body, err := m.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := assertStatusCode(resp.StatusCode, http.StatusCreated, http.StatusConflict); err != nil {
+ return nil, err
+ }
+
+ if resp.StatusCode != http.StatusCreated {
+ var merr membersError
+ if err := json.Unmarshal(body, &merr); err != nil {
+ return nil, err
+ }
+ return nil, merr
+ }
+
+ var memb Member
+ if err := json.Unmarshal(body, &memb); err != nil {
+ return nil, err
+ }
+
+ return &memb, nil
+}
+
+func (m *httpMembersAPI) Update(ctx context.Context, memberID string, peerURLs []string) error {
+ urls, err := types.NewURLs(peerURLs)
+ if err != nil {
+ return err
+ }
+
+ req := &membersAPIActionUpdate{peerURLs: urls, memberID: memberID}
+ resp, body, err := m.client.Do(ctx, req)
+ if err != nil {
+ return err
+ }
+
+ if err := assertStatusCode(resp.StatusCode, http.StatusNoContent, http.StatusNotFound, http.StatusConflict); err != nil {
+ return err
+ }
+
+ if resp.StatusCode != http.StatusNoContent {
+ var merr membersError
+ if err := json.Unmarshal(body, &merr); err != nil {
+ return err
+ }
+ return merr
+ }
+
+ return nil
+}
+
+func (m *httpMembersAPI) Remove(ctx context.Context, memberID string) error {
+ req := &membersAPIActionRemove{memberID: memberID}
+ resp, _, err := m.client.Do(ctx, req)
+ if err != nil {
+ return err
+ }
+
+ return assertStatusCode(resp.StatusCode, http.StatusNoContent, http.StatusGone)
+}
+
+func (m *httpMembersAPI) Leader(ctx context.Context) (*Member, error) {
+ req := &membersAPIActionLeader{}
+ resp, body, err := m.client.Do(ctx, req)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
+ return nil, err
+ }
+
+ var leader Member
+ if err := json.Unmarshal(body, &leader); err != nil {
+ return nil, err
+ }
+
+ return &leader, nil
+}
+
+type membersAPIActionList struct{}
+
+func (l *membersAPIActionList) HTTPRequest(ep url.URL) *http.Request {
+ u := v2MembersURL(ep)
+ req, _ := http.NewRequest("GET", u.String(), nil)
+ return req
+}
+
+type membersAPIActionRemove struct {
+ memberID string
+}
+
+func (d *membersAPIActionRemove) HTTPRequest(ep url.URL) *http.Request {
+ u := v2MembersURL(ep)
+ u.Path = path.Join(u.Path, d.memberID)
+ req, _ := http.NewRequest("DELETE", u.String(), nil)
+ return req
+}
+
+type membersAPIActionAdd struct {
+ peerURLs types.URLs
+}
+
+func (a *membersAPIActionAdd) HTTPRequest(ep url.URL) *http.Request {
+ u := v2MembersURL(ep)
+ m := memberCreateOrUpdateRequest{PeerURLs: a.peerURLs}
+ b, _ := json.Marshal(&m)
+ req, _ := http.NewRequest("POST", u.String(), bytes.NewReader(b))
+ req.Header.Set("Content-Type", "application/json")
+ return req
+}
+
+type membersAPIActionUpdate struct {
+ memberID string
+ peerURLs types.URLs
+}
+
+func (a *membersAPIActionUpdate) HTTPRequest(ep url.URL) *http.Request {
+ u := v2MembersURL(ep)
+ m := memberCreateOrUpdateRequest{PeerURLs: a.peerURLs}
+ u.Path = path.Join(u.Path, a.memberID)
+ b, _ := json.Marshal(&m)
+ req, _ := http.NewRequest("PUT", u.String(), bytes.NewReader(b))
+ req.Header.Set("Content-Type", "application/json")
+ return req
+}
+
+func assertStatusCode(got int, want ...int) (err error) {
+ for _, w := range want {
+ if w == got {
+ return nil
+ }
+ }
+ return fmt.Errorf("unexpected status code %d", got)
+}
+
+type membersAPIActionLeader struct{}
+
+func (l *membersAPIActionLeader) HTTPRequest(ep url.URL) *http.Request {
+ u := v2MembersURL(ep)
+ u.Path = path.Join(u.Path, defaultLeaderSuffix)
+ req, _ := http.NewRequest("GET", u.String(), nil)
+ return req
+}
+
+// v2MembersURL add the necessary path to the provided endpoint
+// to route requests to the default v2 members API.
+func v2MembersURL(ep url.URL) *url.URL {
+ ep.Path = path.Join(ep.Path, defaultV2MembersPrefix)
+ return &ep
+}
+
+type membersError struct {
+ Message string `json:"message"`
+ Code int `json:"-"`
+}
+
+func (e membersError) Error() string {
+ return e.Message
+}
diff --git a/vendor/github.com/coreos/etcd/client/util.go b/vendor/github.com/coreos/etcd/client/util.go
new file mode 100644
index 00000000..15a8babf
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/client/util.go
@@ -0,0 +1,53 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package client
+
+import (
+ "regexp"
+)
+
+var (
+ roleNotFoundRegExp *regexp.Regexp
+ userNotFoundRegExp *regexp.Regexp
+)
+
+func init() {
+ roleNotFoundRegExp = regexp.MustCompile("auth: Role .* does not exist.")
+ userNotFoundRegExp = regexp.MustCompile("auth: User .* does not exist.")
+}
+
+// IsKeyNotFound returns true if the error code is ErrorCodeKeyNotFound.
+func IsKeyNotFound(err error) bool {
+ if cErr, ok := err.(Error); ok {
+ return cErr.Code == ErrorCodeKeyNotFound
+ }
+ return false
+}
+
+// IsRoleNotFound returns true if the error means role not found of v2 API.
+func IsRoleNotFound(err error) bool {
+ if ae, ok := err.(authError); ok {
+ return roleNotFoundRegExp.MatchString(ae.Message)
+ }
+ return false
+}
+
+// IsUserNotFound returns true if the error means user not found of v2 API.
+func IsUserNotFound(err error) bool {
+ if ae, ok := err.(authError); ok {
+ return userNotFoundRegExp.MatchString(ae.Message)
+ }
+ return false
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/auth.go b/vendor/github.com/coreos/etcd/clientv3/auth.go
new file mode 100644
index 00000000..7545bb6c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/auth.go
@@ -0,0 +1,233 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/coreos/etcd/auth/authpb"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ "google.golang.org/grpc"
+)
+
+type (
+ AuthEnableResponse pb.AuthEnableResponse
+ AuthDisableResponse pb.AuthDisableResponse
+ AuthenticateResponse pb.AuthenticateResponse
+ AuthUserAddResponse pb.AuthUserAddResponse
+ AuthUserDeleteResponse pb.AuthUserDeleteResponse
+ AuthUserChangePasswordResponse pb.AuthUserChangePasswordResponse
+ AuthUserGrantRoleResponse pb.AuthUserGrantRoleResponse
+ AuthUserGetResponse pb.AuthUserGetResponse
+ AuthUserRevokeRoleResponse pb.AuthUserRevokeRoleResponse
+ AuthRoleAddResponse pb.AuthRoleAddResponse
+ AuthRoleGrantPermissionResponse pb.AuthRoleGrantPermissionResponse
+ AuthRoleGetResponse pb.AuthRoleGetResponse
+ AuthRoleRevokePermissionResponse pb.AuthRoleRevokePermissionResponse
+ AuthRoleDeleteResponse pb.AuthRoleDeleteResponse
+ AuthUserListResponse pb.AuthUserListResponse
+ AuthRoleListResponse pb.AuthRoleListResponse
+
+ PermissionType authpb.Permission_Type
+ Permission authpb.Permission
+)
+
+const (
+ PermRead = authpb.READ
+ PermWrite = authpb.WRITE
+ PermReadWrite = authpb.READWRITE
+)
+
+type Auth interface {
+ // AuthEnable enables auth of an etcd cluster.
+ AuthEnable(ctx context.Context) (*AuthEnableResponse, error)
+
+ // AuthDisable disables auth of an etcd cluster.
+ AuthDisable(ctx context.Context) (*AuthDisableResponse, error)
+
+ // UserAdd adds a new user to an etcd cluster.
+ UserAdd(ctx context.Context, name string, password string) (*AuthUserAddResponse, error)
+
+ // UserDelete deletes a user from an etcd cluster.
+ UserDelete(ctx context.Context, name string) (*AuthUserDeleteResponse, error)
+
+ // UserChangePassword changes a password of a user.
+ UserChangePassword(ctx context.Context, name string, password string) (*AuthUserChangePasswordResponse, error)
+
+ // UserGrantRole grants a role to a user.
+ UserGrantRole(ctx context.Context, user string, role string) (*AuthUserGrantRoleResponse, error)
+
+ // UserGet gets a detailed information of a user.
+ UserGet(ctx context.Context, name string) (*AuthUserGetResponse, error)
+
+ // UserList gets a list of all users.
+ UserList(ctx context.Context) (*AuthUserListResponse, error)
+
+ // UserRevokeRole revokes a role of a user.
+ UserRevokeRole(ctx context.Context, name string, role string) (*AuthUserRevokeRoleResponse, error)
+
+ // RoleAdd adds a new role to an etcd cluster.
+ RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error)
+
+ // RoleGrantPermission grants a permission to a role.
+ RoleGrantPermission(ctx context.Context, name string, key, rangeEnd string, permType PermissionType) (*AuthRoleGrantPermissionResponse, error)
+
+ // RoleGet gets a detailed information of a role.
+ RoleGet(ctx context.Context, role string) (*AuthRoleGetResponse, error)
+
+ // RoleList gets a list of all roles.
+ RoleList(ctx context.Context) (*AuthRoleListResponse, error)
+
+ // RoleRevokePermission revokes a permission from a role.
+ RoleRevokePermission(ctx context.Context, role string, key, rangeEnd string) (*AuthRoleRevokePermissionResponse, error)
+
+ // RoleDelete deletes a role.
+ RoleDelete(ctx context.Context, role string) (*AuthRoleDeleteResponse, error)
+}
+
+type auth struct {
+ remote pb.AuthClient
+ callOpts []grpc.CallOption
+}
+
+func NewAuth(c *Client) Auth {
+ api := &auth{remote: RetryAuthClient(c)}
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api
+}
+
+func (auth *auth) AuthEnable(ctx context.Context) (*AuthEnableResponse, error) {
+ resp, err := auth.remote.AuthEnable(ctx, &pb.AuthEnableRequest{}, auth.callOpts...)
+ return (*AuthEnableResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) AuthDisable(ctx context.Context) (*AuthDisableResponse, error) {
+ resp, err := auth.remote.AuthDisable(ctx, &pb.AuthDisableRequest{}, auth.callOpts...)
+ return (*AuthDisableResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) UserAdd(ctx context.Context, name string, password string) (*AuthUserAddResponse, error) {
+ resp, err := auth.remote.UserAdd(ctx, &pb.AuthUserAddRequest{Name: name, Password: password}, auth.callOpts...)
+ return (*AuthUserAddResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) UserDelete(ctx context.Context, name string) (*AuthUserDeleteResponse, error) {
+ resp, err := auth.remote.UserDelete(ctx, &pb.AuthUserDeleteRequest{Name: name}, auth.callOpts...)
+ return (*AuthUserDeleteResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) UserChangePassword(ctx context.Context, name string, password string) (*AuthUserChangePasswordResponse, error) {
+ resp, err := auth.remote.UserChangePassword(ctx, &pb.AuthUserChangePasswordRequest{Name: name, Password: password}, auth.callOpts...)
+ return (*AuthUserChangePasswordResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) UserGrantRole(ctx context.Context, user string, role string) (*AuthUserGrantRoleResponse, error) {
+ resp, err := auth.remote.UserGrantRole(ctx, &pb.AuthUserGrantRoleRequest{User: user, Role: role}, auth.callOpts...)
+ return (*AuthUserGrantRoleResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) UserGet(ctx context.Context, name string) (*AuthUserGetResponse, error) {
+ resp, err := auth.remote.UserGet(ctx, &pb.AuthUserGetRequest{Name: name}, auth.callOpts...)
+ return (*AuthUserGetResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) UserList(ctx context.Context) (*AuthUserListResponse, error) {
+ resp, err := auth.remote.UserList(ctx, &pb.AuthUserListRequest{}, auth.callOpts...)
+ return (*AuthUserListResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) UserRevokeRole(ctx context.Context, name string, role string) (*AuthUserRevokeRoleResponse, error) {
+ resp, err := auth.remote.UserRevokeRole(ctx, &pb.AuthUserRevokeRoleRequest{Name: name, Role: role}, auth.callOpts...)
+ return (*AuthUserRevokeRoleResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) {
+ resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name}, auth.callOpts...)
+ return (*AuthRoleAddResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) RoleGrantPermission(ctx context.Context, name string, key, rangeEnd string, permType PermissionType) (*AuthRoleGrantPermissionResponse, error) {
+ perm := &authpb.Permission{
+ Key: []byte(key),
+ RangeEnd: []byte(rangeEnd),
+ PermType: authpb.Permission_Type(permType),
+ }
+ resp, err := auth.remote.RoleGrantPermission(ctx, &pb.AuthRoleGrantPermissionRequest{Name: name, Perm: perm}, auth.callOpts...)
+ return (*AuthRoleGrantPermissionResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) RoleGet(ctx context.Context, role string) (*AuthRoleGetResponse, error) {
+ resp, err := auth.remote.RoleGet(ctx, &pb.AuthRoleGetRequest{Role: role}, auth.callOpts...)
+ return (*AuthRoleGetResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) RoleList(ctx context.Context) (*AuthRoleListResponse, error) {
+ resp, err := auth.remote.RoleList(ctx, &pb.AuthRoleListRequest{}, auth.callOpts...)
+ return (*AuthRoleListResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) RoleRevokePermission(ctx context.Context, role string, key, rangeEnd string) (*AuthRoleRevokePermissionResponse, error) {
+ resp, err := auth.remote.RoleRevokePermission(ctx, &pb.AuthRoleRevokePermissionRequest{Role: role, Key: key, RangeEnd: rangeEnd}, auth.callOpts...)
+ return (*AuthRoleRevokePermissionResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *auth) RoleDelete(ctx context.Context, role string) (*AuthRoleDeleteResponse, error) {
+ resp, err := auth.remote.RoleDelete(ctx, &pb.AuthRoleDeleteRequest{Role: role}, auth.callOpts...)
+ return (*AuthRoleDeleteResponse)(resp), toErr(ctx, err)
+}
+
+func StrToPermissionType(s string) (PermissionType, error) {
+ val, ok := authpb.Permission_Type_value[strings.ToUpper(s)]
+ if ok {
+ return PermissionType(val), nil
+ }
+ return PermissionType(-1), fmt.Errorf("invalid permission type: %s", s)
+}
+
+type authenticator struct {
+ conn *grpc.ClientConn // conn in-use
+ remote pb.AuthClient
+ callOpts []grpc.CallOption
+}
+
+func (auth *authenticator) authenticate(ctx context.Context, name string, password string) (*AuthenticateResponse, error) {
+ resp, err := auth.remote.Authenticate(ctx, &pb.AuthenticateRequest{Name: name, Password: password}, auth.callOpts...)
+ return (*AuthenticateResponse)(resp), toErr(ctx, err)
+}
+
+func (auth *authenticator) close() {
+ auth.conn.Close()
+}
+
+func newAuthenticator(endpoint string, opts []grpc.DialOption, c *Client) (*authenticator, error) {
+ conn, err := grpc.Dial(endpoint, opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ api := &authenticator{
+ conn: conn,
+ remote: pb.NewAuthClient(conn),
+ }
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api, nil
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/client.go b/vendor/github.com/coreos/etcd/clientv3/client.go
new file mode 100644
index 00000000..71328077
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/client.go
@@ -0,0 +1,576 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+var (
+ ErrNoAvailableEndpoints = errors.New("etcdclient: no available endpoints")
+ ErrOldCluster = errors.New("etcdclient: old cluster version")
+)
+
+// Client provides and manages an etcd v3 client session.
+type Client struct {
+ Cluster
+ KV
+ Lease
+ Watcher
+ Auth
+ Maintenance
+
+ conn *grpc.ClientConn
+ dialerrc chan error
+
+ cfg Config
+ creds *credentials.TransportCredentials
+ balancer *healthBalancer
+ mu *sync.Mutex
+
+ ctx context.Context
+ cancel context.CancelFunc
+
+ // Username is a user name for authentication.
+ Username string
+ // Password is a password for authentication.
+ Password string
+ // tokenCred is an instance of WithPerRPCCredentials()'s argument
+ tokenCred *authTokenCredential
+
+ callOpts []grpc.CallOption
+}
+
+// New creates a new etcdv3 client from a given configuration.
+func New(cfg Config) (*Client, error) {
+ if len(cfg.Endpoints) == 0 {
+ return nil, ErrNoAvailableEndpoints
+ }
+
+ return newClient(&cfg)
+}
+
+// NewCtxClient creates a client with a context but no underlying grpc
+// connection. This is useful for embedded cases that override the
+// service interface implementations and do not need connection management.
+func NewCtxClient(ctx context.Context) *Client {
+ cctx, cancel := context.WithCancel(ctx)
+ return &Client{ctx: cctx, cancel: cancel}
+}
+
+// NewFromURL creates a new etcdv3 client from a URL.
+func NewFromURL(url string) (*Client, error) {
+ return New(Config{Endpoints: []string{url}})
+}
+
+// Close shuts down the client's etcd connections.
+func (c *Client) Close() error {
+ c.cancel()
+ c.Watcher.Close()
+ c.Lease.Close()
+ if c.conn != nil {
+ return toErr(c.ctx, c.conn.Close())
+ }
+ return c.ctx.Err()
+}
+
+// Ctx is a context for "out of band" messages (e.g., for sending
+// "clean up" message when another context is canceled). It is
+// canceled on client Close().
+func (c *Client) Ctx() context.Context { return c.ctx }
+
+// Endpoints lists the registered endpoints for the client.
+func (c *Client) Endpoints() (eps []string) {
+ // copy the slice; protect original endpoints from being changed
+ eps = make([]string, len(c.cfg.Endpoints))
+ copy(eps, c.cfg.Endpoints)
+ return
+}
+
+// SetEndpoints updates client's endpoints.
+func (c *Client) SetEndpoints(eps ...string) {
+ c.mu.Lock()
+ c.cfg.Endpoints = eps
+ c.mu.Unlock()
+ c.balancer.updateAddrs(eps...)
+
+ // updating notifyCh can trigger new connections,
+ // need update addrs if all connections are down
+ // or addrs does not include pinAddr.
+ c.balancer.mu.RLock()
+ update := !hasAddr(c.balancer.addrs, c.balancer.pinAddr)
+ c.balancer.mu.RUnlock()
+ if update {
+ select {
+ case c.balancer.updateAddrsC <- notifyNext:
+ case <-c.balancer.stopc:
+ }
+ }
+}
+
+// Sync synchronizes client's endpoints with the known endpoints from the etcd membership.
+func (c *Client) Sync(ctx context.Context) error {
+ mresp, err := c.MemberList(ctx)
+ if err != nil {
+ return err
+ }
+ var eps []string
+ for _, m := range mresp.Members {
+ eps = append(eps, m.ClientURLs...)
+ }
+ c.SetEndpoints(eps...)
+ return nil
+}
+
+func (c *Client) autoSync() {
+ if c.cfg.AutoSyncInterval == time.Duration(0) {
+ return
+ }
+
+ for {
+ select {
+ case <-c.ctx.Done():
+ return
+ case <-time.After(c.cfg.AutoSyncInterval):
+ ctx, cancel := context.WithTimeout(c.ctx, 5*time.Second)
+ err := c.Sync(ctx)
+ cancel()
+ if err != nil && err != c.ctx.Err() {
+ logger.Println("Auto sync endpoints failed:", err)
+ }
+ }
+ }
+}
+
+type authTokenCredential struct {
+ token string
+ tokenMu *sync.RWMutex
+}
+
+func (cred authTokenCredential) RequireTransportSecurity() bool {
+ return false
+}
+
+func (cred authTokenCredential) GetRequestMetadata(ctx context.Context, s ...string) (map[string]string, error) {
+ cred.tokenMu.RLock()
+ defer cred.tokenMu.RUnlock()
+ return map[string]string{
+ "token": cred.token,
+ }, nil
+}
+
+func parseEndpoint(endpoint string) (proto string, host string, scheme string) {
+ proto = "tcp"
+ host = endpoint
+ url, uerr := url.Parse(endpoint)
+ if uerr != nil || !strings.Contains(endpoint, "://") {
+ return proto, host, scheme
+ }
+ scheme = url.Scheme
+
+ // strip scheme:// prefix since grpc dials by host
+ host = url.Host
+ switch url.Scheme {
+ case "http", "https":
+ case "unix", "unixs":
+ proto = "unix"
+ host = url.Host + url.Path
+ default:
+ proto, host = "", ""
+ }
+ return proto, host, scheme
+}
+
+func (c *Client) processCreds(scheme string) (creds *credentials.TransportCredentials) {
+ creds = c.creds
+ switch scheme {
+ case "unix":
+ case "http":
+ creds = nil
+ case "https", "unixs":
+ if creds != nil {
+ break
+ }
+ tlsconfig := &tls.Config{}
+ emptyCreds := credentials.NewTLS(tlsconfig)
+ creds = &emptyCreds
+ default:
+ creds = nil
+ }
+ return creds
+}
+
+// dialSetupOpts gives the dial opts prior to any authentication
+func (c *Client) dialSetupOpts(endpoint string, dopts ...grpc.DialOption) (opts []grpc.DialOption) {
+ if c.cfg.DialTimeout > 0 {
+ opts = []grpc.DialOption{grpc.WithTimeout(c.cfg.DialTimeout)}
+ }
+ if c.cfg.DialKeepAliveTime > 0 {
+ params := keepalive.ClientParameters{
+ Time: c.cfg.DialKeepAliveTime,
+ Timeout: c.cfg.DialKeepAliveTimeout,
+ }
+ opts = append(opts, grpc.WithKeepaliveParams(params))
+ }
+ opts = append(opts, dopts...)
+
+ f := func(host string, t time.Duration) (net.Conn, error) {
+ proto, host, _ := parseEndpoint(c.balancer.endpoint(host))
+ if host == "" && endpoint != "" {
+ // dialing an endpoint not in the balancer; use
+ // endpoint passed into dial
+ proto, host, _ = parseEndpoint(endpoint)
+ }
+ if proto == "" {
+ return nil, fmt.Errorf("unknown scheme for %q", host)
+ }
+ select {
+ case <-c.ctx.Done():
+ return nil, c.ctx.Err()
+ default:
+ }
+ dialer := &net.Dialer{Timeout: t}
+ conn, err := dialer.DialContext(c.ctx, proto, host)
+ if err != nil {
+ select {
+ case c.dialerrc <- err:
+ default:
+ }
+ }
+ return conn, err
+ }
+ opts = append(opts, grpc.WithDialer(f))
+
+ creds := c.creds
+ if _, _, scheme := parseEndpoint(endpoint); len(scheme) != 0 {
+ creds = c.processCreds(scheme)
+ }
+ if creds != nil {
+ opts = append(opts, grpc.WithTransportCredentials(*creds))
+ } else {
+ opts = append(opts, grpc.WithInsecure())
+ }
+
+ return opts
+}
+
+// Dial connects to a single endpoint using the client's config.
+func (c *Client) Dial(endpoint string) (*grpc.ClientConn, error) {
+ return c.dial(endpoint)
+}
+
+func (c *Client) getToken(ctx context.Context) error {
+ var err error // return last error in a case of fail
+ var auth *authenticator
+
+ for i := 0; i < len(c.cfg.Endpoints); i++ {
+ endpoint := c.cfg.Endpoints[i]
+ host := getHost(endpoint)
+ // use dial options without dopts to avoid reusing the client balancer
+ auth, err = newAuthenticator(host, c.dialSetupOpts(endpoint), c)
+ if err != nil {
+ continue
+ }
+ defer auth.close()
+
+ var resp *AuthenticateResponse
+ resp, err = auth.authenticate(ctx, c.Username, c.Password)
+ if err != nil {
+ continue
+ }
+
+ c.tokenCred.tokenMu.Lock()
+ c.tokenCred.token = resp.Token
+ c.tokenCred.tokenMu.Unlock()
+
+ return nil
+ }
+
+ return err
+}
+
+func (c *Client) dial(endpoint string, dopts ...grpc.DialOption) (*grpc.ClientConn, error) {
+ opts := c.dialSetupOpts(endpoint, dopts...)
+ host := getHost(endpoint)
+ if c.Username != "" && c.Password != "" {
+ c.tokenCred = &authTokenCredential{
+ tokenMu: &sync.RWMutex{},
+ }
+
+ ctx := c.ctx
+ if c.cfg.DialTimeout > 0 {
+ cctx, cancel := context.WithTimeout(ctx, c.cfg.DialTimeout)
+ defer cancel()
+ ctx = cctx
+ }
+
+ err := c.getToken(ctx)
+ if err != nil {
+ if toErr(ctx, err) != rpctypes.ErrAuthNotEnabled {
+ if err == ctx.Err() && ctx.Err() != c.ctx.Err() {
+ err = context.DeadlineExceeded
+ }
+ return nil, err
+ }
+ } else {
+ opts = append(opts, grpc.WithPerRPCCredentials(c.tokenCred))
+ }
+ }
+
+ opts = append(opts, c.cfg.DialOptions...)
+
+ conn, err := grpc.DialContext(c.ctx, host, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return conn, nil
+}
+
+// WithRequireLeader requires client requests to only succeed
+// when the cluster has a leader.
+func WithRequireLeader(ctx context.Context) context.Context {
+ md := metadata.Pairs(rpctypes.MetadataRequireLeaderKey, rpctypes.MetadataHasLeader)
+ return metadata.NewOutgoingContext(ctx, md)
+}
+
+func newClient(cfg *Config) (*Client, error) {
+ if cfg == nil {
+ cfg = &Config{}
+ }
+ var creds *credentials.TransportCredentials
+ if cfg.TLS != nil {
+ c := credentials.NewTLS(cfg.TLS)
+ creds = &c
+ }
+
+ // use a temporary skeleton client to bootstrap first connection
+ baseCtx := context.TODO()
+ if cfg.Context != nil {
+ baseCtx = cfg.Context
+ }
+
+ ctx, cancel := context.WithCancel(baseCtx)
+ client := &Client{
+ conn: nil,
+ dialerrc: make(chan error, 1),
+ cfg: *cfg,
+ creds: creds,
+ ctx: ctx,
+ cancel: cancel,
+ mu: new(sync.Mutex),
+ callOpts: defaultCallOpts,
+ }
+ if cfg.Username != "" && cfg.Password != "" {
+ client.Username = cfg.Username
+ client.Password = cfg.Password
+ }
+ if cfg.MaxCallSendMsgSize > 0 || cfg.MaxCallRecvMsgSize > 0 {
+ if cfg.MaxCallRecvMsgSize > 0 && cfg.MaxCallSendMsgSize > cfg.MaxCallRecvMsgSize {
+ return nil, fmt.Errorf("gRPC message recv limit (%d bytes) must be greater than send limit (%d bytes)", cfg.MaxCallRecvMsgSize, cfg.MaxCallSendMsgSize)
+ }
+ callOpts := []grpc.CallOption{
+ defaultFailFast,
+ defaultMaxCallSendMsgSize,
+ defaultMaxCallRecvMsgSize,
+ }
+ if cfg.MaxCallSendMsgSize > 0 {
+ callOpts[1] = grpc.MaxCallSendMsgSize(cfg.MaxCallSendMsgSize)
+ }
+ if cfg.MaxCallRecvMsgSize > 0 {
+ callOpts[2] = grpc.MaxCallRecvMsgSize(cfg.MaxCallRecvMsgSize)
+ }
+ client.callOpts = callOpts
+ }
+
+ client.balancer = newHealthBalancer(cfg.Endpoints, cfg.DialTimeout, func(ep string) (bool, error) {
+ return grpcHealthCheck(client, ep)
+ })
+
+ // use Endpoints[0] so that for https:// without any tls config given, then
+ // grpc will assume the certificate server name is the endpoint host.
+ conn, err := client.dial(cfg.Endpoints[0], grpc.WithBalancer(client.balancer))
+ if err != nil {
+ client.cancel()
+ client.balancer.Close()
+ return nil, err
+ }
+ client.conn = conn
+
+ // wait for a connection
+ if cfg.DialTimeout > 0 {
+ hasConn := false
+ waitc := time.After(cfg.DialTimeout)
+ select {
+ case <-client.balancer.ready():
+ hasConn = true
+ case <-ctx.Done():
+ case <-waitc:
+ }
+ if !hasConn {
+ err := context.DeadlineExceeded
+ select {
+ case err = <-client.dialerrc:
+ default:
+ }
+ client.cancel()
+ client.balancer.Close()
+ conn.Close()
+ return nil, err
+ }
+ }
+
+ client.Cluster = NewCluster(client)
+ client.KV = NewKV(client)
+ client.Lease = NewLease(client)
+ client.Watcher = NewWatcher(client)
+ client.Auth = NewAuth(client)
+ client.Maintenance = NewMaintenance(client)
+
+ if cfg.RejectOldCluster {
+ if err := client.checkVersion(); err != nil {
+ client.Close()
+ return nil, err
+ }
+ }
+
+ go client.autoSync()
+ return client, nil
+}
+
+func (c *Client) checkVersion() (err error) {
+ var wg sync.WaitGroup
+ errc := make(chan error, len(c.cfg.Endpoints))
+ ctx, cancel := context.WithCancel(c.ctx)
+ if c.cfg.DialTimeout > 0 {
+ ctx, cancel = context.WithTimeout(ctx, c.cfg.DialTimeout)
+ }
+ wg.Add(len(c.cfg.Endpoints))
+ for _, ep := range c.cfg.Endpoints {
+ // if cluster is current, any endpoint gives a recent version
+ go func(e string) {
+ defer wg.Done()
+ resp, rerr := c.Status(ctx, e)
+ if rerr != nil {
+ errc <- rerr
+ return
+ }
+ vs := strings.Split(resp.Version, ".")
+ maj, min := 0, 0
+ if len(vs) >= 2 {
+ maj, _ = strconv.Atoi(vs[0])
+ min, rerr = strconv.Atoi(vs[1])
+ }
+ if maj < 3 || (maj == 3 && min < 2) {
+ rerr = ErrOldCluster
+ }
+ errc <- rerr
+ }(ep)
+ }
+ // wait for success
+ for i := 0; i < len(c.cfg.Endpoints); i++ {
+ if err = <-errc; err == nil {
+ break
+ }
+ }
+ cancel()
+ wg.Wait()
+ return err
+}
+
+// ActiveConnection returns the current in-use connection
+func (c *Client) ActiveConnection() *grpc.ClientConn { return c.conn }
+
+// isHaltErr returns true if the given error and context indicate no forward
+// progress can be made, even after reconnecting.
+func isHaltErr(ctx context.Context, err error) bool {
+ if ctx != nil && ctx.Err() != nil {
+ return true
+ }
+ if err == nil {
+ return false
+ }
+ ev, _ := status.FromError(err)
+ // Unavailable codes mean the system will be right back.
+ // (e.g., can't connect, lost leader)
+ // Treat Internal codes as if something failed, leaving the
+ // system in an inconsistent state, but retrying could make progress.
+ // (e.g., failed in middle of send, corrupted frame)
+ // TODO: are permanent Internal errors possible from grpc?
+ return ev.Code() != codes.Unavailable && ev.Code() != codes.Internal
+}
+
+// isUnavailableErr returns true if the given error is an unavailable error
+func isUnavailableErr(ctx context.Context, err error) bool {
+ if ctx != nil && ctx.Err() != nil {
+ return false
+ }
+ if err == nil {
+ return false
+ }
+ ev, _ := status.FromError(err)
+ // Unavailable codes mean the system will be right back.
+ // (e.g., can't connect, lost leader)
+ return ev.Code() == codes.Unavailable
+}
+
+func toErr(ctx context.Context, err error) error {
+ if err == nil {
+ return nil
+ }
+ err = rpctypes.Error(err)
+ if _, ok := err.(rpctypes.EtcdError); ok {
+ return err
+ }
+ ev, _ := status.FromError(err)
+ code := ev.Code()
+ switch code {
+ case codes.DeadlineExceeded:
+ fallthrough
+ case codes.Canceled:
+ if ctx.Err() != nil {
+ err = ctx.Err()
+ }
+ case codes.Unavailable:
+ case codes.FailedPrecondition:
+ err = grpc.ErrClientConnClosing
+ }
+ return err
+}
+
+func canceledByCaller(stopCtx context.Context, err error) bool {
+ if stopCtx.Err() == nil || err == nil {
+ return false
+ }
+
+ return err == context.Canceled || err == context.DeadlineExceeded
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/cluster.go b/vendor/github.com/coreos/etcd/clientv3/cluster.go
new file mode 100644
index 00000000..785672be
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/cluster.go
@@ -0,0 +1,114 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/pkg/types"
+
+ "google.golang.org/grpc"
+)
+
+type (
+ Member pb.Member
+ MemberListResponse pb.MemberListResponse
+ MemberAddResponse pb.MemberAddResponse
+ MemberRemoveResponse pb.MemberRemoveResponse
+ MemberUpdateResponse pb.MemberUpdateResponse
+)
+
+type Cluster interface {
+ // MemberList lists the current cluster membership.
+ MemberList(ctx context.Context) (*MemberListResponse, error)
+
+ // MemberAdd adds a new member into the cluster.
+ MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error)
+
+ // MemberRemove removes an existing member from the cluster.
+ MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error)
+
+ // MemberUpdate updates the peer addresses of the member.
+ MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error)
+}
+
+type cluster struct {
+ remote pb.ClusterClient
+ callOpts []grpc.CallOption
+}
+
+func NewCluster(c *Client) Cluster {
+ api := &cluster{remote: RetryClusterClient(c)}
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api
+}
+
+func NewClusterFromClusterClient(remote pb.ClusterClient, c *Client) Cluster {
+ api := &cluster{remote: remote}
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api
+}
+
+func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) {
+ // fail-fast before panic in rafthttp
+ if _, err := types.NewURLs(peerAddrs); err != nil {
+ return nil, err
+ }
+
+ r := &pb.MemberAddRequest{PeerURLs: peerAddrs}
+ resp, err := c.remote.MemberAdd(ctx, r, c.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ return (*MemberAddResponse)(resp), nil
+}
+
+func (c *cluster) MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error) {
+ r := &pb.MemberRemoveRequest{ID: id}
+ resp, err := c.remote.MemberRemove(ctx, r, c.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ return (*MemberRemoveResponse)(resp), nil
+}
+
+func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []string) (*MemberUpdateResponse, error) {
+ // fail-fast before panic in rafthttp
+ if _, err := types.NewURLs(peerAddrs); err != nil {
+ return nil, err
+ }
+
+ // it is safe to retry on update.
+ r := &pb.MemberUpdateRequest{ID: id, PeerURLs: peerAddrs}
+ resp, err := c.remote.MemberUpdate(ctx, r, c.callOpts...)
+ if err == nil {
+ return (*MemberUpdateResponse)(resp), nil
+ }
+ return nil, toErr(ctx, err)
+}
+
+func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) {
+ // it is safe to retry on list.
+ resp, err := c.remote.MemberList(ctx, &pb.MemberListRequest{}, c.callOpts...)
+ if err == nil {
+ return (*MemberListResponse)(resp), nil
+ }
+ return nil, toErr(ctx, err)
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/compact_op.go b/vendor/github.com/coreos/etcd/clientv3/compact_op.go
new file mode 100644
index 00000000..41e80c1d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/compact_op.go
@@ -0,0 +1,51 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+)
+
+// CompactOp represents a compact operation.
+type CompactOp struct {
+ revision int64
+ physical bool
+}
+
+// CompactOption configures compact operation.
+type CompactOption func(*CompactOp)
+
+func (op *CompactOp) applyCompactOpts(opts []CompactOption) {
+ for _, opt := range opts {
+ opt(op)
+ }
+}
+
+// OpCompact wraps slice CompactOption to create a CompactOp.
+func OpCompact(rev int64, opts ...CompactOption) CompactOp {
+ ret := CompactOp{revision: rev}
+ ret.applyCompactOpts(opts)
+ return ret
+}
+
+func (op CompactOp) toRequest() *pb.CompactionRequest {
+ return &pb.CompactionRequest{Revision: op.revision, Physical: op.physical}
+}
+
+// WithCompactPhysical makes Compact wait until all compacted entries are
+// removed from the etcd server's storage.
+func WithCompactPhysical() CompactOption {
+ return func(op *CompactOp) { op.physical = true }
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/compare.go b/vendor/github.com/coreos/etcd/clientv3/compare.go
new file mode 100644
index 00000000..b5f0a255
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/compare.go
@@ -0,0 +1,140 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+)
+
+type CompareTarget int
+type CompareResult int
+
+const (
+ CompareVersion CompareTarget = iota
+ CompareCreated
+ CompareModified
+ CompareValue
+)
+
+type Cmp pb.Compare
+
+func Compare(cmp Cmp, result string, v interface{}) Cmp {
+ var r pb.Compare_CompareResult
+
+ switch result {
+ case "=":
+ r = pb.Compare_EQUAL
+ case "!=":
+ r = pb.Compare_NOT_EQUAL
+ case ">":
+ r = pb.Compare_GREATER
+ case "<":
+ r = pb.Compare_LESS
+ default:
+ panic("Unknown result op")
+ }
+
+ cmp.Result = r
+ switch cmp.Target {
+ case pb.Compare_VALUE:
+ val, ok := v.(string)
+ if !ok {
+ panic("bad compare value")
+ }
+ cmp.TargetUnion = &pb.Compare_Value{Value: []byte(val)}
+ case pb.Compare_VERSION:
+ cmp.TargetUnion = &pb.Compare_Version{Version: mustInt64(v)}
+ case pb.Compare_CREATE:
+ cmp.TargetUnion = &pb.Compare_CreateRevision{CreateRevision: mustInt64(v)}
+ case pb.Compare_MOD:
+ cmp.TargetUnion = &pb.Compare_ModRevision{ModRevision: mustInt64(v)}
+ case pb.Compare_LEASE:
+ cmp.TargetUnion = &pb.Compare_Lease{Lease: mustInt64orLeaseID(v)}
+ default:
+ panic("Unknown compare type")
+ }
+ return cmp
+}
+
+func Value(key string) Cmp {
+ return Cmp{Key: []byte(key), Target: pb.Compare_VALUE}
+}
+
+func Version(key string) Cmp {
+ return Cmp{Key: []byte(key), Target: pb.Compare_VERSION}
+}
+
+func CreateRevision(key string) Cmp {
+ return Cmp{Key: []byte(key), Target: pb.Compare_CREATE}
+}
+
+func ModRevision(key string) Cmp {
+ return Cmp{Key: []byte(key), Target: pb.Compare_MOD}
+}
+
+// LeaseValue compares a key's LeaseID to a value of your choosing. The empty
+// LeaseID is 0, otherwise known as `NoLease`.
+func LeaseValue(key string) Cmp {
+ return Cmp{Key: []byte(key), Target: pb.Compare_LEASE}
+}
+
+// KeyBytes returns the byte slice holding with the comparison key.
+func (cmp *Cmp) KeyBytes() []byte { return cmp.Key }
+
+// WithKeyBytes sets the byte slice for the comparison key.
+func (cmp *Cmp) WithKeyBytes(key []byte) { cmp.Key = key }
+
+// ValueBytes returns the byte slice holding the comparison value, if any.
+func (cmp *Cmp) ValueBytes() []byte {
+ if tu, ok := cmp.TargetUnion.(*pb.Compare_Value); ok {
+ return tu.Value
+ }
+ return nil
+}
+
+// WithValueBytes sets the byte slice for the comparison's value.
+func (cmp *Cmp) WithValueBytes(v []byte) { cmp.TargetUnion.(*pb.Compare_Value).Value = v }
+
+// WithRange sets the comparison to scan the range [key, end).
+func (cmp Cmp) WithRange(end string) Cmp {
+ cmp.RangeEnd = []byte(end)
+ return cmp
+}
+
+// WithPrefix sets the comparison to scan all keys prefixed by the key.
+func (cmp Cmp) WithPrefix() Cmp {
+ cmp.RangeEnd = getPrefix(cmp.Key)
+ return cmp
+}
+
+// mustInt64 panics if val isn't an int or int64. It returns an int64 otherwise.
+func mustInt64(val interface{}) int64 {
+ if v, ok := val.(int64); ok {
+ return v
+ }
+ if v, ok := val.(int); ok {
+ return int64(v)
+ }
+ panic("bad value")
+}
+
+// mustInt64orLeaseID panics if val isn't a LeaseID, int or int64. It returns an
+// int64 otherwise.
+func mustInt64orLeaseID(val interface{}) int64 {
+ if v, ok := val.(LeaseID); ok {
+ return int64(v)
+ }
+ return mustInt64(val)
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/config.go b/vendor/github.com/coreos/etcd/clientv3/config.go
new file mode 100644
index 00000000..79d6e2a9
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/config.go
@@ -0,0 +1,75 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "crypto/tls"
+ "time"
+
+ "google.golang.org/grpc"
+)
+
+type Config struct {
+ // Endpoints is a list of URLs.
+ Endpoints []string `json:"endpoints"`
+
+ // AutoSyncInterval is the interval to update endpoints with its latest members.
+ // 0 disables auto-sync. By default auto-sync is disabled.
+ AutoSyncInterval time.Duration `json:"auto-sync-interval"`
+
+ // DialTimeout is the timeout for failing to establish a connection.
+ DialTimeout time.Duration `json:"dial-timeout"`
+
+ // DialKeepAliveTime is the time after which client pings the server to see if
+ // transport is alive.
+ DialKeepAliveTime time.Duration `json:"dial-keep-alive-time"`
+
+ // DialKeepAliveTimeout is the time that the client waits for a response for the
+ // keep-alive probe. If the response is not received in this time, the connection is closed.
+ DialKeepAliveTimeout time.Duration `json:"dial-keep-alive-timeout"`
+
+ // MaxCallSendMsgSize is the client-side request send limit in bytes.
+ // If 0, it defaults to 2.0 MiB (2 * 1024 * 1024).
+ // Make sure that "MaxCallSendMsgSize" < server-side default send/recv limit.
+ // ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
+ MaxCallSendMsgSize int
+
+ // MaxCallRecvMsgSize is the client-side response receive limit.
+ // If 0, it defaults to "math.MaxInt32", because range response can
+ // easily exceed request send limits.
+ // Make sure that "MaxCallRecvMsgSize" >= server-side default send/recv limit.
+ // ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
+ MaxCallRecvMsgSize int
+
+ // TLS holds the client secure credentials, if any.
+ TLS *tls.Config
+
+ // Username is a user name for authentication.
+ Username string `json:"username"`
+
+ // Password is a password for authentication.
+ Password string `json:"password"`
+
+ // RejectOldCluster when set will refuse to create a client against an outdated cluster.
+ RejectOldCluster bool `json:"reject-old-cluster"`
+
+ // DialOptions is a list of dial options for the grpc client (e.g., for interceptors).
+ DialOptions []grpc.DialOption
+
+ // Context is the default client context; it can be used to cancel grpc dial out and
+ // other operations that do not have an explicit context.
+ Context context.Context
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/doc.go b/vendor/github.com/coreos/etcd/clientv3/doc.go
new file mode 100644
index 00000000..717fbe43
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/doc.go
@@ -0,0 +1,97 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package clientv3 implements the official Go etcd client for v3.
+//
+// Create client using `clientv3.New`:
+//
+// // expect dial time-out on ipv4 blackhole
+// _, err := clientv3.New(clientv3.Config{
+// Endpoints: []string{"http://254.0.0.1:12345"},
+// DialTimeout: 2 * time.Second
+// })
+//
+// // etcd clientv3 >= v3.2.10, grpc/grpc-go >= v1.7.3
+// if err == context.DeadlineExceeded {
+// // handle errors
+// }
+//
+// // etcd clientv3 <= v3.2.9, grpc/grpc-go <= v1.2.1
+// if err == grpc.ErrClientConnTimeout {
+// // handle errors
+// }
+//
+// cli, err := clientv3.New(clientv3.Config{
+// Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"},
+// DialTimeout: 5 * time.Second,
+// })
+// if err != nil {
+// // handle error!
+// }
+// defer cli.Close()
+//
+// Make sure to close the client after using it. If the client is not closed, the
+// connection will have leaky goroutines.
+//
+// To specify a client request timeout, wrap the context with context.WithTimeout:
+//
+// ctx, cancel := context.WithTimeout(context.Background(), timeout)
+// resp, err := kvc.Put(ctx, "sample_key", "sample_value")
+// cancel()
+// if err != nil {
+// // handle error!
+// }
+// // use the response
+//
+// The Client has internal state (watchers and leases), so Clients should be reused instead of created as needed.
+// Clients are safe for concurrent use by multiple goroutines.
+//
+// etcd client returns 3 types of errors:
+//
+// 1. context error: canceled or deadline exceeded.
+// 2. gRPC status error: e.g. when clock drifts in server-side before client's context deadline exceeded.
+// 3. gRPC error: see https://github.com/coreos/etcd/blob/master/etcdserver/api/v3rpc/rpctypes/error.go
+//
+// Here is the example code to handle client errors:
+//
+// resp, err := kvc.Put(ctx, "", "")
+// if err != nil {
+// if err == context.Canceled {
+// // ctx is canceled by another routine
+// } else if err == context.DeadlineExceeded {
+// // ctx is attached with a deadline and it exceeded
+// } else if ev, ok := status.FromError(err); ok {
+// code := ev.Code()
+// if code == codes.DeadlineExceeded {
+// // server-side context might have timed-out first (due to clock skew)
+// // while original client-side context is not timed-out yet
+// }
+// } else if verr, ok := err.(*v3rpc.ErrEmptyKey); ok {
+// // process (verr.Errors)
+// } else {
+// // bad cluster endpoints, which are not etcd servers
+// }
+// }
+//
+// go func() { cli.Close() }()
+// _, err := kvc.Get(ctx, "a")
+// if err != nil {
+// if err == context.Canceled {
+// // grpc balancer calls 'Get' with an inflight client.Close
+// } else if err == grpc.ErrClientConnClosing {
+// // grpc balancer calls 'Get' after client.Close.
+// }
+// }
+//
+package clientv3
diff --git a/vendor/github.com/coreos/etcd/clientv3/health_balancer.go b/vendor/github.com/coreos/etcd/clientv3/health_balancer.go
new file mode 100644
index 00000000..5918cba8
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/health_balancer.go
@@ -0,0 +1,609 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "errors"
+ "net/url"
+ "strings"
+ "sync"
+ "time"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ healthpb "google.golang.org/grpc/health/grpc_health_v1"
+ "google.golang.org/grpc/status"
+)
+
+const (
+ minHealthRetryDuration = 3 * time.Second
+ unknownService = "unknown service grpc.health.v1.Health"
+)
+
+// ErrNoAddrAvilable is returned by Get() when the balancer does not have
+// any active connection to endpoints at the time.
+// This error is returned only when opts.BlockingWait is true.
+var ErrNoAddrAvilable = status.Error(codes.Unavailable, "there is no address available")
+
+type healthCheckFunc func(ep string) (bool, error)
+
+type notifyMsg int
+
+const (
+ notifyReset notifyMsg = iota
+ notifyNext
+)
+
+// healthBalancer does the bare minimum to expose multiple eps
+// to the grpc reconnection code path
+type healthBalancer struct {
+ // addrs are the client's endpoint addresses for grpc
+ addrs []grpc.Address
+
+ // eps holds the raw endpoints from the client
+ eps []string
+
+ // notifyCh notifies grpc of the set of addresses for connecting
+ notifyCh chan []grpc.Address
+
+ // readyc closes once the first connection is up
+ readyc chan struct{}
+ readyOnce sync.Once
+
+ // healthCheck checks an endpoint's health.
+ healthCheck healthCheckFunc
+ healthCheckTimeout time.Duration
+
+ unhealthyMu sync.RWMutex
+ unhealthyHostPorts map[string]time.Time
+
+ // mu protects all fields below.
+ mu sync.RWMutex
+
+ // upc closes when pinAddr transitions from empty to non-empty or the balancer closes.
+ upc chan struct{}
+
+ // downc closes when grpc calls down() on pinAddr
+ downc chan struct{}
+
+ // stopc is closed to signal updateNotifyLoop should stop.
+ stopc chan struct{}
+ stopOnce sync.Once
+ wg sync.WaitGroup
+
+ // donec closes when all goroutines are exited
+ donec chan struct{}
+
+ // updateAddrsC notifies updateNotifyLoop to update addrs.
+ updateAddrsC chan notifyMsg
+
+ // grpc issues TLS cert checks using the string passed into dial so
+ // that string must be the host. To recover the full scheme://host URL,
+ // have a map from hosts to the original endpoint.
+ hostPort2ep map[string]string
+
+ // pinAddr is the currently pinned address; set to the empty string on
+ // initialization and shutdown.
+ pinAddr string
+
+ closed bool
+}
+
+func newHealthBalancer(eps []string, timeout time.Duration, hc healthCheckFunc) *healthBalancer {
+ notifyCh := make(chan []grpc.Address)
+ addrs := eps2addrs(eps)
+ hb := &healthBalancer{
+ addrs: addrs,
+ eps: eps,
+ notifyCh: notifyCh,
+ readyc: make(chan struct{}),
+ healthCheck: hc,
+ unhealthyHostPorts: make(map[string]time.Time),
+ upc: make(chan struct{}),
+ stopc: make(chan struct{}),
+ downc: make(chan struct{}),
+ donec: make(chan struct{}),
+ updateAddrsC: make(chan notifyMsg),
+ hostPort2ep: getHostPort2ep(eps),
+ }
+ if timeout < minHealthRetryDuration {
+ timeout = minHealthRetryDuration
+ }
+ hb.healthCheckTimeout = timeout
+
+ close(hb.downc)
+ go hb.updateNotifyLoop()
+ hb.wg.Add(1)
+ go func() {
+ defer hb.wg.Done()
+ hb.updateUnhealthy()
+ }()
+ return hb
+}
+
+func (b *healthBalancer) Start(target string, config grpc.BalancerConfig) error { return nil }
+
+func (b *healthBalancer) ConnectNotify() <-chan struct{} {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ return b.upc
+}
+
+func (b *healthBalancer) ready() <-chan struct{} { return b.readyc }
+
+func (b *healthBalancer) endpoint(hostPort string) string {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ return b.hostPort2ep[hostPort]
+}
+
+func (b *healthBalancer) pinned() string {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ return b.pinAddr
+}
+
+func (b *healthBalancer) hostPortError(hostPort string, err error) {
+ if b.endpoint(hostPort) == "" {
+ logger.Lvl(4).Infof("clientv3/balancer: %q is stale (skip marking as unhealthy on %q)", hostPort, err.Error())
+ return
+ }
+
+ b.unhealthyMu.Lock()
+ b.unhealthyHostPorts[hostPort] = time.Now()
+ b.unhealthyMu.Unlock()
+ logger.Lvl(4).Infof("clientv3/balancer: %q is marked unhealthy (%q)", hostPort, err.Error())
+}
+
+func (b *healthBalancer) removeUnhealthy(hostPort, msg string) {
+ if b.endpoint(hostPort) == "" {
+ logger.Lvl(4).Infof("clientv3/balancer: %q was not in unhealthy (%q)", hostPort, msg)
+ return
+ }
+
+ b.unhealthyMu.Lock()
+ delete(b.unhealthyHostPorts, hostPort)
+ b.unhealthyMu.Unlock()
+ logger.Lvl(4).Infof("clientv3/balancer: %q is removed from unhealthy (%q)", hostPort, msg)
+}
+
+func (b *healthBalancer) countUnhealthy() (count int) {
+ b.unhealthyMu.RLock()
+ count = len(b.unhealthyHostPorts)
+ b.unhealthyMu.RUnlock()
+ return count
+}
+
+func (b *healthBalancer) isUnhealthy(hostPort string) (unhealthy bool) {
+ b.unhealthyMu.RLock()
+ _, unhealthy = b.unhealthyHostPorts[hostPort]
+ b.unhealthyMu.RUnlock()
+ return unhealthy
+}
+
+func (b *healthBalancer) cleanupUnhealthy() {
+ b.unhealthyMu.Lock()
+ for k, v := range b.unhealthyHostPorts {
+ if time.Since(v) > b.healthCheckTimeout {
+ delete(b.unhealthyHostPorts, k)
+ logger.Lvl(4).Infof("clientv3/balancer: removed %q from unhealthy after %v", k, b.healthCheckTimeout)
+ }
+ }
+ b.unhealthyMu.Unlock()
+}
+
+func (b *healthBalancer) liveAddrs() ([]grpc.Address, map[string]struct{}) {
+ unhealthyCnt := b.countUnhealthy()
+
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+
+ hbAddrs := b.addrs
+ if len(b.addrs) == 1 || unhealthyCnt == 0 || unhealthyCnt == len(b.addrs) {
+ liveHostPorts := make(map[string]struct{}, len(b.hostPort2ep))
+ for k := range b.hostPort2ep {
+ liveHostPorts[k] = struct{}{}
+ }
+ return hbAddrs, liveHostPorts
+ }
+
+ addrs := make([]grpc.Address, 0, len(b.addrs)-unhealthyCnt)
+ liveHostPorts := make(map[string]struct{}, len(addrs))
+ for _, addr := range b.addrs {
+ if !b.isUnhealthy(addr.Addr) {
+ addrs = append(addrs, addr)
+ liveHostPorts[addr.Addr] = struct{}{}
+ }
+ }
+ return addrs, liveHostPorts
+}
+
+func (b *healthBalancer) updateUnhealthy() {
+ for {
+ select {
+ case <-time.After(b.healthCheckTimeout):
+ b.cleanupUnhealthy()
+ pinned := b.pinned()
+ if pinned == "" || b.isUnhealthy(pinned) {
+ select {
+ case b.updateAddrsC <- notifyNext:
+ case <-b.stopc:
+ return
+ }
+ }
+ case <-b.stopc:
+ return
+ }
+ }
+}
+
+func (b *healthBalancer) updateAddrs(eps ...string) {
+ np := getHostPort2ep(eps)
+
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ match := len(np) == len(b.hostPort2ep)
+ if match {
+ for k, v := range np {
+ if b.hostPort2ep[k] != v {
+ match = false
+ break
+ }
+ }
+ }
+ if match {
+ // same endpoints, so no need to update address
+ return
+ }
+
+ b.hostPort2ep = np
+ b.addrs, b.eps = eps2addrs(eps), eps
+
+ b.unhealthyMu.Lock()
+ b.unhealthyHostPorts = make(map[string]time.Time)
+ b.unhealthyMu.Unlock()
+}
+
+func (b *healthBalancer) next() {
+ b.mu.RLock()
+ downc := b.downc
+ b.mu.RUnlock()
+ select {
+ case b.updateAddrsC <- notifyNext:
+ case <-b.stopc:
+ }
+ // wait until disconnect so new RPCs are not issued on old connection
+ select {
+ case <-downc:
+ case <-b.stopc:
+ }
+}
+
+func (b *healthBalancer) updateNotifyLoop() {
+ defer close(b.donec)
+
+ for {
+ b.mu.RLock()
+ upc, downc, addr := b.upc, b.downc, b.pinAddr
+ b.mu.RUnlock()
+ // downc or upc should be closed
+ select {
+ case <-downc:
+ downc = nil
+ default:
+ }
+ select {
+ case <-upc:
+ upc = nil
+ default:
+ }
+ switch {
+ case downc == nil && upc == nil:
+ // stale
+ select {
+ case <-b.stopc:
+ return
+ default:
+ }
+ case downc == nil:
+ b.notifyAddrs(notifyReset)
+ select {
+ case <-upc:
+ case msg := <-b.updateAddrsC:
+ b.notifyAddrs(msg)
+ case <-b.stopc:
+ return
+ }
+ case upc == nil:
+ select {
+ // close connections that are not the pinned address
+ case b.notifyCh <- []grpc.Address{{Addr: addr}}:
+ case <-downc:
+ case <-b.stopc:
+ return
+ }
+ select {
+ case <-downc:
+ b.notifyAddrs(notifyReset)
+ case msg := <-b.updateAddrsC:
+ b.notifyAddrs(msg)
+ case <-b.stopc:
+ return
+ }
+ }
+ }
+}
+
+func (b *healthBalancer) notifyAddrs(msg notifyMsg) {
+ if msg == notifyNext {
+ select {
+ case b.notifyCh <- []grpc.Address{}:
+ case <-b.stopc:
+ return
+ }
+ }
+ b.mu.RLock()
+ pinAddr := b.pinAddr
+ downc := b.downc
+ b.mu.RUnlock()
+ addrs, hostPorts := b.liveAddrs()
+
+ var waitDown bool
+ if pinAddr != "" {
+ _, ok := hostPorts[pinAddr]
+ waitDown = !ok
+ }
+
+ select {
+ case b.notifyCh <- addrs:
+ if waitDown {
+ select {
+ case <-downc:
+ case <-b.stopc:
+ }
+ }
+ case <-b.stopc:
+ }
+}
+
+func (b *healthBalancer) Up(addr grpc.Address) func(error) {
+ if !b.mayPin(addr) {
+ return func(err error) {}
+ }
+
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ // gRPC might call Up after it called Close. We add this check
+ // to "fix" it up at application layer. Otherwise, will panic
+ // if b.upc is already closed.
+ if b.closed {
+ return func(err error) {}
+ }
+
+ // gRPC might call Up on a stale address.
+ // Prevent updating pinAddr with a stale address.
+ if !hasAddr(b.addrs, addr.Addr) {
+ return func(err error) {}
+ }
+
+ if b.pinAddr != "" {
+ logger.Lvl(4).Infof("clientv3/balancer: %q is up but not pinned (already pinned %q)", addr.Addr, b.pinAddr)
+ return func(err error) {}
+ }
+
+ // notify waiting Get()s and pin first connected address
+ close(b.upc)
+ b.downc = make(chan struct{})
+ b.pinAddr = addr.Addr
+ logger.Lvl(4).Infof("clientv3/balancer: pin %q", addr.Addr)
+
+ // notify client that a connection is up
+ b.readyOnce.Do(func() { close(b.readyc) })
+
+ return func(err error) {
+ // If connected to a black hole endpoint or a killed server, the gRPC ping
+ // timeout will induce a network I/O error, and retrying until success;
+ // finding healthy endpoint on retry could take several timeouts and redials.
+ // To avoid wasting retries, gray-list unhealthy endpoints.
+ b.hostPortError(addr.Addr, err)
+
+ b.mu.Lock()
+ b.upc = make(chan struct{})
+ close(b.downc)
+ b.pinAddr = ""
+ b.mu.Unlock()
+ logger.Lvl(4).Infof("clientv3/balancer: unpin %q (%q)", addr.Addr, err.Error())
+ }
+}
+
+func (b *healthBalancer) mayPin(addr grpc.Address) bool {
+ if b.endpoint(addr.Addr) == "" { // stale host:port
+ return false
+ }
+
+ b.unhealthyMu.RLock()
+ unhealthyCnt := len(b.unhealthyHostPorts)
+ failedTime, bad := b.unhealthyHostPorts[addr.Addr]
+ b.unhealthyMu.RUnlock()
+
+ b.mu.RLock()
+ skip := len(b.addrs) == 1 || unhealthyCnt == 0 || len(b.addrs) == unhealthyCnt
+ b.mu.RUnlock()
+ if skip || !bad {
+ return true
+ }
+
+ // prevent isolated member's endpoint from being infinitely retried, as follows:
+ // 1. keepalive pings detects GoAway with http2.ErrCodeEnhanceYourCalm
+ // 2. balancer 'Up' unpins with grpc: failed with network I/O error
+ // 3. grpc-healthcheck still SERVING, thus retry to pin
+ // instead, return before grpc-healthcheck if failed within healthcheck timeout
+ if elapsed := time.Since(failedTime); elapsed < b.healthCheckTimeout {
+ logger.Lvl(4).Infof("clientv3/balancer: %q is up but not pinned (failed %v ago, require minimum %v after failure)", addr.Addr, elapsed, b.healthCheckTimeout)
+ return false
+ }
+
+ if ok, _ := b.healthCheck(addr.Addr); ok {
+ b.removeUnhealthy(addr.Addr, "health check success")
+ return true
+ }
+
+ b.hostPortError(addr.Addr, errors.New("health check failed"))
+ return false
+}
+
+func (b *healthBalancer) Get(ctx context.Context, opts grpc.BalancerGetOptions) (grpc.Address, func(), error) {
+ var (
+ addr string
+ closed bool
+ )
+
+ // If opts.BlockingWait is false (for fail-fast RPCs), it should return
+ // an address it has notified via Notify immediately instead of blocking.
+ if !opts.BlockingWait {
+ b.mu.RLock()
+ closed = b.closed
+ addr = b.pinAddr
+ b.mu.RUnlock()
+ if closed {
+ return grpc.Address{Addr: ""}, nil, grpc.ErrClientConnClosing
+ }
+ if addr == "" {
+ return grpc.Address{Addr: ""}, nil, ErrNoAddrAvilable
+ }
+ return grpc.Address{Addr: addr}, func() {}, nil
+ }
+
+ for {
+ b.mu.RLock()
+ ch := b.upc
+ b.mu.RUnlock()
+ select {
+ case <-ch:
+ case <-b.donec:
+ return grpc.Address{Addr: ""}, nil, grpc.ErrClientConnClosing
+ case <-ctx.Done():
+ return grpc.Address{Addr: ""}, nil, ctx.Err()
+ }
+ b.mu.RLock()
+ closed = b.closed
+ addr = b.pinAddr
+ b.mu.RUnlock()
+ // Close() which sets b.closed = true can be called before Get(), Get() must exit if balancer is closed.
+ if closed {
+ return grpc.Address{Addr: ""}, nil, grpc.ErrClientConnClosing
+ }
+ if addr != "" {
+ break
+ }
+ }
+ return grpc.Address{Addr: addr}, func() {}, nil
+}
+
+func (b *healthBalancer) Notify() <-chan []grpc.Address { return b.notifyCh }
+
+func (b *healthBalancer) Close() error {
+ b.mu.Lock()
+ // In case gRPC calls close twice. TODO: remove the checking
+ // when we are sure that gRPC wont call close twice.
+ if b.closed {
+ b.mu.Unlock()
+ <-b.donec
+ return nil
+ }
+ b.closed = true
+ b.stopOnce.Do(func() { close(b.stopc) })
+ b.pinAddr = ""
+
+ // In the case of following scenario:
+ // 1. upc is not closed; no pinned address
+ // 2. client issues an RPC, calling invoke(), which calls Get(), enters for loop, blocks
+ // 3. client.conn.Close() calls balancer.Close(); closed = true
+ // 4. for loop in Get() never exits since ctx is the context passed in by the client and may not be canceled
+ // we must close upc so Get() exits from blocking on upc
+ select {
+ case <-b.upc:
+ default:
+ // terminate all waiting Get()s
+ close(b.upc)
+ }
+
+ b.mu.Unlock()
+ b.wg.Wait()
+
+ // wait for updateNotifyLoop to finish
+ <-b.donec
+ close(b.notifyCh)
+
+ return nil
+}
+
+func grpcHealthCheck(client *Client, ep string) (bool, error) {
+ conn, err := client.dial(ep)
+ if err != nil {
+ return false, err
+ }
+ defer conn.Close()
+ cli := healthpb.NewHealthClient(conn)
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ resp, err := cli.Check(ctx, &healthpb.HealthCheckRequest{})
+ cancel()
+ if err != nil {
+ if s, ok := status.FromError(err); ok && s.Code() == codes.Unavailable {
+ if s.Message() == unknownService { // etcd < v3.3.0
+ return true, nil
+ }
+ }
+ return false, err
+ }
+ return resp.Status == healthpb.HealthCheckResponse_SERVING, nil
+}
+
+func hasAddr(addrs []grpc.Address, targetAddr string) bool {
+ for _, addr := range addrs {
+ if targetAddr == addr.Addr {
+ return true
+ }
+ }
+ return false
+}
+
+func getHost(ep string) string {
+ url, uerr := url.Parse(ep)
+ if uerr != nil || !strings.Contains(ep, "://") {
+ return ep
+ }
+ return url.Host
+}
+
+func eps2addrs(eps []string) []grpc.Address {
+ addrs := make([]grpc.Address, len(eps))
+ for i := range eps {
+ addrs[i].Addr = getHost(eps[i])
+ }
+ return addrs
+}
+
+func getHostPort2ep(eps []string) map[string]string {
+ hm := make(map[string]string, len(eps))
+ for i := range eps {
+ _, host, _ := parseEndpoint(eps[i])
+ hm[host] = eps[i]
+ }
+ return hm
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/kv.go b/vendor/github.com/coreos/etcd/clientv3/kv.go
new file mode 100644
index 00000000..5a7469bd
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/kv.go
@@ -0,0 +1,177 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ "google.golang.org/grpc"
+)
+
+type (
+ CompactResponse pb.CompactionResponse
+ PutResponse pb.PutResponse
+ GetResponse pb.RangeResponse
+ DeleteResponse pb.DeleteRangeResponse
+ TxnResponse pb.TxnResponse
+)
+
+type KV interface {
+ // Put puts a key-value pair into etcd.
+ // Note that key,value can be plain bytes array and string is
+ // an immutable representation of that bytes array.
+ // To get a string of bytes, do string([]byte{0x10, 0x20}).
+ Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)
+
+ // Get retrieves keys.
+ // By default, Get will return the value for "key", if any.
+ // When passed WithRange(end), Get will return the keys in the range [key, end).
+ // When passed WithFromKey(), Get returns keys greater than or equal to key.
+ // When passed WithRev(rev) with rev > 0, Get retrieves keys at the given revision;
+ // if the required revision is compacted, the request will fail with ErrCompacted .
+ // When passed WithLimit(limit), the number of returned keys is bounded by limit.
+ // When passed WithSort(), the keys will be sorted.
+ Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error)
+
+ // Delete deletes a key, or optionally using WithRange(end), [key, end).
+ Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error)
+
+ // Compact compacts etcd KV history before the given rev.
+ Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error)
+
+ // Do applies a single Op on KV without a transaction.
+ // Do is useful when creating arbitrary operations to be issued at a
+ // later time; the user can range over the operations, calling Do to
+ // execute them. Get/Put/Delete, on the other hand, are best suited
+ // for when the operation should be issued at the time of declaration.
+ Do(ctx context.Context, op Op) (OpResponse, error)
+
+ // Txn creates a transaction.
+ Txn(ctx context.Context) Txn
+}
+
+type OpResponse struct {
+ put *PutResponse
+ get *GetResponse
+ del *DeleteResponse
+ txn *TxnResponse
+}
+
+func (op OpResponse) Put() *PutResponse { return op.put }
+func (op OpResponse) Get() *GetResponse { return op.get }
+func (op OpResponse) Del() *DeleteResponse { return op.del }
+func (op OpResponse) Txn() *TxnResponse { return op.txn }
+
+func (resp *PutResponse) OpResponse() OpResponse {
+ return OpResponse{put: resp}
+}
+func (resp *GetResponse) OpResponse() OpResponse {
+ return OpResponse{get: resp}
+}
+func (resp *DeleteResponse) OpResponse() OpResponse {
+ return OpResponse{del: resp}
+}
+func (resp *TxnResponse) OpResponse() OpResponse {
+ return OpResponse{txn: resp}
+}
+
+type kv struct {
+ remote pb.KVClient
+ callOpts []grpc.CallOption
+}
+
+func NewKV(c *Client) KV {
+ api := &kv{remote: RetryKVClient(c)}
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api
+}
+
+func NewKVFromKVClient(remote pb.KVClient, c *Client) KV {
+ api := &kv{remote: remote}
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api
+}
+
+func (kv *kv) Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) {
+ r, err := kv.Do(ctx, OpPut(key, val, opts...))
+ return r.put, toErr(ctx, err)
+}
+
+func (kv *kv) Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error) {
+ r, err := kv.Do(ctx, OpGet(key, opts...))
+ return r.get, toErr(ctx, err)
+}
+
+func (kv *kv) Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error) {
+ r, err := kv.Do(ctx, OpDelete(key, opts...))
+ return r.del, toErr(ctx, err)
+}
+
+func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) {
+ resp, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest(), kv.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ return (*CompactResponse)(resp), err
+}
+
+func (kv *kv) Txn(ctx context.Context) Txn {
+ return &txn{
+ kv: kv,
+ ctx: ctx,
+ callOpts: kv.callOpts,
+ }
+}
+
+func (kv *kv) Do(ctx context.Context, op Op) (OpResponse, error) {
+ var err error
+ switch op.t {
+ case tRange:
+ var resp *pb.RangeResponse
+ resp, err = kv.remote.Range(ctx, op.toRangeRequest(), kv.callOpts...)
+ if err == nil {
+ return OpResponse{get: (*GetResponse)(resp)}, nil
+ }
+ case tPut:
+ var resp *pb.PutResponse
+ r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue, IgnoreLease: op.ignoreLease}
+ resp, err = kv.remote.Put(ctx, r, kv.callOpts...)
+ if err == nil {
+ return OpResponse{put: (*PutResponse)(resp)}, nil
+ }
+ case tDeleteRange:
+ var resp *pb.DeleteRangeResponse
+ r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
+ resp, err = kv.remote.DeleteRange(ctx, r, kv.callOpts...)
+ if err == nil {
+ return OpResponse{del: (*DeleteResponse)(resp)}, nil
+ }
+ case tTxn:
+ var resp *pb.TxnResponse
+ resp, err = kv.remote.Txn(ctx, op.toTxnRequest(), kv.callOpts...)
+ if err == nil {
+ return OpResponse{txn: (*TxnResponse)(resp)}, nil
+ }
+ default:
+ panic("Unknown op")
+ }
+ return OpResponse{}, toErr(ctx, err)
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/lease.go b/vendor/github.com/coreos/etcd/clientv3/lease.go
new file mode 100644
index 00000000..3729cf37
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/lease.go
@@ -0,0 +1,588 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/metadata"
+)
+
+type (
+ LeaseRevokeResponse pb.LeaseRevokeResponse
+ LeaseID int64
+)
+
+// LeaseGrantResponse wraps the protobuf message LeaseGrantResponse.
+type LeaseGrantResponse struct {
+ *pb.ResponseHeader
+ ID LeaseID
+ TTL int64
+ Error string
+}
+
+// LeaseKeepAliveResponse wraps the protobuf message LeaseKeepAliveResponse.
+type LeaseKeepAliveResponse struct {
+ *pb.ResponseHeader
+ ID LeaseID
+ TTL int64
+}
+
+// LeaseTimeToLiveResponse wraps the protobuf message LeaseTimeToLiveResponse.
+type LeaseTimeToLiveResponse struct {
+ *pb.ResponseHeader
+ ID LeaseID `json:"id"`
+
+ // TTL is the remaining TTL in seconds for the lease; the lease will expire in under TTL+1 seconds. Expired lease will return -1.
+ TTL int64 `json:"ttl"`
+
+ // GrantedTTL is the initial granted time in seconds upon lease creation/renewal.
+ GrantedTTL int64 `json:"granted-ttl"`
+
+ // Keys is the list of keys attached to this lease.
+ Keys [][]byte `json:"keys"`
+}
+
+// LeaseStatus represents a lease status.
+type LeaseStatus struct {
+ ID LeaseID `json:"id"`
+ // TODO: TTL int64
+}
+
+// LeaseLeasesResponse wraps the protobuf message LeaseLeasesResponse.
+type LeaseLeasesResponse struct {
+ *pb.ResponseHeader
+ Leases []LeaseStatus `json:"leases"`
+}
+
+const (
+ // defaultTTL is the assumed lease TTL used for the first keepalive
+ // deadline before the actual TTL is known to the client.
+ defaultTTL = 5 * time.Second
+ // NoLease is a lease ID for the absence of a lease.
+ NoLease LeaseID = 0
+
+ // retryConnWait is how long to wait before retrying request due to an error
+ retryConnWait = 500 * time.Millisecond
+)
+
+// LeaseResponseChSize is the size of buffer to store unsent lease responses.
+// WARNING: DO NOT UPDATE.
+// Only for testing purposes.
+var LeaseResponseChSize = 16
+
+// ErrKeepAliveHalted is returned if client keep alive loop halts with an unexpected error.
+//
+// This usually means that automatic lease renewal via KeepAlive is broken, but KeepAliveOnce will still work as expected.
+type ErrKeepAliveHalted struct {
+ Reason error
+}
+
+func (e ErrKeepAliveHalted) Error() string {
+ s := "etcdclient: leases keep alive halted"
+ if e.Reason != nil {
+ s += ": " + e.Reason.Error()
+ }
+ return s
+}
+
+type Lease interface {
+ // Grant creates a new lease.
+ Grant(ctx context.Context, ttl int64) (*LeaseGrantResponse, error)
+
+ // Revoke revokes the given lease.
+ Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, error)
+
+ // TimeToLive retrieves the lease information of the given lease ID.
+ TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption) (*LeaseTimeToLiveResponse, error)
+
+ // Leases retrieves all leases.
+ Leases(ctx context.Context) (*LeaseLeasesResponse, error)
+
+ // KeepAlive keeps the given lease alive forever. If the keepalive response
+ // posted to the channel is not consumed immediately, the lease client will
+ // continue sending keep alive requests to the etcd server at least every
+ // second until latest response is consumed.
+ //
+ // The returned "LeaseKeepAliveResponse" channel closes if underlying keep
+ // alive stream is interrupted in some way the client cannot handle itself;
+ // given context "ctx" is canceled or timed out. "LeaseKeepAliveResponse"
+ // from this closed channel is nil.
+ //
+ // If client keep alive loop halts with an unexpected error (e.g. "etcdserver:
+ // no leader") or canceled by the caller (e.g. context.Canceled), the error
+ // is returned. Otherwise, it retries.
+ //
+ // TODO(v4.0): post errors to last keep alive message before closing
+ // (see https://github.com/coreos/etcd/pull/7866)
+ KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error)
+
+ // KeepAliveOnce renews the lease once. The response corresponds to the
+ // first message from calling KeepAlive. If the response has a recoverable
+ // error, KeepAliveOnce will retry the RPC with a new keep alive message.
+ //
+ // In most of the cases, Keepalive should be used instead of KeepAliveOnce.
+ KeepAliveOnce(ctx context.Context, id LeaseID) (*LeaseKeepAliveResponse, error)
+
+ // Close releases all resources Lease keeps for efficient communication
+ // with the etcd server.
+ Close() error
+}
+
+type lessor struct {
+ mu sync.Mutex // guards all fields
+
+ // donec is closed and loopErr is set when recvKeepAliveLoop stops
+ donec chan struct{}
+ loopErr error
+
+ remote pb.LeaseClient
+
+ stream pb.Lease_LeaseKeepAliveClient
+ streamCancel context.CancelFunc
+
+ stopCtx context.Context
+ stopCancel context.CancelFunc
+
+ keepAlives map[LeaseID]*keepAlive
+
+ // firstKeepAliveTimeout is the timeout for the first keepalive request
+ // before the actual TTL is known to the lease client
+ firstKeepAliveTimeout time.Duration
+
+ // firstKeepAliveOnce ensures stream starts after first KeepAlive call.
+ firstKeepAliveOnce sync.Once
+
+ callOpts []grpc.CallOption
+}
+
+// keepAlive multiplexes a keepalive for a lease over multiple channels
+type keepAlive struct {
+ chs []chan<- *LeaseKeepAliveResponse
+ ctxs []context.Context
+ // deadline is the time the keep alive channels close if no response
+ deadline time.Time
+ // nextKeepAlive is when to send the next keep alive message
+ nextKeepAlive time.Time
+ // donec is closed on lease revoke, expiration, or cancel.
+ donec chan struct{}
+}
+
+func NewLease(c *Client) Lease {
+ return NewLeaseFromLeaseClient(RetryLeaseClient(c), c, c.cfg.DialTimeout+time.Second)
+}
+
+func NewLeaseFromLeaseClient(remote pb.LeaseClient, c *Client, keepAliveTimeout time.Duration) Lease {
+ l := &lessor{
+ donec: make(chan struct{}),
+ keepAlives: make(map[LeaseID]*keepAlive),
+ remote: remote,
+ firstKeepAliveTimeout: keepAliveTimeout,
+ }
+ if l.firstKeepAliveTimeout == time.Second {
+ l.firstKeepAliveTimeout = defaultTTL
+ }
+ if c != nil {
+ l.callOpts = c.callOpts
+ }
+ reqLeaderCtx := WithRequireLeader(context.Background())
+ l.stopCtx, l.stopCancel = context.WithCancel(reqLeaderCtx)
+ return l
+}
+
+func (l *lessor) Grant(ctx context.Context, ttl int64) (*LeaseGrantResponse, error) {
+ r := &pb.LeaseGrantRequest{TTL: ttl}
+ resp, err := l.remote.LeaseGrant(ctx, r, l.callOpts...)
+ if err == nil {
+ gresp := &LeaseGrantResponse{
+ ResponseHeader: resp.GetHeader(),
+ ID: LeaseID(resp.ID),
+ TTL: resp.TTL,
+ Error: resp.Error,
+ }
+ return gresp, nil
+ }
+ return nil, toErr(ctx, err)
+}
+
+func (l *lessor) Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, error) {
+ r := &pb.LeaseRevokeRequest{ID: int64(id)}
+ resp, err := l.remote.LeaseRevoke(ctx, r, l.callOpts...)
+ if err == nil {
+ return (*LeaseRevokeResponse)(resp), nil
+ }
+ return nil, toErr(ctx, err)
+}
+
+func (l *lessor) TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption) (*LeaseTimeToLiveResponse, error) {
+ r := toLeaseTimeToLiveRequest(id, opts...)
+ resp, err := l.remote.LeaseTimeToLive(ctx, r, l.callOpts...)
+ if err == nil {
+ gresp := &LeaseTimeToLiveResponse{
+ ResponseHeader: resp.GetHeader(),
+ ID: LeaseID(resp.ID),
+ TTL: resp.TTL,
+ GrantedTTL: resp.GrantedTTL,
+ Keys: resp.Keys,
+ }
+ return gresp, nil
+ }
+ return nil, toErr(ctx, err)
+}
+
+func (l *lessor) Leases(ctx context.Context) (*LeaseLeasesResponse, error) {
+ resp, err := l.remote.LeaseLeases(ctx, &pb.LeaseLeasesRequest{}, l.callOpts...)
+ if err == nil {
+ leases := make([]LeaseStatus, len(resp.Leases))
+ for i := range resp.Leases {
+ leases[i] = LeaseStatus{ID: LeaseID(resp.Leases[i].ID)}
+ }
+ return &LeaseLeasesResponse{ResponseHeader: resp.GetHeader(), Leases: leases}, nil
+ }
+ return nil, toErr(ctx, err)
+}
+
+func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) {
+ ch := make(chan *LeaseKeepAliveResponse, LeaseResponseChSize)
+
+ l.mu.Lock()
+ // ensure that recvKeepAliveLoop is still running
+ select {
+ case <-l.donec:
+ err := l.loopErr
+ l.mu.Unlock()
+ close(ch)
+ return ch, ErrKeepAliveHalted{Reason: err}
+ default:
+ }
+ ka, ok := l.keepAlives[id]
+ if !ok {
+ // create fresh keep alive
+ ka = &keepAlive{
+ chs: []chan<- *LeaseKeepAliveResponse{ch},
+ ctxs: []context.Context{ctx},
+ deadline: time.Now().Add(l.firstKeepAliveTimeout),
+ nextKeepAlive: time.Now(),
+ donec: make(chan struct{}),
+ }
+ l.keepAlives[id] = ka
+ } else {
+ // add channel and context to existing keep alive
+ ka.ctxs = append(ka.ctxs, ctx)
+ ka.chs = append(ka.chs, ch)
+ }
+ l.mu.Unlock()
+
+ go l.keepAliveCtxCloser(id, ctx, ka.donec)
+ l.firstKeepAliveOnce.Do(func() {
+ go l.recvKeepAliveLoop()
+ go l.deadlineLoop()
+ })
+
+ return ch, nil
+}
+
+func (l *lessor) KeepAliveOnce(ctx context.Context, id LeaseID) (*LeaseKeepAliveResponse, error) {
+ for {
+ resp, err := l.keepAliveOnce(ctx, id)
+ if err == nil {
+ if resp.TTL <= 0 {
+ err = rpctypes.ErrLeaseNotFound
+ }
+ return resp, err
+ }
+ if isHaltErr(ctx, err) {
+ return nil, toErr(ctx, err)
+ }
+ }
+}
+
+func (l *lessor) Close() error {
+ l.stopCancel()
+ // close for synchronous teardown if stream goroutines never launched
+ l.firstKeepAliveOnce.Do(func() { close(l.donec) })
+ <-l.donec
+ return nil
+}
+
+func (l *lessor) keepAliveCtxCloser(id LeaseID, ctx context.Context, donec <-chan struct{}) {
+ select {
+ case <-donec:
+ return
+ case <-l.donec:
+ return
+ case <-ctx.Done():
+ }
+
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ ka, ok := l.keepAlives[id]
+ if !ok {
+ return
+ }
+
+ // close channel and remove context if still associated with keep alive
+ for i, c := range ka.ctxs {
+ if c == ctx {
+ close(ka.chs[i])
+ ka.ctxs = append(ka.ctxs[:i], ka.ctxs[i+1:]...)
+ ka.chs = append(ka.chs[:i], ka.chs[i+1:]...)
+ break
+ }
+ }
+ // remove if no one more listeners
+ if len(ka.chs) == 0 {
+ delete(l.keepAlives, id)
+ }
+}
+
+// closeRequireLeader scans keepAlives for ctxs that have require leader
+// and closes the associated channels.
+func (l *lessor) closeRequireLeader() {
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ for _, ka := range l.keepAlives {
+ reqIdxs := 0
+ // find all required leader channels, close, mark as nil
+ for i, ctx := range ka.ctxs {
+ md, ok := metadata.FromOutgoingContext(ctx)
+ if !ok {
+ continue
+ }
+ ks := md[rpctypes.MetadataRequireLeaderKey]
+ if len(ks) < 1 || ks[0] != rpctypes.MetadataHasLeader {
+ continue
+ }
+ close(ka.chs[i])
+ ka.chs[i] = nil
+ reqIdxs++
+ }
+ if reqIdxs == 0 {
+ continue
+ }
+ // remove all channels that required a leader from keepalive
+ newChs := make([]chan<- *LeaseKeepAliveResponse, len(ka.chs)-reqIdxs)
+ newCtxs := make([]context.Context, len(newChs))
+ newIdx := 0
+ for i := range ka.chs {
+ if ka.chs[i] == nil {
+ continue
+ }
+ newChs[newIdx], newCtxs[newIdx] = ka.chs[i], ka.ctxs[newIdx]
+ newIdx++
+ }
+ ka.chs, ka.ctxs = newChs, newCtxs
+ }
+}
+
+func (l *lessor) keepAliveOnce(ctx context.Context, id LeaseID) (*LeaseKeepAliveResponse, error) {
+ cctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+
+ stream, err := l.remote.LeaseKeepAlive(cctx, l.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+
+ err = stream.Send(&pb.LeaseKeepAliveRequest{ID: int64(id)})
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+
+ resp, rerr := stream.Recv()
+ if rerr != nil {
+ return nil, toErr(ctx, rerr)
+ }
+
+ karesp := &LeaseKeepAliveResponse{
+ ResponseHeader: resp.GetHeader(),
+ ID: LeaseID(resp.ID),
+ TTL: resp.TTL,
+ }
+ return karesp, nil
+}
+
+func (l *lessor) recvKeepAliveLoop() (gerr error) {
+ defer func() {
+ l.mu.Lock()
+ close(l.donec)
+ l.loopErr = gerr
+ for _, ka := range l.keepAlives {
+ ka.close()
+ }
+ l.keepAlives = make(map[LeaseID]*keepAlive)
+ l.mu.Unlock()
+ }()
+
+ for {
+ stream, err := l.resetRecv()
+ if err != nil {
+ if canceledByCaller(l.stopCtx, err) {
+ return err
+ }
+ } else {
+ for {
+ resp, err := stream.Recv()
+ if err != nil {
+ if canceledByCaller(l.stopCtx, err) {
+ return err
+ }
+
+ if toErr(l.stopCtx, err) == rpctypes.ErrNoLeader {
+ l.closeRequireLeader()
+ }
+ break
+ }
+
+ l.recvKeepAlive(resp)
+ }
+ }
+
+ select {
+ case <-time.After(retryConnWait):
+ continue
+ case <-l.stopCtx.Done():
+ return l.stopCtx.Err()
+ }
+ }
+}
+
+// resetRecv opens a new lease stream and starts sending keep alive requests.
+func (l *lessor) resetRecv() (pb.Lease_LeaseKeepAliveClient, error) {
+ sctx, cancel := context.WithCancel(l.stopCtx)
+ stream, err := l.remote.LeaseKeepAlive(sctx, l.callOpts...)
+ if err != nil {
+ cancel()
+ return nil, err
+ }
+
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ if l.stream != nil && l.streamCancel != nil {
+ l.streamCancel()
+ }
+
+ l.streamCancel = cancel
+ l.stream = stream
+
+ go l.sendKeepAliveLoop(stream)
+ return stream, nil
+}
+
+// recvKeepAlive updates a lease based on its LeaseKeepAliveResponse
+func (l *lessor) recvKeepAlive(resp *pb.LeaseKeepAliveResponse) {
+ karesp := &LeaseKeepAliveResponse{
+ ResponseHeader: resp.GetHeader(),
+ ID: LeaseID(resp.ID),
+ TTL: resp.TTL,
+ }
+
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ ka, ok := l.keepAlives[karesp.ID]
+ if !ok {
+ return
+ }
+
+ if karesp.TTL <= 0 {
+ // lease expired; close all keep alive channels
+ delete(l.keepAlives, karesp.ID)
+ ka.close()
+ return
+ }
+
+ // send update to all channels
+ nextKeepAlive := time.Now().Add((time.Duration(karesp.TTL) * time.Second) / 3.0)
+ ka.deadline = time.Now().Add(time.Duration(karesp.TTL) * time.Second)
+ for _, ch := range ka.chs {
+ select {
+ case ch <- karesp:
+ default:
+ }
+ // still advance in order to rate-limit keep-alive sends
+ ka.nextKeepAlive = nextKeepAlive
+ }
+}
+
+// deadlineLoop reaps any keep alive channels that have not received a response
+// within the lease TTL
+func (l *lessor) deadlineLoop() {
+ for {
+ select {
+ case <-time.After(time.Second):
+ case <-l.donec:
+ return
+ }
+ now := time.Now()
+ l.mu.Lock()
+ for id, ka := range l.keepAlives {
+ if ka.deadline.Before(now) {
+ // waited too long for response; lease may be expired
+ ka.close()
+ delete(l.keepAlives, id)
+ }
+ }
+ l.mu.Unlock()
+ }
+}
+
+// sendKeepAliveLoop sends keep alive requests for the lifetime of the given stream.
+func (l *lessor) sendKeepAliveLoop(stream pb.Lease_LeaseKeepAliveClient) {
+ for {
+ var tosend []LeaseID
+
+ now := time.Now()
+ l.mu.Lock()
+ for id, ka := range l.keepAlives {
+ if ka.nextKeepAlive.Before(now) {
+ tosend = append(tosend, id)
+ }
+ }
+ l.mu.Unlock()
+
+ for _, id := range tosend {
+ r := &pb.LeaseKeepAliveRequest{ID: int64(id)}
+ if err := stream.Send(r); err != nil {
+ // TODO do something with this error?
+ return
+ }
+ }
+
+ select {
+ case <-time.After(500 * time.Millisecond):
+ case <-stream.Context().Done():
+ return
+ case <-l.donec:
+ return
+ case <-l.stopCtx.Done():
+ return
+ }
+ }
+}
+
+func (ka *keepAlive) close() {
+ close(ka.donec)
+ for _, ch := range ka.chs {
+ close(ch)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/logger.go b/vendor/github.com/coreos/etcd/clientv3/logger.go
new file mode 100644
index 00000000..782e3131
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/logger.go
@@ -0,0 +1,135 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "io/ioutil"
+ "sync"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+// Logger is the logger used by client library.
+// It implements grpclog.LoggerV2 interface.
+type Logger interface {
+ grpclog.LoggerV2
+
+ // Lvl returns logger if logger's verbosity level >= "lvl".
+ // Otherwise, logger that discards all logs.
+ Lvl(lvl int) Logger
+
+ // to satisfy capnslog
+
+ Print(args ...interface{})
+ Printf(format string, args ...interface{})
+ Println(args ...interface{})
+}
+
+var (
+ loggerMu sync.RWMutex
+ logger Logger
+)
+
+type settableLogger struct {
+ l grpclog.LoggerV2
+ mu sync.RWMutex
+}
+
+func init() {
+ // disable client side logs by default
+ logger = &settableLogger{}
+ SetLogger(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, ioutil.Discard))
+}
+
+// SetLogger sets client-side Logger.
+func SetLogger(l grpclog.LoggerV2) {
+ loggerMu.Lock()
+ logger = NewLogger(l)
+ // override grpclog so that any changes happen with locking
+ grpclog.SetLoggerV2(logger)
+ loggerMu.Unlock()
+}
+
+// GetLogger returns the current logger.
+func GetLogger() Logger {
+ loggerMu.RLock()
+ l := logger
+ loggerMu.RUnlock()
+ return l
+}
+
+// NewLogger returns a new Logger with grpclog.LoggerV2.
+func NewLogger(gl grpclog.LoggerV2) Logger {
+ return &settableLogger{l: gl}
+}
+
+func (s *settableLogger) get() grpclog.LoggerV2 {
+ s.mu.RLock()
+ l := s.l
+ s.mu.RUnlock()
+ return l
+}
+
+// implement the grpclog.LoggerV2 interface
+
+func (s *settableLogger) Info(args ...interface{}) { s.get().Info(args...) }
+func (s *settableLogger) Infof(format string, args ...interface{}) { s.get().Infof(format, args...) }
+func (s *settableLogger) Infoln(args ...interface{}) { s.get().Infoln(args...) }
+func (s *settableLogger) Warning(args ...interface{}) { s.get().Warning(args...) }
+func (s *settableLogger) Warningf(format string, args ...interface{}) {
+ s.get().Warningf(format, args...)
+}
+func (s *settableLogger) Warningln(args ...interface{}) { s.get().Warningln(args...) }
+func (s *settableLogger) Error(args ...interface{}) { s.get().Error(args...) }
+func (s *settableLogger) Errorf(format string, args ...interface{}) {
+ s.get().Errorf(format, args...)
+}
+func (s *settableLogger) Errorln(args ...interface{}) { s.get().Errorln(args...) }
+func (s *settableLogger) Fatal(args ...interface{}) { s.get().Fatal(args...) }
+func (s *settableLogger) Fatalf(format string, args ...interface{}) { s.get().Fatalf(format, args...) }
+func (s *settableLogger) Fatalln(args ...interface{}) { s.get().Fatalln(args...) }
+func (s *settableLogger) Print(args ...interface{}) { s.get().Info(args...) }
+func (s *settableLogger) Printf(format string, args ...interface{}) { s.get().Infof(format, args...) }
+func (s *settableLogger) Println(args ...interface{}) { s.get().Infoln(args...) }
+func (s *settableLogger) V(l int) bool { return s.get().V(l) }
+func (s *settableLogger) Lvl(lvl int) Logger {
+ s.mu.RLock()
+ l := s.l
+ s.mu.RUnlock()
+ if l.V(lvl) {
+ return s
+ }
+ return &noLogger{}
+}
+
+type noLogger struct{}
+
+func (*noLogger) Info(args ...interface{}) {}
+func (*noLogger) Infof(format string, args ...interface{}) {}
+func (*noLogger) Infoln(args ...interface{}) {}
+func (*noLogger) Warning(args ...interface{}) {}
+func (*noLogger) Warningf(format string, args ...interface{}) {}
+func (*noLogger) Warningln(args ...interface{}) {}
+func (*noLogger) Error(args ...interface{}) {}
+func (*noLogger) Errorf(format string, args ...interface{}) {}
+func (*noLogger) Errorln(args ...interface{}) {}
+func (*noLogger) Fatal(args ...interface{}) {}
+func (*noLogger) Fatalf(format string, args ...interface{}) {}
+func (*noLogger) Fatalln(args ...interface{}) {}
+func (*noLogger) Print(args ...interface{}) {}
+func (*noLogger) Printf(format string, args ...interface{}) {}
+func (*noLogger) Println(args ...interface{}) {}
+func (*noLogger) V(l int) bool { return false }
+func (ng *noLogger) Lvl(lvl int) Logger { return ng }
diff --git a/vendor/github.com/coreos/etcd/clientv3/maintenance.go b/vendor/github.com/coreos/etcd/clientv3/maintenance.go
new file mode 100644
index 00000000..f60cfbe4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/maintenance.go
@@ -0,0 +1,226 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "io"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ "google.golang.org/grpc"
+)
+
+type (
+ DefragmentResponse pb.DefragmentResponse
+ AlarmResponse pb.AlarmResponse
+ AlarmMember pb.AlarmMember
+ StatusResponse pb.StatusResponse
+ HashKVResponse pb.HashKVResponse
+ MoveLeaderResponse pb.MoveLeaderResponse
+)
+
+type Maintenance interface {
+ // AlarmList gets all active alarms.
+ AlarmList(ctx context.Context) (*AlarmResponse, error)
+
+ // AlarmDisarm disarms a given alarm.
+ AlarmDisarm(ctx context.Context, m *AlarmMember) (*AlarmResponse, error)
+
+ // Defragment releases wasted space from internal fragmentation on a given etcd member.
+ // Defragment is only needed when deleting a large number of keys and want to reclaim
+ // the resources.
+ // Defragment is an expensive operation. User should avoid defragmenting multiple members
+ // at the same time.
+ // To defragment multiple members in the cluster, user need to call defragment multiple
+ // times with different endpoints.
+ Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error)
+
+ // Status gets the status of the endpoint.
+ Status(ctx context.Context, endpoint string) (*StatusResponse, error)
+
+ // HashKV returns a hash of the KV state at the time of the RPC.
+ // If revision is zero, the hash is computed on all keys. If the revision
+ // is non-zero, the hash is computed on all keys at or below the given revision.
+ HashKV(ctx context.Context, endpoint string, rev int64) (*HashKVResponse, error)
+
+ // Snapshot provides a reader for a point-in-time snapshot of etcd.
+ Snapshot(ctx context.Context) (io.ReadCloser, error)
+
+ // MoveLeader requests current leader to transfer its leadership to the transferee.
+ // Request must be made to the leader.
+ MoveLeader(ctx context.Context, transfereeID uint64) (*MoveLeaderResponse, error)
+}
+
+type maintenance struct {
+ dial func(endpoint string) (pb.MaintenanceClient, func(), error)
+ remote pb.MaintenanceClient
+ callOpts []grpc.CallOption
+}
+
+func NewMaintenance(c *Client) Maintenance {
+ api := &maintenance{
+ dial: func(endpoint string) (pb.MaintenanceClient, func(), error) {
+ conn, err := c.dial(endpoint)
+ if err != nil {
+ return nil, nil, err
+ }
+ cancel := func() { conn.Close() }
+ return RetryMaintenanceClient(c, conn), cancel, nil
+ },
+ remote: RetryMaintenanceClient(c, c.conn),
+ }
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api
+}
+
+func NewMaintenanceFromMaintenanceClient(remote pb.MaintenanceClient, c *Client) Maintenance {
+ api := &maintenance{
+ dial: func(string) (pb.MaintenanceClient, func(), error) {
+ return remote, func() {}, nil
+ },
+ remote: remote,
+ }
+ if c != nil {
+ api.callOpts = c.callOpts
+ }
+ return api
+}
+
+func (m *maintenance) AlarmList(ctx context.Context) (*AlarmResponse, error) {
+ req := &pb.AlarmRequest{
+ Action: pb.AlarmRequest_GET,
+ MemberID: 0, // all
+ Alarm: pb.AlarmType_NONE, // all
+ }
+ resp, err := m.remote.Alarm(ctx, req, m.callOpts...)
+ if err == nil {
+ return (*AlarmResponse)(resp), nil
+ }
+ return nil, toErr(ctx, err)
+}
+
+func (m *maintenance) AlarmDisarm(ctx context.Context, am *AlarmMember) (*AlarmResponse, error) {
+ req := &pb.AlarmRequest{
+ Action: pb.AlarmRequest_DEACTIVATE,
+ MemberID: am.MemberID,
+ Alarm: am.Alarm,
+ }
+
+ if req.MemberID == 0 && req.Alarm == pb.AlarmType_NONE {
+ ar, err := m.AlarmList(ctx)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ ret := AlarmResponse{}
+ for _, am := range ar.Alarms {
+ dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am))
+ if derr != nil {
+ return nil, toErr(ctx, derr)
+ }
+ ret.Alarms = append(ret.Alarms, dresp.Alarms...)
+ }
+ return &ret, nil
+ }
+
+ resp, err := m.remote.Alarm(ctx, req, m.callOpts...)
+ if err == nil {
+ return (*AlarmResponse)(resp), nil
+ }
+ return nil, toErr(ctx, err)
+}
+
+func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error) {
+ remote, cancel, err := m.dial(endpoint)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ defer cancel()
+ resp, err := remote.Defragment(ctx, &pb.DefragmentRequest{}, m.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ return (*DefragmentResponse)(resp), nil
+}
+
+func (m *maintenance) Status(ctx context.Context, endpoint string) (*StatusResponse, error) {
+ remote, cancel, err := m.dial(endpoint)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ defer cancel()
+ resp, err := remote.Status(ctx, &pb.StatusRequest{}, m.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ return (*StatusResponse)(resp), nil
+}
+
+func (m *maintenance) HashKV(ctx context.Context, endpoint string, rev int64) (*HashKVResponse, error) {
+ remote, cancel, err := m.dial(endpoint)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ defer cancel()
+ resp, err := remote.HashKV(ctx, &pb.HashKVRequest{Revision: rev}, m.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+ return (*HashKVResponse)(resp), nil
+}
+
+func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) {
+ ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{}, m.callOpts...)
+ if err != nil {
+ return nil, toErr(ctx, err)
+ }
+
+ pr, pw := io.Pipe()
+ go func() {
+ for {
+ resp, err := ss.Recv()
+ if err != nil {
+ pw.CloseWithError(err)
+ return
+ }
+ if resp == nil && err == nil {
+ break
+ }
+ if _, werr := pw.Write(resp.Blob); werr != nil {
+ pw.CloseWithError(werr)
+ return
+ }
+ }
+ pw.Close()
+ }()
+ return &snapshotReadCloser{ctx: ctx, ReadCloser: pr}, nil
+}
+
+type snapshotReadCloser struct {
+ ctx context.Context
+ io.ReadCloser
+}
+
+func (rc *snapshotReadCloser) Read(p []byte) (n int, err error) {
+ n, err = rc.ReadCloser.Read(p)
+ return n, toErr(rc.ctx, err)
+}
+
+func (m *maintenance) MoveLeader(ctx context.Context, transfereeID uint64) (*MoveLeaderResponse, error) {
+ resp, err := m.remote.MoveLeader(ctx, &pb.MoveLeaderRequest{TargetID: transfereeID}, m.callOpts...)
+ return (*MoveLeaderResponse)(resp), toErr(ctx, err)
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/op.go b/vendor/github.com/coreos/etcd/clientv3/op.go
new file mode 100644
index 00000000..c6ec5bf5
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/op.go
@@ -0,0 +1,513 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+type opType int
+
+const (
+ // A default Op has opType 0, which is invalid.
+ tRange opType = iota + 1
+ tPut
+ tDeleteRange
+ tTxn
+)
+
+var (
+ noPrefixEnd = []byte{0}
+)
+
+// Op represents an Operation that kv can execute.
+type Op struct {
+ t opType
+ key []byte
+ end []byte
+
+ // for range
+ limit int64
+ sort *SortOption
+ serializable bool
+ keysOnly bool
+ countOnly bool
+ minModRev int64
+ maxModRev int64
+ minCreateRev int64
+ maxCreateRev int64
+
+ // for range, watch
+ rev int64
+
+ // for watch, put, delete
+ prevKV bool
+
+ // for put
+ ignoreValue bool
+ ignoreLease bool
+
+ // progressNotify is for progress updates.
+ progressNotify bool
+ // createdNotify is for created event
+ createdNotify bool
+ // filters for watchers
+ filterPut bool
+ filterDelete bool
+
+ // for put
+ val []byte
+ leaseID LeaseID
+
+ // txn
+ cmps []Cmp
+ thenOps []Op
+ elseOps []Op
+}
+
+// accessors / mutators
+
+func (op Op) IsTxn() bool { return op.t == tTxn }
+func (op Op) Txn() ([]Cmp, []Op, []Op) { return op.cmps, op.thenOps, op.elseOps }
+
+// KeyBytes returns the byte slice holding the Op's key.
+func (op Op) KeyBytes() []byte { return op.key }
+
+// WithKeyBytes sets the byte slice for the Op's key.
+func (op *Op) WithKeyBytes(key []byte) { op.key = key }
+
+// RangeBytes returns the byte slice holding with the Op's range end, if any.
+func (op Op) RangeBytes() []byte { return op.end }
+
+// Rev returns the requested revision, if any.
+func (op Op) Rev() int64 { return op.rev }
+
+// IsPut returns true iff the operation is a Put.
+func (op Op) IsPut() bool { return op.t == tPut }
+
+// IsGet returns true iff the operation is a Get.
+func (op Op) IsGet() bool { return op.t == tRange }
+
+// IsDelete returns true iff the operation is a Delete.
+func (op Op) IsDelete() bool { return op.t == tDeleteRange }
+
+// IsSerializable returns true if the serializable field is true.
+func (op Op) IsSerializable() bool { return op.serializable == true }
+
+// IsKeysOnly returns whether keysOnly is set.
+func (op Op) IsKeysOnly() bool { return op.keysOnly == true }
+
+// IsCountOnly returns whether countOnly is set.
+func (op Op) IsCountOnly() bool { return op.countOnly == true }
+
+// MinModRev returns the operation's minimum modify revision.
+func (op Op) MinModRev() int64 { return op.minModRev }
+
+// MaxModRev returns the operation's maximum modify revision.
+func (op Op) MaxModRev() int64 { return op.maxModRev }
+
+// MinCreateRev returns the operation's minimum create revision.
+func (op Op) MinCreateRev() int64 { return op.minCreateRev }
+
+// MaxCreateRev returns the operation's maximum create revision.
+func (op Op) MaxCreateRev() int64 { return op.maxCreateRev }
+
+// WithRangeBytes sets the byte slice for the Op's range end.
+func (op *Op) WithRangeBytes(end []byte) { op.end = end }
+
+// ValueBytes returns the byte slice holding the Op's value, if any.
+func (op Op) ValueBytes() []byte { return op.val }
+
+// WithValueBytes sets the byte slice for the Op's value.
+func (op *Op) WithValueBytes(v []byte) { op.val = v }
+
+func (op Op) toRangeRequest() *pb.RangeRequest {
+ if op.t != tRange {
+ panic("op.t != tRange")
+ }
+ r := &pb.RangeRequest{
+ Key: op.key,
+ RangeEnd: op.end,
+ Limit: op.limit,
+ Revision: op.rev,
+ Serializable: op.serializable,
+ KeysOnly: op.keysOnly,
+ CountOnly: op.countOnly,
+ MinModRevision: op.minModRev,
+ MaxModRevision: op.maxModRev,
+ MinCreateRevision: op.minCreateRev,
+ MaxCreateRevision: op.maxCreateRev,
+ }
+ if op.sort != nil {
+ r.SortOrder = pb.RangeRequest_SortOrder(op.sort.Order)
+ r.SortTarget = pb.RangeRequest_SortTarget(op.sort.Target)
+ }
+ return r
+}
+
+func (op Op) toTxnRequest() *pb.TxnRequest {
+ thenOps := make([]*pb.RequestOp, len(op.thenOps))
+ for i, tOp := range op.thenOps {
+ thenOps[i] = tOp.toRequestOp()
+ }
+ elseOps := make([]*pb.RequestOp, len(op.elseOps))
+ for i, eOp := range op.elseOps {
+ elseOps[i] = eOp.toRequestOp()
+ }
+ cmps := make([]*pb.Compare, len(op.cmps))
+ for i := range op.cmps {
+ cmps[i] = (*pb.Compare)(&op.cmps[i])
+ }
+ return &pb.TxnRequest{Compare: cmps, Success: thenOps, Failure: elseOps}
+}
+
+func (op Op) toRequestOp() *pb.RequestOp {
+ switch op.t {
+ case tRange:
+ return &pb.RequestOp{Request: &pb.RequestOp_RequestRange{RequestRange: op.toRangeRequest()}}
+ case tPut:
+ r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue, IgnoreLease: op.ignoreLease}
+ return &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: r}}
+ case tDeleteRange:
+ r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
+ return &pb.RequestOp{Request: &pb.RequestOp_RequestDeleteRange{RequestDeleteRange: r}}
+ case tTxn:
+ return &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{RequestTxn: op.toTxnRequest()}}
+ default:
+ panic("Unknown Op")
+ }
+}
+
+func (op Op) isWrite() bool {
+ if op.t == tTxn {
+ for _, tOp := range op.thenOps {
+ if tOp.isWrite() {
+ return true
+ }
+ }
+ for _, tOp := range op.elseOps {
+ if tOp.isWrite() {
+ return true
+ }
+ }
+ return false
+ }
+ return op.t != tRange
+}
+
+func OpGet(key string, opts ...OpOption) Op {
+ ret := Op{t: tRange, key: []byte(key)}
+ ret.applyOpts(opts)
+ return ret
+}
+
+func OpDelete(key string, opts ...OpOption) Op {
+ ret := Op{t: tDeleteRange, key: []byte(key)}
+ ret.applyOpts(opts)
+ switch {
+ case ret.leaseID != 0:
+ panic("unexpected lease in delete")
+ case ret.limit != 0:
+ panic("unexpected limit in delete")
+ case ret.rev != 0:
+ panic("unexpected revision in delete")
+ case ret.sort != nil:
+ panic("unexpected sort in delete")
+ case ret.serializable:
+ panic("unexpected serializable in delete")
+ case ret.countOnly:
+ panic("unexpected countOnly in delete")
+ case ret.minModRev != 0, ret.maxModRev != 0:
+ panic("unexpected mod revision filter in delete")
+ case ret.minCreateRev != 0, ret.maxCreateRev != 0:
+ panic("unexpected create revision filter in delete")
+ case ret.filterDelete, ret.filterPut:
+ panic("unexpected filter in delete")
+ case ret.createdNotify:
+ panic("unexpected createdNotify in delete")
+ }
+ return ret
+}
+
+func OpPut(key, val string, opts ...OpOption) Op {
+ ret := Op{t: tPut, key: []byte(key), val: []byte(val)}
+ ret.applyOpts(opts)
+ switch {
+ case ret.end != nil:
+ panic("unexpected range in put")
+ case ret.limit != 0:
+ panic("unexpected limit in put")
+ case ret.rev != 0:
+ panic("unexpected revision in put")
+ case ret.sort != nil:
+ panic("unexpected sort in put")
+ case ret.serializable:
+ panic("unexpected serializable in put")
+ case ret.countOnly:
+ panic("unexpected countOnly in put")
+ case ret.minModRev != 0, ret.maxModRev != 0:
+ panic("unexpected mod revision filter in put")
+ case ret.minCreateRev != 0, ret.maxCreateRev != 0:
+ panic("unexpected create revision filter in put")
+ case ret.filterDelete, ret.filterPut:
+ panic("unexpected filter in put")
+ case ret.createdNotify:
+ panic("unexpected createdNotify in put")
+ }
+ return ret
+}
+
+func OpTxn(cmps []Cmp, thenOps []Op, elseOps []Op) Op {
+ return Op{t: tTxn, cmps: cmps, thenOps: thenOps, elseOps: elseOps}
+}
+
+func opWatch(key string, opts ...OpOption) Op {
+ ret := Op{t: tRange, key: []byte(key)}
+ ret.applyOpts(opts)
+ switch {
+ case ret.leaseID != 0:
+ panic("unexpected lease in watch")
+ case ret.limit != 0:
+ panic("unexpected limit in watch")
+ case ret.sort != nil:
+ panic("unexpected sort in watch")
+ case ret.serializable:
+ panic("unexpected serializable in watch")
+ case ret.countOnly:
+ panic("unexpected countOnly in watch")
+ case ret.minModRev != 0, ret.maxModRev != 0:
+ panic("unexpected mod revision filter in watch")
+ case ret.minCreateRev != 0, ret.maxCreateRev != 0:
+ panic("unexpected create revision filter in watch")
+ }
+ return ret
+}
+
+func (op *Op) applyOpts(opts []OpOption) {
+ for _, opt := range opts {
+ opt(op)
+ }
+}
+
+// OpOption configures Operations like Get, Put, Delete.
+type OpOption func(*Op)
+
+// WithLease attaches a lease ID to a key in 'Put' request.
+func WithLease(leaseID LeaseID) OpOption {
+ return func(op *Op) { op.leaseID = leaseID }
+}
+
+// WithLimit limits the number of results to return from 'Get' request.
+// If WithLimit is given a 0 limit, it is treated as no limit.
+func WithLimit(n int64) OpOption { return func(op *Op) { op.limit = n } }
+
+// WithRev specifies the store revision for 'Get' request.
+// Or the start revision of 'Watch' request.
+func WithRev(rev int64) OpOption { return func(op *Op) { op.rev = rev } }
+
+// WithSort specifies the ordering in 'Get' request. It requires
+// 'WithRange' and/or 'WithPrefix' to be specified too.
+// 'target' specifies the target to sort by: key, version, revisions, value.
+// 'order' can be either 'SortNone', 'SortAscend', 'SortDescend'.
+func WithSort(target SortTarget, order SortOrder) OpOption {
+ return func(op *Op) {
+ if target == SortByKey && order == SortAscend {
+ // If order != SortNone, server fetches the entire key-space,
+ // and then applies the sort and limit, if provided.
+ // Since by default the server returns results sorted by keys
+ // in lexicographically ascending order, the client should ignore
+ // SortOrder if the target is SortByKey.
+ order = SortNone
+ }
+ op.sort = &SortOption{target, order}
+ }
+}
+
+// GetPrefixRangeEnd gets the range end of the prefix.
+// 'Get(foo, WithPrefix())' is equal to 'Get(foo, WithRange(GetPrefixRangeEnd(foo))'.
+func GetPrefixRangeEnd(prefix string) string {
+ return string(getPrefix([]byte(prefix)))
+}
+
+func getPrefix(key []byte) []byte {
+ end := make([]byte, len(key))
+ copy(end, key)
+ for i := len(end) - 1; i >= 0; i-- {
+ if end[i] < 0xff {
+ end[i] = end[i] + 1
+ end = end[:i+1]
+ return end
+ }
+ }
+ // next prefix does not exist (e.g., 0xffff);
+ // default to WithFromKey policy
+ return noPrefixEnd
+}
+
+// WithPrefix enables 'Get', 'Delete', or 'Watch' requests to operate
+// on the keys with matching prefix. For example, 'Get(foo, WithPrefix())'
+// can return 'foo1', 'foo2', and so on.
+func WithPrefix() OpOption {
+ return func(op *Op) {
+ if len(op.key) == 0 {
+ op.key, op.end = []byte{0}, []byte{0}
+ return
+ }
+ op.end = getPrefix(op.key)
+ }
+}
+
+// WithRange specifies the range of 'Get', 'Delete', 'Watch' requests.
+// For example, 'Get' requests with 'WithRange(end)' returns
+// the keys in the range [key, end).
+// endKey must be lexicographically greater than start key.
+func WithRange(endKey string) OpOption {
+ return func(op *Op) { op.end = []byte(endKey) }
+}
+
+// WithFromKey specifies the range of 'Get', 'Delete', 'Watch' requests
+// to be equal or greater than the key in the argument.
+func WithFromKey() OpOption { return WithRange("\x00") }
+
+// WithSerializable makes 'Get' request serializable. By default,
+// it's linearizable. Serializable requests are better for lower latency
+// requirement.
+func WithSerializable() OpOption {
+ return func(op *Op) { op.serializable = true }
+}
+
+// WithKeysOnly makes the 'Get' request return only the keys and the corresponding
+// values will be omitted.
+func WithKeysOnly() OpOption {
+ return func(op *Op) { op.keysOnly = true }
+}
+
+// WithCountOnly makes the 'Get' request return only the count of keys.
+func WithCountOnly() OpOption {
+ return func(op *Op) { op.countOnly = true }
+}
+
+// WithMinModRev filters out keys for Get with modification revisions less than the given revision.
+func WithMinModRev(rev int64) OpOption { return func(op *Op) { op.minModRev = rev } }
+
+// WithMaxModRev filters out keys for Get with modification revisions greater than the given revision.
+func WithMaxModRev(rev int64) OpOption { return func(op *Op) { op.maxModRev = rev } }
+
+// WithMinCreateRev filters out keys for Get with creation revisions less than the given revision.
+func WithMinCreateRev(rev int64) OpOption { return func(op *Op) { op.minCreateRev = rev } }
+
+// WithMaxCreateRev filters out keys for Get with creation revisions greater than the given revision.
+func WithMaxCreateRev(rev int64) OpOption { return func(op *Op) { op.maxCreateRev = rev } }
+
+// WithFirstCreate gets the key with the oldest creation revision in the request range.
+func WithFirstCreate() []OpOption { return withTop(SortByCreateRevision, SortAscend) }
+
+// WithLastCreate gets the key with the latest creation revision in the request range.
+func WithLastCreate() []OpOption { return withTop(SortByCreateRevision, SortDescend) }
+
+// WithFirstKey gets the lexically first key in the request range.
+func WithFirstKey() []OpOption { return withTop(SortByKey, SortAscend) }
+
+// WithLastKey gets the lexically last key in the request range.
+func WithLastKey() []OpOption { return withTop(SortByKey, SortDescend) }
+
+// WithFirstRev gets the key with the oldest modification revision in the request range.
+func WithFirstRev() []OpOption { return withTop(SortByModRevision, SortAscend) }
+
+// WithLastRev gets the key with the latest modification revision in the request range.
+func WithLastRev() []OpOption { return withTop(SortByModRevision, SortDescend) }
+
+// withTop gets the first key over the get's prefix given a sort order
+func withTop(target SortTarget, order SortOrder) []OpOption {
+ return []OpOption{WithPrefix(), WithSort(target, order), WithLimit(1)}
+}
+
+// WithProgressNotify makes watch server send periodic progress updates
+// every 10 minutes when there is no incoming events.
+// Progress updates have zero events in WatchResponse.
+func WithProgressNotify() OpOption {
+ return func(op *Op) {
+ op.progressNotify = true
+ }
+}
+
+// WithCreatedNotify makes watch server sends the created event.
+func WithCreatedNotify() OpOption {
+ return func(op *Op) {
+ op.createdNotify = true
+ }
+}
+
+// WithFilterPut discards PUT events from the watcher.
+func WithFilterPut() OpOption {
+ return func(op *Op) { op.filterPut = true }
+}
+
+// WithFilterDelete discards DELETE events from the watcher.
+func WithFilterDelete() OpOption {
+ return func(op *Op) { op.filterDelete = true }
+}
+
+// WithPrevKV gets the previous key-value pair before the event happens. If the previous KV is already compacted,
+// nothing will be returned.
+func WithPrevKV() OpOption {
+ return func(op *Op) {
+ op.prevKV = true
+ }
+}
+
+// WithIgnoreValue updates the key using its current value.
+// This option can not be combined with non-empty values.
+// Returns an error if the key does not exist.
+func WithIgnoreValue() OpOption {
+ return func(op *Op) {
+ op.ignoreValue = true
+ }
+}
+
+// WithIgnoreLease updates the key using its current lease.
+// This option can not be combined with WithLease.
+// Returns an error if the key does not exist.
+func WithIgnoreLease() OpOption {
+ return func(op *Op) {
+ op.ignoreLease = true
+ }
+}
+
+// LeaseOp represents an Operation that lease can execute.
+type LeaseOp struct {
+ id LeaseID
+
+ // for TimeToLive
+ attachedKeys bool
+}
+
+// LeaseOption configures lease operations.
+type LeaseOption func(*LeaseOp)
+
+func (op *LeaseOp) applyOpts(opts []LeaseOption) {
+ for _, opt := range opts {
+ opt(op)
+ }
+}
+
+// WithAttachedKeys makes TimeToLive list the keys attached to the given lease ID.
+func WithAttachedKeys() LeaseOption {
+ return func(op *LeaseOp) { op.attachedKeys = true }
+}
+
+func toLeaseTimeToLiveRequest(id LeaseID, opts ...LeaseOption) *pb.LeaseTimeToLiveRequest {
+ ret := &LeaseOp{id: id}
+ ret.applyOpts(opts)
+ return &pb.LeaseTimeToLiveRequest{ID: int64(id), Keys: ret.attachedKeys}
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/options.go b/vendor/github.com/coreos/etcd/clientv3/options.go
new file mode 100644
index 00000000..fa25811f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/options.go
@@ -0,0 +1,49 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "math"
+
+ "google.golang.org/grpc"
+)
+
+var (
+ // Disable gRPC internal retrial logic
+ // TODO: enable when gRPC retry is stable (FailFast=false)
+ // Reference:
+ // - https://github.com/grpc/grpc-go/issues/1532
+ // - https://github.com/grpc/proposal/blob/master/A6-client-retries.md
+ defaultFailFast = grpc.FailFast(true)
+
+ // client-side request send limit, gRPC default is math.MaxInt32
+ // Make sure that "client-side send limit < server-side default send/recv limit"
+ // Same value as "embed.DefaultMaxRequestBytes" plus gRPC overhead bytes
+ defaultMaxCallSendMsgSize = grpc.MaxCallSendMsgSize(2 * 1024 * 1024)
+
+ // client-side response receive limit, gRPC default is 4MB
+ // Make sure that "client-side receive limit >= server-side default send/recv limit"
+ // because range response can easily exceed request send limits
+ // Default to math.MaxInt32; writes exceeding server-side send limit fails anyway
+ defaultMaxCallRecvMsgSize = grpc.MaxCallRecvMsgSize(math.MaxInt32)
+)
+
+// defaultCallOpts defines a list of default "gRPC.CallOption".
+// Some options are exposed to "clientv3.Config".
+// Defaults will be overridden by the settings in "clientv3.Config".
+var defaultCallOpts = []grpc.CallOption{defaultFailFast, defaultMaxCallSendMsgSize, defaultMaxCallRecvMsgSize}
+
+// MaxLeaseTTL is the maximum lease TTL value
+const MaxLeaseTTL = 9000000000
diff --git a/vendor/github.com/coreos/etcd/clientv3/ready_wait.go b/vendor/github.com/coreos/etcd/clientv3/ready_wait.go
new file mode 100644
index 00000000..c6ef585b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/ready_wait.go
@@ -0,0 +1,30 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import "context"
+
+// TODO: remove this when "FailFast=false" is fixed.
+// See https://github.com/grpc/grpc-go/issues/1532.
+func readyWait(rpcCtx, clientCtx context.Context, ready <-chan struct{}) error {
+ select {
+ case <-ready:
+ return nil
+ case <-rpcCtx.Done():
+ return rpcCtx.Err()
+ case <-clientCtx.Done():
+ return clientCtx.Err()
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/retry.go b/vendor/github.com/coreos/etcd/clientv3/retry.go
new file mode 100644
index 00000000..7f89ba64
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/retry.go
@@ -0,0 +1,496 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+
+ "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+type retryPolicy uint8
+
+const (
+ repeatable retryPolicy = iota
+ nonRepeatable
+)
+
+type rpcFunc func(ctx context.Context) error
+type retryRPCFunc func(context.Context, rpcFunc, retryPolicy) error
+type retryStopErrFunc func(error) bool
+
+// immutable requests (e.g. Get) should be retried unless it's
+// an obvious server-side error (e.g. rpctypes.ErrRequestTooLarge).
+//
+// "isRepeatableStopError" returns "true" when an immutable request
+// is interrupted by server-side or gRPC-side error and its status
+// code is not transient (!= codes.Unavailable).
+//
+// Returning "true" means retry should stop, since client cannot
+// handle itself even with retries.
+func isRepeatableStopError(err error) bool {
+ eErr := rpctypes.Error(err)
+ // always stop retry on etcd errors
+ if serverErr, ok := eErr.(rpctypes.EtcdError); ok && serverErr.Code() != codes.Unavailable {
+ return true
+ }
+ // only retry if unavailable
+ ev, _ := status.FromError(err)
+ return ev.Code() != codes.Unavailable
+}
+
+// mutable requests (e.g. Put, Delete, Txn) should only be retried
+// when the status code is codes.Unavailable when initial connection
+// has not been established (no pinned endpoint).
+//
+// "isNonRepeatableStopError" returns "true" when a mutable request
+// is interrupted by non-transient error that client cannot handle itself,
+// or transient error while the connection has already been established
+// (pinned endpoint exists).
+//
+// Returning "true" means retry should stop, otherwise it violates
+// write-at-most-once semantics.
+func isNonRepeatableStopError(err error) bool {
+ ev, _ := status.FromError(err)
+ if ev.Code() != codes.Unavailable {
+ return true
+ }
+ desc := rpctypes.ErrorDesc(err)
+ return desc != "there is no address available" && desc != "there is no connection available"
+}
+
+func (c *Client) newRetryWrapper() retryRPCFunc {
+ return func(rpcCtx context.Context, f rpcFunc, rp retryPolicy) error {
+ var isStop retryStopErrFunc
+ switch rp {
+ case repeatable:
+ isStop = isRepeatableStopError
+ case nonRepeatable:
+ isStop = isNonRepeatableStopError
+ }
+ for {
+ if err := readyWait(rpcCtx, c.ctx, c.balancer.ConnectNotify()); err != nil {
+ return err
+ }
+ pinned := c.balancer.pinned()
+ err := f(rpcCtx)
+ if err == nil {
+ return nil
+ }
+ logger.Lvl(4).Infof("clientv3/retry: error %q on pinned endpoint %q", err.Error(), pinned)
+
+ if s, ok := status.FromError(err); ok && (s.Code() == codes.Unavailable || s.Code() == codes.DeadlineExceeded || s.Code() == codes.Internal) {
+ // mark this before endpoint switch is triggered
+ c.balancer.hostPortError(pinned, err)
+ c.balancer.next()
+ logger.Lvl(4).Infof("clientv3/retry: switching from %q due to error %q", pinned, err.Error())
+ }
+
+ if isStop(err) {
+ return err
+ }
+ }
+ }
+}
+
+func (c *Client) newAuthRetryWrapper(retryf retryRPCFunc) retryRPCFunc {
+ return func(rpcCtx context.Context, f rpcFunc, rp retryPolicy) error {
+ for {
+ pinned := c.balancer.pinned()
+ err := retryf(rpcCtx, f, rp)
+ if err == nil {
+ return nil
+ }
+ logger.Lvl(4).Infof("clientv3/auth-retry: error %q on pinned endpoint %q", err.Error(), pinned)
+ // always stop retry on etcd errors other than invalid auth token
+ if rpctypes.Error(err) == rpctypes.ErrInvalidAuthToken {
+ gterr := c.getToken(rpcCtx)
+ if gterr != nil {
+ logger.Lvl(4).Infof("clientv3/auth-retry: cannot retry due to error %q(%q) on pinned endpoint %q", err.Error(), gterr.Error(), pinned)
+ return err // return the original error for simplicity
+ }
+ continue
+ }
+ return err
+ }
+ }
+}
+
+type retryKVClient struct {
+ kc pb.KVClient
+ retryf retryRPCFunc
+}
+
+// RetryKVClient implements a KVClient.
+func RetryKVClient(c *Client) pb.KVClient {
+ return &retryKVClient{
+ kc: pb.NewKVClient(c.conn),
+ retryf: c.newAuthRetryWrapper(c.newRetryWrapper()),
+ }
+}
+func (rkv *retryKVClient) Range(ctx context.Context, in *pb.RangeRequest, opts ...grpc.CallOption) (resp *pb.RangeResponse, err error) {
+ err = rkv.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rkv.kc.Range(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rkv *retryKVClient) Put(ctx context.Context, in *pb.PutRequest, opts ...grpc.CallOption) (resp *pb.PutResponse, err error) {
+ err = rkv.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rkv.kc.Put(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rkv *retryKVClient) DeleteRange(ctx context.Context, in *pb.DeleteRangeRequest, opts ...grpc.CallOption) (resp *pb.DeleteRangeResponse, err error) {
+ err = rkv.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rkv.kc.DeleteRange(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rkv *retryKVClient) Txn(ctx context.Context, in *pb.TxnRequest, opts ...grpc.CallOption) (resp *pb.TxnResponse, err error) {
+ // TODO: "repeatable" for read-only txn
+ err = rkv.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rkv.kc.Txn(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rkv *retryKVClient) Compact(ctx context.Context, in *pb.CompactionRequest, opts ...grpc.CallOption) (resp *pb.CompactionResponse, err error) {
+ err = rkv.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rkv.kc.Compact(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+type retryLeaseClient struct {
+ lc pb.LeaseClient
+ retryf retryRPCFunc
+}
+
+// RetryLeaseClient implements a LeaseClient.
+func RetryLeaseClient(c *Client) pb.LeaseClient {
+ return &retryLeaseClient{
+ lc: pb.NewLeaseClient(c.conn),
+ retryf: c.newAuthRetryWrapper(c.newRetryWrapper()),
+ }
+}
+
+func (rlc *retryLeaseClient) LeaseTimeToLive(ctx context.Context, in *pb.LeaseTimeToLiveRequest, opts ...grpc.CallOption) (resp *pb.LeaseTimeToLiveResponse, err error) {
+ err = rlc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rlc.lc.LeaseTimeToLive(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rlc *retryLeaseClient) LeaseLeases(ctx context.Context, in *pb.LeaseLeasesRequest, opts ...grpc.CallOption) (resp *pb.LeaseLeasesResponse, err error) {
+ err = rlc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rlc.lc.LeaseLeases(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rlc *retryLeaseClient) LeaseGrant(ctx context.Context, in *pb.LeaseGrantRequest, opts ...grpc.CallOption) (resp *pb.LeaseGrantResponse, err error) {
+ err = rlc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rlc.lc.LeaseGrant(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+
+}
+
+func (rlc *retryLeaseClient) LeaseRevoke(ctx context.Context, in *pb.LeaseRevokeRequest, opts ...grpc.CallOption) (resp *pb.LeaseRevokeResponse, err error) {
+ err = rlc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rlc.lc.LeaseRevoke(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rlc *retryLeaseClient) LeaseKeepAlive(ctx context.Context, opts ...grpc.CallOption) (stream pb.Lease_LeaseKeepAliveClient, err error) {
+ err = rlc.retryf(ctx, func(rctx context.Context) error {
+ stream, err = rlc.lc.LeaseKeepAlive(rctx, opts...)
+ return err
+ }, repeatable)
+ return stream, err
+}
+
+type retryClusterClient struct {
+ cc pb.ClusterClient
+ retryf retryRPCFunc
+}
+
+// RetryClusterClient implements a ClusterClient.
+func RetryClusterClient(c *Client) pb.ClusterClient {
+ return &retryClusterClient{
+ cc: pb.NewClusterClient(c.conn),
+ retryf: c.newRetryWrapper(),
+ }
+}
+
+func (rcc *retryClusterClient) MemberList(ctx context.Context, in *pb.MemberListRequest, opts ...grpc.CallOption) (resp *pb.MemberListResponse, err error) {
+ err = rcc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rcc.cc.MemberList(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rcc *retryClusterClient) MemberAdd(ctx context.Context, in *pb.MemberAddRequest, opts ...grpc.CallOption) (resp *pb.MemberAddResponse, err error) {
+ err = rcc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rcc.cc.MemberAdd(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rcc *retryClusterClient) MemberRemove(ctx context.Context, in *pb.MemberRemoveRequest, opts ...grpc.CallOption) (resp *pb.MemberRemoveResponse, err error) {
+ err = rcc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rcc.cc.MemberRemove(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rcc *retryClusterClient) MemberUpdate(ctx context.Context, in *pb.MemberUpdateRequest, opts ...grpc.CallOption) (resp *pb.MemberUpdateResponse, err error) {
+ err = rcc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rcc.cc.MemberUpdate(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+type retryMaintenanceClient struct {
+ mc pb.MaintenanceClient
+ retryf retryRPCFunc
+}
+
+// RetryMaintenanceClient implements a Maintenance.
+func RetryMaintenanceClient(c *Client, conn *grpc.ClientConn) pb.MaintenanceClient {
+ return &retryMaintenanceClient{
+ mc: pb.NewMaintenanceClient(conn),
+ retryf: c.newRetryWrapper(),
+ }
+}
+
+func (rmc *retryMaintenanceClient) Alarm(ctx context.Context, in *pb.AlarmRequest, opts ...grpc.CallOption) (resp *pb.AlarmResponse, err error) {
+ err = rmc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rmc.mc.Alarm(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rmc *retryMaintenanceClient) Status(ctx context.Context, in *pb.StatusRequest, opts ...grpc.CallOption) (resp *pb.StatusResponse, err error) {
+ err = rmc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rmc.mc.Status(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rmc *retryMaintenanceClient) Hash(ctx context.Context, in *pb.HashRequest, opts ...grpc.CallOption) (resp *pb.HashResponse, err error) {
+ err = rmc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rmc.mc.Hash(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rmc *retryMaintenanceClient) HashKV(ctx context.Context, in *pb.HashKVRequest, opts ...grpc.CallOption) (resp *pb.HashKVResponse, err error) {
+ err = rmc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rmc.mc.HashKV(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rmc *retryMaintenanceClient) Snapshot(ctx context.Context, in *pb.SnapshotRequest, opts ...grpc.CallOption) (stream pb.Maintenance_SnapshotClient, err error) {
+ err = rmc.retryf(ctx, func(rctx context.Context) error {
+ stream, err = rmc.mc.Snapshot(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return stream, err
+}
+
+func (rmc *retryMaintenanceClient) MoveLeader(ctx context.Context, in *pb.MoveLeaderRequest, opts ...grpc.CallOption) (resp *pb.MoveLeaderResponse, err error) {
+ err = rmc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rmc.mc.MoveLeader(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rmc *retryMaintenanceClient) Defragment(ctx context.Context, in *pb.DefragmentRequest, opts ...grpc.CallOption) (resp *pb.DefragmentResponse, err error) {
+ err = rmc.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rmc.mc.Defragment(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+type retryAuthClient struct {
+ ac pb.AuthClient
+ retryf retryRPCFunc
+}
+
+// RetryAuthClient implements a AuthClient.
+func RetryAuthClient(c *Client) pb.AuthClient {
+ return &retryAuthClient{
+ ac: pb.NewAuthClient(c.conn),
+ retryf: c.newRetryWrapper(),
+ }
+}
+
+func (rac *retryAuthClient) UserList(ctx context.Context, in *pb.AuthUserListRequest, opts ...grpc.CallOption) (resp *pb.AuthUserListResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.UserList(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) UserGet(ctx context.Context, in *pb.AuthUserGetRequest, opts ...grpc.CallOption) (resp *pb.AuthUserGetResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.UserGet(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) RoleGet(ctx context.Context, in *pb.AuthRoleGetRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleGetResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.RoleGet(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) RoleList(ctx context.Context, in *pb.AuthRoleListRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleListResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.RoleList(rctx, in, opts...)
+ return err
+ }, repeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) AuthEnable(ctx context.Context, in *pb.AuthEnableRequest, opts ...grpc.CallOption) (resp *pb.AuthEnableResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.AuthEnable(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) AuthDisable(ctx context.Context, in *pb.AuthDisableRequest, opts ...grpc.CallOption) (resp *pb.AuthDisableResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.AuthDisable(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) UserAdd(ctx context.Context, in *pb.AuthUserAddRequest, opts ...grpc.CallOption) (resp *pb.AuthUserAddResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.UserAdd(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) UserDelete(ctx context.Context, in *pb.AuthUserDeleteRequest, opts ...grpc.CallOption) (resp *pb.AuthUserDeleteResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.UserDelete(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) UserChangePassword(ctx context.Context, in *pb.AuthUserChangePasswordRequest, opts ...grpc.CallOption) (resp *pb.AuthUserChangePasswordResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.UserChangePassword(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) UserGrantRole(ctx context.Context, in *pb.AuthUserGrantRoleRequest, opts ...grpc.CallOption) (resp *pb.AuthUserGrantRoleResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.UserGrantRole(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) UserRevokeRole(ctx context.Context, in *pb.AuthUserRevokeRoleRequest, opts ...grpc.CallOption) (resp *pb.AuthUserRevokeRoleResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.UserRevokeRole(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) RoleAdd(ctx context.Context, in *pb.AuthRoleAddRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleAddResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.RoleAdd(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) RoleDelete(ctx context.Context, in *pb.AuthRoleDeleteRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleDeleteResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.RoleDelete(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) RoleGrantPermission(ctx context.Context, in *pb.AuthRoleGrantPermissionRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleGrantPermissionResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.RoleGrantPermission(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) RoleRevokePermission(ctx context.Context, in *pb.AuthRoleRevokePermissionRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleRevokePermissionResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.RoleRevokePermission(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
+
+func (rac *retryAuthClient) Authenticate(ctx context.Context, in *pb.AuthenticateRequest, opts ...grpc.CallOption) (resp *pb.AuthenticateResponse, err error) {
+ err = rac.retryf(ctx, func(rctx context.Context) error {
+ resp, err = rac.ac.Authenticate(rctx, in, opts...)
+ return err
+ }, nonRepeatable)
+ return resp, err
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/sort.go b/vendor/github.com/coreos/etcd/clientv3/sort.go
new file mode 100644
index 00000000..2bb9d9a1
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/sort.go
@@ -0,0 +1,37 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+type SortTarget int
+type SortOrder int
+
+const (
+ SortNone SortOrder = iota
+ SortAscend
+ SortDescend
+)
+
+const (
+ SortByKey SortTarget = iota
+ SortByVersion
+ SortByCreateRevision
+ SortByModRevision
+ SortByValue
+)
+
+type SortOption struct {
+ Target SortTarget
+ Order SortOrder
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/txn.go b/vendor/github.com/coreos/etcd/clientv3/txn.go
new file mode 100644
index 00000000..c3c2d248
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/txn.go
@@ -0,0 +1,151 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "sync"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ "google.golang.org/grpc"
+)
+
+// Txn is the interface that wraps mini-transactions.
+//
+// Txn(context.TODO()).If(
+// Compare(Value(k1), ">", v1),
+// Compare(Version(k1), "=", 2)
+// ).Then(
+// OpPut(k2,v2), OpPut(k3,v3)
+// ).Else(
+// OpPut(k4,v4), OpPut(k5,v5)
+// ).Commit()
+//
+type Txn interface {
+ // If takes a list of comparison. If all comparisons passed in succeed,
+ // the operations passed into Then() will be executed. Or the operations
+ // passed into Else() will be executed.
+ If(cs ...Cmp) Txn
+
+ // Then takes a list of operations. The Ops list will be executed, if the
+ // comparisons passed in If() succeed.
+ Then(ops ...Op) Txn
+
+ // Else takes a list of operations. The Ops list will be executed, if the
+ // comparisons passed in If() fail.
+ Else(ops ...Op) Txn
+
+ // Commit tries to commit the transaction.
+ Commit() (*TxnResponse, error)
+}
+
+type txn struct {
+ kv *kv
+ ctx context.Context
+
+ mu sync.Mutex
+ cif bool
+ cthen bool
+ celse bool
+
+ isWrite bool
+
+ cmps []*pb.Compare
+
+ sus []*pb.RequestOp
+ fas []*pb.RequestOp
+
+ callOpts []grpc.CallOption
+}
+
+func (txn *txn) If(cs ...Cmp) Txn {
+ txn.mu.Lock()
+ defer txn.mu.Unlock()
+
+ if txn.cif {
+ panic("cannot call If twice!")
+ }
+
+ if txn.cthen {
+ panic("cannot call If after Then!")
+ }
+
+ if txn.celse {
+ panic("cannot call If after Else!")
+ }
+
+ txn.cif = true
+
+ for i := range cs {
+ txn.cmps = append(txn.cmps, (*pb.Compare)(&cs[i]))
+ }
+
+ return txn
+}
+
+func (txn *txn) Then(ops ...Op) Txn {
+ txn.mu.Lock()
+ defer txn.mu.Unlock()
+
+ if txn.cthen {
+ panic("cannot call Then twice!")
+ }
+ if txn.celse {
+ panic("cannot call Then after Else!")
+ }
+
+ txn.cthen = true
+
+ for _, op := range ops {
+ txn.isWrite = txn.isWrite || op.isWrite()
+ txn.sus = append(txn.sus, op.toRequestOp())
+ }
+
+ return txn
+}
+
+func (txn *txn) Else(ops ...Op) Txn {
+ txn.mu.Lock()
+ defer txn.mu.Unlock()
+
+ if txn.celse {
+ panic("cannot call Else twice!")
+ }
+
+ txn.celse = true
+
+ for _, op := range ops {
+ txn.isWrite = txn.isWrite || op.isWrite()
+ txn.fas = append(txn.fas, op.toRequestOp())
+ }
+
+ return txn
+}
+
+func (txn *txn) Commit() (*TxnResponse, error) {
+ txn.mu.Lock()
+ defer txn.mu.Unlock()
+
+ r := &pb.TxnRequest{Compare: txn.cmps, Success: txn.sus, Failure: txn.fas}
+
+ var resp *pb.TxnResponse
+ var err error
+ resp, err = txn.kv.remote.Txn(txn.ctx, r, txn.callOpts...)
+ if err != nil {
+ return nil, toErr(txn.ctx, err)
+ }
+ return (*TxnResponse)(resp), nil
+}
diff --git a/vendor/github.com/coreos/etcd/clientv3/watch.go b/vendor/github.com/coreos/etcd/clientv3/watch.go
new file mode 100644
index 00000000..d7633850
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/clientv3/watch.go
@@ -0,0 +1,828 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package clientv3
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "time"
+
+ v3rpc "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ mvccpb "github.com/coreos/etcd/mvcc/mvccpb"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+const (
+ EventTypeDelete = mvccpb.DELETE
+ EventTypePut = mvccpb.PUT
+
+ closeSendErrTimeout = 250 * time.Millisecond
+)
+
+type Event mvccpb.Event
+
+type WatchChan <-chan WatchResponse
+
+type Watcher interface {
+ // Watch watches on a key or prefix. The watched events will be returned
+ // through the returned channel. If revisions waiting to be sent over the
+ // watch are compacted, then the watch will be canceled by the server, the
+ // client will post a compacted error watch response, and the channel will close.
+ Watch(ctx context.Context, key string, opts ...OpOption) WatchChan
+
+ // Close closes the watcher and cancels all watch requests.
+ Close() error
+}
+
+type WatchResponse struct {
+ Header pb.ResponseHeader
+ Events []*Event
+
+ // CompactRevision is the minimum revision the watcher may receive.
+ CompactRevision int64
+
+ // Canceled is used to indicate watch failure.
+ // If the watch failed and the stream was about to close, before the channel is closed,
+ // the channel sends a final response that has Canceled set to true with a non-nil Err().
+ Canceled bool
+
+ // Created is used to indicate the creation of the watcher.
+ Created bool
+
+ closeErr error
+
+ // cancelReason is a reason of canceling watch
+ cancelReason string
+}
+
+// IsCreate returns true if the event tells that the key is newly created.
+func (e *Event) IsCreate() bool {
+ return e.Type == EventTypePut && e.Kv.CreateRevision == e.Kv.ModRevision
+}
+
+// IsModify returns true if the event tells that a new value is put on existing key.
+func (e *Event) IsModify() bool {
+ return e.Type == EventTypePut && e.Kv.CreateRevision != e.Kv.ModRevision
+}
+
+// Err is the error value if this WatchResponse holds an error.
+func (wr *WatchResponse) Err() error {
+ switch {
+ case wr.closeErr != nil:
+ return v3rpc.Error(wr.closeErr)
+ case wr.CompactRevision != 0:
+ return v3rpc.ErrCompacted
+ case wr.Canceled:
+ if len(wr.cancelReason) != 0 {
+ return v3rpc.Error(status.Error(codes.FailedPrecondition, wr.cancelReason))
+ }
+ return v3rpc.ErrFutureRev
+ }
+ return nil
+}
+
+// IsProgressNotify returns true if the WatchResponse is progress notification.
+func (wr *WatchResponse) IsProgressNotify() bool {
+ return len(wr.Events) == 0 && !wr.Canceled && !wr.Created && wr.CompactRevision == 0 && wr.Header.Revision != 0
+}
+
+// watcher implements the Watcher interface
+type watcher struct {
+ remote pb.WatchClient
+ callOpts []grpc.CallOption
+
+ // mu protects the grpc streams map
+ mu sync.RWMutex
+
+ // streams holds all the active grpc streams keyed by ctx value.
+ streams map[string]*watchGrpcStream
+}
+
+// watchGrpcStream tracks all watch resources attached to a single grpc stream.
+type watchGrpcStream struct {
+ owner *watcher
+ remote pb.WatchClient
+ callOpts []grpc.CallOption
+
+ // ctx controls internal remote.Watch requests
+ ctx context.Context
+ // ctxKey is the key used when looking up this stream's context
+ ctxKey string
+ cancel context.CancelFunc
+
+ // substreams holds all active watchers on this grpc stream
+ substreams map[int64]*watcherStream
+ // resuming holds all resuming watchers on this grpc stream
+ resuming []*watcherStream
+
+ // reqc sends a watch request from Watch() to the main goroutine
+ reqc chan *watchRequest
+ // respc receives data from the watch client
+ respc chan *pb.WatchResponse
+ // donec closes to broadcast shutdown
+ donec chan struct{}
+ // errc transmits errors from grpc Recv to the watch stream reconnect logic
+ errc chan error
+ // closingc gets the watcherStream of closing watchers
+ closingc chan *watcherStream
+ // wg is Done when all substream goroutines have exited
+ wg sync.WaitGroup
+
+ // resumec closes to signal that all substreams should begin resuming
+ resumec chan struct{}
+ // closeErr is the error that closed the watch stream
+ closeErr error
+}
+
+// watchRequest is issued by the subscriber to start a new watcher
+type watchRequest struct {
+ ctx context.Context
+ key string
+ end string
+ rev int64
+ // send created notification event if this field is true
+ createdNotify bool
+ // progressNotify is for progress updates
+ progressNotify bool
+ // filters is the list of events to filter out
+ filters []pb.WatchCreateRequest_FilterType
+ // get the previous key-value pair before the event happens
+ prevKV bool
+ // retc receives a chan WatchResponse once the watcher is established
+ retc chan chan WatchResponse
+}
+
+// watcherStream represents a registered watcher
+type watcherStream struct {
+ // initReq is the request that initiated this request
+ initReq watchRequest
+
+ // outc publishes watch responses to subscriber
+ outc chan WatchResponse
+ // recvc buffers watch responses before publishing
+ recvc chan *WatchResponse
+ // donec closes when the watcherStream goroutine stops.
+ donec chan struct{}
+ // closing is set to true when stream should be scheduled to shutdown.
+ closing bool
+ // id is the registered watch id on the grpc stream
+ id int64
+
+ // buf holds all events received from etcd but not yet consumed by the client
+ buf []*WatchResponse
+}
+
+func NewWatcher(c *Client) Watcher {
+ return NewWatchFromWatchClient(pb.NewWatchClient(c.conn), c)
+}
+
+func NewWatchFromWatchClient(wc pb.WatchClient, c *Client) Watcher {
+ w := &watcher{
+ remote: wc,
+ streams: make(map[string]*watchGrpcStream),
+ }
+ if c != nil {
+ w.callOpts = c.callOpts
+ }
+ return w
+}
+
+// never closes
+var valCtxCh = make(chan struct{})
+var zeroTime = time.Unix(0, 0)
+
+// ctx with only the values; never Done
+type valCtx struct{ context.Context }
+
+func (vc *valCtx) Deadline() (time.Time, bool) { return zeroTime, false }
+func (vc *valCtx) Done() <-chan struct{} { return valCtxCh }
+func (vc *valCtx) Err() error { return nil }
+
+func (w *watcher) newWatcherGrpcStream(inctx context.Context) *watchGrpcStream {
+ ctx, cancel := context.WithCancel(&valCtx{inctx})
+ wgs := &watchGrpcStream{
+ owner: w,
+ remote: w.remote,
+ callOpts: w.callOpts,
+ ctx: ctx,
+ ctxKey: streamKeyFromCtx(inctx),
+ cancel: cancel,
+ substreams: make(map[int64]*watcherStream),
+ respc: make(chan *pb.WatchResponse),
+ reqc: make(chan *watchRequest),
+ donec: make(chan struct{}),
+ errc: make(chan error, 1),
+ closingc: make(chan *watcherStream),
+ resumec: make(chan struct{}),
+ }
+ go wgs.run()
+ return wgs
+}
+
+// Watch posts a watch request to run() and waits for a new watcher channel
+func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) WatchChan {
+ ow := opWatch(key, opts...)
+
+ var filters []pb.WatchCreateRequest_FilterType
+ if ow.filterPut {
+ filters = append(filters, pb.WatchCreateRequest_NOPUT)
+ }
+ if ow.filterDelete {
+ filters = append(filters, pb.WatchCreateRequest_NODELETE)
+ }
+
+ wr := &watchRequest{
+ ctx: ctx,
+ createdNotify: ow.createdNotify,
+ key: string(ow.key),
+ end: string(ow.end),
+ rev: ow.rev,
+ progressNotify: ow.progressNotify,
+ filters: filters,
+ prevKV: ow.prevKV,
+ retc: make(chan chan WatchResponse, 1),
+ }
+
+ ok := false
+ ctxKey := streamKeyFromCtx(ctx)
+
+ // find or allocate appropriate grpc watch stream
+ w.mu.Lock()
+ if w.streams == nil {
+ // closed
+ w.mu.Unlock()
+ ch := make(chan WatchResponse)
+ close(ch)
+ return ch
+ }
+ wgs := w.streams[ctxKey]
+ if wgs == nil {
+ wgs = w.newWatcherGrpcStream(ctx)
+ w.streams[ctxKey] = wgs
+ }
+ donec := wgs.donec
+ reqc := wgs.reqc
+ w.mu.Unlock()
+
+ // couldn't create channel; return closed channel
+ closeCh := make(chan WatchResponse, 1)
+
+ // submit request
+ select {
+ case reqc <- wr:
+ ok = true
+ case <-wr.ctx.Done():
+ case <-donec:
+ if wgs.closeErr != nil {
+ closeCh <- WatchResponse{closeErr: wgs.closeErr}
+ break
+ }
+ // retry; may have dropped stream from no ctxs
+ return w.Watch(ctx, key, opts...)
+ }
+
+ // receive channel
+ if ok {
+ select {
+ case ret := <-wr.retc:
+ return ret
+ case <-ctx.Done():
+ case <-donec:
+ if wgs.closeErr != nil {
+ closeCh <- WatchResponse{closeErr: wgs.closeErr}
+ break
+ }
+ // retry; may have dropped stream from no ctxs
+ return w.Watch(ctx, key, opts...)
+ }
+ }
+
+ close(closeCh)
+ return closeCh
+}
+
+func (w *watcher) Close() (err error) {
+ w.mu.Lock()
+ streams := w.streams
+ w.streams = nil
+ w.mu.Unlock()
+ for _, wgs := range streams {
+ if werr := wgs.close(); werr != nil {
+ err = werr
+ }
+ }
+ return err
+}
+
+func (w *watchGrpcStream) close() (err error) {
+ w.cancel()
+ <-w.donec
+ select {
+ case err = <-w.errc:
+ default:
+ }
+ return toErr(w.ctx, err)
+}
+
+func (w *watcher) closeStream(wgs *watchGrpcStream) {
+ w.mu.Lock()
+ close(wgs.donec)
+ wgs.cancel()
+ if w.streams != nil {
+ delete(w.streams, wgs.ctxKey)
+ }
+ w.mu.Unlock()
+}
+
+func (w *watchGrpcStream) addSubstream(resp *pb.WatchResponse, ws *watcherStream) {
+ if resp.WatchId == -1 {
+ // failed; no channel
+ close(ws.recvc)
+ return
+ }
+ ws.id = resp.WatchId
+ w.substreams[ws.id] = ws
+}
+
+func (w *watchGrpcStream) sendCloseSubstream(ws *watcherStream, resp *WatchResponse) {
+ select {
+ case ws.outc <- *resp:
+ case <-ws.initReq.ctx.Done():
+ case <-time.After(closeSendErrTimeout):
+ }
+ close(ws.outc)
+}
+
+func (w *watchGrpcStream) closeSubstream(ws *watcherStream) {
+ // send channel response in case stream was never established
+ select {
+ case ws.initReq.retc <- ws.outc:
+ default:
+ }
+ // close subscriber's channel
+ if closeErr := w.closeErr; closeErr != nil && ws.initReq.ctx.Err() == nil {
+ go w.sendCloseSubstream(ws, &WatchResponse{closeErr: w.closeErr})
+ } else if ws.outc != nil {
+ close(ws.outc)
+ }
+ if ws.id != -1 {
+ delete(w.substreams, ws.id)
+ return
+ }
+ for i := range w.resuming {
+ if w.resuming[i] == ws {
+ w.resuming[i] = nil
+ return
+ }
+ }
+}
+
+// run is the root of the goroutines for managing a watcher client
+func (w *watchGrpcStream) run() {
+ var wc pb.Watch_WatchClient
+ var closeErr error
+
+ // substreams marked to close but goroutine still running; needed for
+ // avoiding double-closing recvc on grpc stream teardown
+ closing := make(map[*watcherStream]struct{})
+
+ defer func() {
+ w.closeErr = closeErr
+ // shutdown substreams and resuming substreams
+ for _, ws := range w.substreams {
+ if _, ok := closing[ws]; !ok {
+ close(ws.recvc)
+ closing[ws] = struct{}{}
+ }
+ }
+ for _, ws := range w.resuming {
+ if _, ok := closing[ws]; ws != nil && !ok {
+ close(ws.recvc)
+ closing[ws] = struct{}{}
+ }
+ }
+ w.joinSubstreams()
+ for range closing {
+ w.closeSubstream(<-w.closingc)
+ }
+ w.wg.Wait()
+ w.owner.closeStream(w)
+ }()
+
+ // start a stream with the etcd grpc server
+ if wc, closeErr = w.newWatchClient(); closeErr != nil {
+ return
+ }
+
+ cancelSet := make(map[int64]struct{})
+
+ for {
+ select {
+ // Watch() requested
+ case wreq := <-w.reqc:
+ outc := make(chan WatchResponse, 1)
+ ws := &watcherStream{
+ initReq: *wreq,
+ id: -1,
+ outc: outc,
+ // unbuffered so resumes won't cause repeat events
+ recvc: make(chan *WatchResponse),
+ }
+
+ ws.donec = make(chan struct{})
+ w.wg.Add(1)
+ go w.serveSubstream(ws, w.resumec)
+
+ // queue up for watcher creation/resume
+ w.resuming = append(w.resuming, ws)
+ if len(w.resuming) == 1 {
+ // head of resume queue, can register a new watcher
+ wc.Send(ws.initReq.toPB())
+ }
+ // New events from the watch client
+ case pbresp := <-w.respc:
+ switch {
+ case pbresp.Created:
+ // response to head of queue creation
+ if ws := w.resuming[0]; ws != nil {
+ w.addSubstream(pbresp, ws)
+ w.dispatchEvent(pbresp)
+ w.resuming[0] = nil
+ }
+ if ws := w.nextResume(); ws != nil {
+ wc.Send(ws.initReq.toPB())
+ }
+ case pbresp.Canceled && pbresp.CompactRevision == 0:
+ delete(cancelSet, pbresp.WatchId)
+ if ws, ok := w.substreams[pbresp.WatchId]; ok {
+ // signal to stream goroutine to update closingc
+ close(ws.recvc)
+ closing[ws] = struct{}{}
+ }
+ default:
+ // dispatch to appropriate watch stream
+ if ok := w.dispatchEvent(pbresp); ok {
+ break
+ }
+ // watch response on unexpected watch id; cancel id
+ if _, ok := cancelSet[pbresp.WatchId]; ok {
+ break
+ }
+ cancelSet[pbresp.WatchId] = struct{}{}
+ cr := &pb.WatchRequest_CancelRequest{
+ CancelRequest: &pb.WatchCancelRequest{
+ WatchId: pbresp.WatchId,
+ },
+ }
+ req := &pb.WatchRequest{RequestUnion: cr}
+ wc.Send(req)
+ }
+ // watch client failed on Recv; spawn another if possible
+ case err := <-w.errc:
+ if isHaltErr(w.ctx, err) || toErr(w.ctx, err) == v3rpc.ErrNoLeader {
+ closeErr = err
+ return
+ }
+ if wc, closeErr = w.newWatchClient(); closeErr != nil {
+ return
+ }
+ if ws := w.nextResume(); ws != nil {
+ wc.Send(ws.initReq.toPB())
+ }
+ cancelSet = make(map[int64]struct{})
+ case <-w.ctx.Done():
+ return
+ case ws := <-w.closingc:
+ w.closeSubstream(ws)
+ delete(closing, ws)
+ if len(w.substreams)+len(w.resuming) == 0 {
+ // no more watchers on this stream, shutdown
+ return
+ }
+ }
+ }
+}
+
+// nextResume chooses the next resuming to register with the grpc stream. Abandoned
+// streams are marked as nil in the queue since the head must wait for its inflight registration.
+func (w *watchGrpcStream) nextResume() *watcherStream {
+ for len(w.resuming) != 0 {
+ if w.resuming[0] != nil {
+ return w.resuming[0]
+ }
+ w.resuming = w.resuming[1:len(w.resuming)]
+ }
+ return nil
+}
+
+// dispatchEvent sends a WatchResponse to the appropriate watcher stream
+func (w *watchGrpcStream) dispatchEvent(pbresp *pb.WatchResponse) bool {
+ events := make([]*Event, len(pbresp.Events))
+ for i, ev := range pbresp.Events {
+ events[i] = (*Event)(ev)
+ }
+ wr := &WatchResponse{
+ Header: *pbresp.Header,
+ Events: events,
+ CompactRevision: pbresp.CompactRevision,
+ Created: pbresp.Created,
+ Canceled: pbresp.Canceled,
+ cancelReason: pbresp.CancelReason,
+ }
+ ws, ok := w.substreams[pbresp.WatchId]
+ if !ok {
+ return false
+ }
+ select {
+ case ws.recvc <- wr:
+ case <-ws.donec:
+ return false
+ }
+ return true
+}
+
+// serveWatchClient forwards messages from the grpc stream to run()
+func (w *watchGrpcStream) serveWatchClient(wc pb.Watch_WatchClient) {
+ for {
+ resp, err := wc.Recv()
+ if err != nil {
+ select {
+ case w.errc <- err:
+ case <-w.donec:
+ }
+ return
+ }
+ select {
+ case w.respc <- resp:
+ case <-w.donec:
+ return
+ }
+ }
+}
+
+// serveSubstream forwards watch responses from run() to the subscriber
+func (w *watchGrpcStream) serveSubstream(ws *watcherStream, resumec chan struct{}) {
+ if ws.closing {
+ panic("created substream goroutine but substream is closing")
+ }
+
+ // nextRev is the minimum expected next revision
+ nextRev := ws.initReq.rev
+ resuming := false
+ defer func() {
+ if !resuming {
+ ws.closing = true
+ }
+ close(ws.donec)
+ if !resuming {
+ w.closingc <- ws
+ }
+ w.wg.Done()
+ }()
+
+ emptyWr := &WatchResponse{}
+ for {
+ curWr := emptyWr
+ outc := ws.outc
+
+ if len(ws.buf) > 0 {
+ curWr = ws.buf[0]
+ } else {
+ outc = nil
+ }
+ select {
+ case outc <- *curWr:
+ if ws.buf[0].Err() != nil {
+ return
+ }
+ ws.buf[0] = nil
+ ws.buf = ws.buf[1:]
+ case wr, ok := <-ws.recvc:
+ if !ok {
+ // shutdown from closeSubstream
+ return
+ }
+
+ if wr.Created {
+ if ws.initReq.retc != nil {
+ ws.initReq.retc <- ws.outc
+ // to prevent next write from taking the slot in buffered channel
+ // and posting duplicate create events
+ ws.initReq.retc = nil
+
+ // send first creation event only if requested
+ if ws.initReq.createdNotify {
+ ws.outc <- *wr
+ }
+ // once the watch channel is returned, a current revision
+ // watch must resume at the store revision. This is necessary
+ // for the following case to work as expected:
+ // wch := m1.Watch("a")
+ // m2.Put("a", "b")
+ // <-wch
+ // If the revision is only bound on the first observed event,
+ // if wch is disconnected before the Put is issued, then reconnects
+ // after it is committed, it'll miss the Put.
+ if ws.initReq.rev == 0 {
+ nextRev = wr.Header.Revision
+ }
+ }
+ } else {
+ // current progress of watch; <= store revision
+ nextRev = wr.Header.Revision
+ }
+
+ if len(wr.Events) > 0 {
+ nextRev = wr.Events[len(wr.Events)-1].Kv.ModRevision + 1
+ }
+ ws.initReq.rev = nextRev
+
+ // created event is already sent above,
+ // watcher should not post duplicate events
+ if wr.Created {
+ continue
+ }
+
+ // TODO pause channel if buffer gets too large
+ ws.buf = append(ws.buf, wr)
+ case <-w.ctx.Done():
+ return
+ case <-ws.initReq.ctx.Done():
+ return
+ case <-resumec:
+ resuming = true
+ return
+ }
+ }
+ // lazily send cancel message if events on missing id
+}
+
+func (w *watchGrpcStream) newWatchClient() (pb.Watch_WatchClient, error) {
+ // mark all substreams as resuming
+ close(w.resumec)
+ w.resumec = make(chan struct{})
+ w.joinSubstreams()
+ for _, ws := range w.substreams {
+ ws.id = -1
+ w.resuming = append(w.resuming, ws)
+ }
+ // strip out nils, if any
+ var resuming []*watcherStream
+ for _, ws := range w.resuming {
+ if ws != nil {
+ resuming = append(resuming, ws)
+ }
+ }
+ w.resuming = resuming
+ w.substreams = make(map[int64]*watcherStream)
+
+ // connect to grpc stream while accepting watcher cancelation
+ stopc := make(chan struct{})
+ donec := w.waitCancelSubstreams(stopc)
+ wc, err := w.openWatchClient()
+ close(stopc)
+ <-donec
+
+ // serve all non-closing streams, even if there's a client error
+ // so that the teardown path can shutdown the streams as expected.
+ for _, ws := range w.resuming {
+ if ws.closing {
+ continue
+ }
+ ws.donec = make(chan struct{})
+ w.wg.Add(1)
+ go w.serveSubstream(ws, w.resumec)
+ }
+
+ if err != nil {
+ return nil, v3rpc.Error(err)
+ }
+
+ // receive data from new grpc stream
+ go w.serveWatchClient(wc)
+ return wc, nil
+}
+
+func (w *watchGrpcStream) waitCancelSubstreams(stopc <-chan struct{}) <-chan struct{} {
+ var wg sync.WaitGroup
+ wg.Add(len(w.resuming))
+ donec := make(chan struct{})
+ for i := range w.resuming {
+ go func(ws *watcherStream) {
+ defer wg.Done()
+ if ws.closing {
+ if ws.initReq.ctx.Err() != nil && ws.outc != nil {
+ close(ws.outc)
+ ws.outc = nil
+ }
+ return
+ }
+ select {
+ case <-ws.initReq.ctx.Done():
+ // closed ws will be removed from resuming
+ ws.closing = true
+ close(ws.outc)
+ ws.outc = nil
+ w.wg.Add(1)
+ go func() {
+ defer w.wg.Done()
+ w.closingc <- ws
+ }()
+ case <-stopc:
+ }
+ }(w.resuming[i])
+ }
+ go func() {
+ defer close(donec)
+ wg.Wait()
+ }()
+ return donec
+}
+
+// joinSubstreams waits for all substream goroutines to complete.
+func (w *watchGrpcStream) joinSubstreams() {
+ for _, ws := range w.substreams {
+ <-ws.donec
+ }
+ for _, ws := range w.resuming {
+ if ws != nil {
+ <-ws.donec
+ }
+ }
+}
+
+var maxBackoff = 100 * time.Millisecond
+
+// openWatchClient retries opening a watch client until success or halt.
+// manually retry in case "ws==nil && err==nil"
+// TODO: remove FailFast=false
+func (w *watchGrpcStream) openWatchClient() (ws pb.Watch_WatchClient, err error) {
+ backoff := time.Millisecond
+ for {
+ select {
+ case <-w.ctx.Done():
+ if err == nil {
+ return nil, w.ctx.Err()
+ }
+ return nil, err
+ default:
+ }
+ if ws, err = w.remote.Watch(w.ctx, w.callOpts...); ws != nil && err == nil {
+ break
+ }
+ if isHaltErr(w.ctx, err) {
+ return nil, v3rpc.Error(err)
+ }
+ if isUnavailableErr(w.ctx, err) {
+ // retry, but backoff
+ if backoff < maxBackoff {
+ // 25% backoff factor
+ backoff = backoff + backoff/4
+ if backoff > maxBackoff {
+ backoff = maxBackoff
+ }
+ }
+ time.Sleep(backoff)
+ }
+ }
+ return ws, nil
+}
+
+// toPB converts an internal watch request structure to its protobuf WatchRequest structure.
+func (wr *watchRequest) toPB() *pb.WatchRequest {
+ req := &pb.WatchCreateRequest{
+ StartRevision: wr.rev,
+ Key: []byte(wr.key),
+ RangeEnd: []byte(wr.end),
+ ProgressNotify: wr.progressNotify,
+ Filters: wr.filters,
+ PrevKv: wr.prevKV,
+ }
+ cr := &pb.WatchRequest_CreateRequest{CreateRequest: req}
+ return &pb.WatchRequest{RequestUnion: cr}
+}
+
+func streamKeyFromCtx(ctx context.Context) string {
+ if md, ok := metadata.FromOutgoingContext(ctx); ok {
+ return fmt.Sprintf("%+v", md)
+ }
+ return ""
+}
diff --git a/vendor/github.com/coreos/etcd/cmd/etcd b/vendor/github.com/coreos/etcd/cmd/etcd
new file mode 120000
index 00000000..b870225a
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/cmd/etcd
@@ -0,0 +1 @@
+../
\ No newline at end of file
diff --git a/vendor/github.com/coreos/etcd/cmd/etcdctl b/vendor/github.com/coreos/etcd/cmd/etcdctl
new file mode 120000
index 00000000..05bb269d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/cmd/etcdctl
@@ -0,0 +1 @@
+../etcdctl
\ No newline at end of file
diff --git a/vendor/github.com/coreos/etcd/cmd/functional b/vendor/github.com/coreos/etcd/cmd/functional
new file mode 120000
index 00000000..44faa31a
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/cmd/functional
@@ -0,0 +1 @@
+../functional
\ No newline at end of file
diff --git a/vendor/github.com/coreos/etcd/cmd/tools b/vendor/github.com/coreos/etcd/cmd/tools
new file mode 120000
index 00000000..4887d6e0
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/cmd/tools
@@ -0,0 +1 @@
+../tools
\ No newline at end of file
diff --git a/vendor/github.com/coreos/etcd/compactor/compactor.go b/vendor/github.com/coreos/etcd/compactor/compactor.go
new file mode 100644
index 00000000..8100b693
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/compactor/compactor.go
@@ -0,0 +1,66 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compactor
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "compactor")
+)
+
+const (
+ ModePeriodic = "periodic"
+ ModeRevision = "revision"
+)
+
+// Compactor purges old log from the storage periodically.
+type Compactor interface {
+ // Run starts the main loop of the compactor in background.
+ // Use Stop() to halt the loop and release the resource.
+ Run()
+ // Stop halts the main loop of the compactor.
+ Stop()
+ // Pause temporally suspend the compactor not to run compaction. Resume() to unpose.
+ Pause()
+ // Resume restarts the compactor suspended by Pause().
+ Resume()
+}
+
+type Compactable interface {
+ Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error)
+}
+
+type RevGetter interface {
+ Rev() int64
+}
+
+func New(mode string, retention time.Duration, rg RevGetter, c Compactable) (Compactor, error) {
+ switch mode {
+ case ModePeriodic:
+ return NewPeriodic(retention, rg, c), nil
+ case ModeRevision:
+ return NewRevision(int64(retention), rg, c), nil
+ default:
+ return nil, fmt.Errorf("unsupported compaction mode %s", mode)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/compactor/doc.go b/vendor/github.com/coreos/etcd/compactor/doc.go
new file mode 100644
index 00000000..cb158340
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/compactor/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package compactor implements automated policies for compacting etcd's mvcc storage.
+package compactor
diff --git a/vendor/github.com/coreos/etcd/compactor/periodic.go b/vendor/github.com/coreos/etcd/compactor/periodic.go
new file mode 100644
index 00000000..9d9164e9
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/compactor/periodic.go
@@ -0,0 +1,191 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compactor
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/mvcc"
+
+ "github.com/jonboulle/clockwork"
+)
+
+// Periodic compacts the log by purging revisions older than
+// the configured retention time.
+type Periodic struct {
+ clock clockwork.Clock
+ period time.Duration
+
+ rg RevGetter
+ c Compactable
+
+ revs []int64
+ ctx context.Context
+ cancel context.CancelFunc
+
+ // mu protects paused
+ mu sync.RWMutex
+ paused bool
+}
+
+// NewPeriodic creates a new instance of Periodic compactor that purges
+// the log older than h Duration.
+func NewPeriodic(h time.Duration, rg RevGetter, c Compactable) *Periodic {
+ return newPeriodic(clockwork.NewRealClock(), h, rg, c)
+}
+
+func newPeriodic(clock clockwork.Clock, h time.Duration, rg RevGetter, c Compactable) *Periodic {
+ t := &Periodic{
+ clock: clock,
+ period: h,
+ rg: rg,
+ c: c,
+ revs: make([]int64, 0),
+ }
+ t.ctx, t.cancel = context.WithCancel(context.Background())
+ return t
+}
+
+/*
+Compaction period 1-hour:
+ 1. compute compaction period, which is 1-hour
+ 2. record revisions for every 1/10 of 1-hour (6-minute)
+ 3. keep recording revisions with no compaction for first 1-hour
+ 4. do compact with revs[0]
+ - success? contiue on for-loop and move sliding window; revs = revs[1:]
+ - failure? update revs, and retry after 1/10 of 1-hour (6-minute)
+
+Compaction period 24-hour:
+ 1. compute compaction period, which is 1-hour
+ 2. record revisions for every 1/10 of 1-hour (6-minute)
+ 3. keep recording revisions with no compaction for first 24-hour
+ 4. do compact with revs[0]
+ - success? contiue on for-loop and move sliding window; revs = revs[1:]
+ - failure? update revs, and retry after 1/10 of 1-hour (6-minute)
+
+Compaction period 59-min:
+ 1. compute compaction period, which is 59-min
+ 2. record revisions for every 1/10 of 59-min (5.9-min)
+ 3. keep recording revisions with no compaction for first 59-min
+ 4. do compact with revs[0]
+ - success? contiue on for-loop and move sliding window; revs = revs[1:]
+ - failure? update revs, and retry after 1/10 of 59-min (5.9-min)
+
+Compaction period 5-sec:
+ 1. compute compaction period, which is 5-sec
+ 2. record revisions for every 1/10 of 5-sec (0.5-sec)
+ 3. keep recording revisions with no compaction for first 5-sec
+ 4. do compact with revs[0]
+ - success? contiue on for-loop and move sliding window; revs = revs[1:]
+ - failure? update revs, and retry after 1/10 of 5-sec (0.5-sec)
+*/
+
+// Run runs periodic compactor.
+func (t *Periodic) Run() {
+ compactInterval := t.getCompactInterval()
+ retryInterval := t.getRetryInterval()
+ retentions := t.getRetentions()
+
+ go func() {
+ lastSuccess := t.clock.Now()
+ baseInterval := t.period
+ for {
+ t.revs = append(t.revs, t.rg.Rev())
+ if len(t.revs) > retentions {
+ t.revs = t.revs[1:] // t.revs[0] is always the rev at t.period ago
+ }
+
+ select {
+ case <-t.ctx.Done():
+ return
+ case <-t.clock.After(retryInterval):
+ t.mu.Lock()
+ p := t.paused
+ t.mu.Unlock()
+ if p {
+ continue
+ }
+ }
+
+ if t.clock.Now().Sub(lastSuccess) < baseInterval {
+ continue
+ }
+
+ // wait up to initial given period
+ if baseInterval == t.period {
+ baseInterval = compactInterval
+ }
+ rev := t.revs[0]
+
+ plog.Noticef("Starting auto-compaction at revision %d (retention: %v)", rev, t.period)
+ _, err := t.c.Compact(t.ctx, &pb.CompactionRequest{Revision: rev})
+ if err == nil || err == mvcc.ErrCompacted {
+ lastSuccess = t.clock.Now()
+ plog.Noticef("Finished auto-compaction at revision %d", rev)
+ } else {
+ plog.Noticef("Failed auto-compaction at revision %d (%v)", rev, err)
+ plog.Noticef("Retry after %v", retryInterval)
+ }
+ }
+ }()
+}
+
+// if given compaction period x is <1-hour, compact every x duration.
+// (e.g. --auto-compaction-mode 'periodic' --auto-compaction-retention='10m', then compact every 10-minute)
+// if given compaction period x is >1-hour, compact every hour.
+// (e.g. --auto-compaction-mode 'periodic' --auto-compaction-retention='2h', then compact every 1-hour)
+func (t *Periodic) getCompactInterval() time.Duration {
+ itv := t.period
+ if itv > time.Hour {
+ itv = time.Hour
+ }
+ return itv
+}
+
+func (t *Periodic) getRetentions() int {
+ return int(t.period/t.getRetryInterval()) + 1
+}
+
+const retryDivisor = 10
+
+func (t *Periodic) getRetryInterval() time.Duration {
+ itv := t.period
+ if itv > time.Hour {
+ itv = time.Hour
+ }
+ return itv / retryDivisor
+}
+
+// Stop stops periodic compactor.
+func (t *Periodic) Stop() {
+ t.cancel()
+}
+
+// Pause pauses periodic compactor.
+func (t *Periodic) Pause() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.paused = true
+}
+
+// Resume resumes periodic compactor.
+func (t *Periodic) Resume() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.paused = false
+}
diff --git a/vendor/github.com/coreos/etcd/compactor/revision.go b/vendor/github.com/coreos/etcd/compactor/revision.go
new file mode 100644
index 00000000..927e41c9
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/compactor/revision.go
@@ -0,0 +1,115 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package compactor
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/mvcc"
+
+ "github.com/jonboulle/clockwork"
+)
+
+// Revision compacts the log by purging revisions older than
+// the configured reivison number. Compaction happens every 5 minutes.
+type Revision struct {
+ clock clockwork.Clock
+ retention int64
+
+ rg RevGetter
+ c Compactable
+
+ ctx context.Context
+ cancel context.CancelFunc
+
+ mu sync.Mutex
+ paused bool
+}
+
+// NewRevision creates a new instance of Revisonal compactor that purges
+// the log older than retention revisions from the current revision.
+func NewRevision(retention int64, rg RevGetter, c Compactable) *Revision {
+ return newRevision(clockwork.NewRealClock(), retention, rg, c)
+}
+
+func newRevision(clock clockwork.Clock, retention int64, rg RevGetter, c Compactable) *Revision {
+ t := &Revision{
+ clock: clock,
+ retention: retention,
+ rg: rg,
+ c: c,
+ }
+ t.ctx, t.cancel = context.WithCancel(context.Background())
+ return t
+}
+
+const revInterval = 5 * time.Minute
+
+// Run runs revision-based compactor.
+func (t *Revision) Run() {
+ prev := int64(0)
+ go func() {
+ for {
+ select {
+ case <-t.ctx.Done():
+ return
+ case <-t.clock.After(revInterval):
+ t.mu.Lock()
+ p := t.paused
+ t.mu.Unlock()
+ if p {
+ continue
+ }
+ }
+
+ rev := t.rg.Rev() - t.retention
+ if rev <= 0 || rev == prev {
+ continue
+ }
+
+ plog.Noticef("Starting auto-compaction at revision %d (retention: %d revisions)", rev, t.retention)
+ _, err := t.c.Compact(t.ctx, &pb.CompactionRequest{Revision: rev})
+ if err == nil || err == mvcc.ErrCompacted {
+ prev = rev
+ plog.Noticef("Finished auto-compaction at revision %d", rev)
+ } else {
+ plog.Noticef("Failed auto-compaction at revision %d (%v)", rev, err)
+ plog.Noticef("Retry after %v", revInterval)
+ }
+ }
+ }()
+}
+
+// Stop stops revision-based compactor.
+func (t *Revision) Stop() {
+ t.cancel()
+}
+
+// Pause pauses revision-based compactor.
+func (t *Revision) Pause() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.paused = true
+}
+
+// Resume resumes revision-based compactor.
+func (t *Revision) Resume() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.paused = false
+}
diff --git a/vendor/github.com/coreos/etcd/discovery/discovery.go b/vendor/github.com/coreos/etcd/discovery/discovery.go
new file mode 100644
index 00000000..7d1fa0d0
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/discovery/discovery.go
@@ -0,0 +1,363 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package discovery provides an implementation of the cluster discovery that
+// is used by etcd.
+package discovery
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math"
+ "net/http"
+ "net/url"
+ "path"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/coreos/etcd/client"
+ "github.com/coreos/etcd/pkg/transport"
+ "github.com/coreos/etcd/pkg/types"
+
+ "github.com/coreos/pkg/capnslog"
+ "github.com/jonboulle/clockwork"
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "discovery")
+
+ ErrInvalidURL = errors.New("discovery: invalid URL")
+ ErrBadSizeKey = errors.New("discovery: size key is bad")
+ ErrSizeNotFound = errors.New("discovery: size key not found")
+ ErrTokenNotFound = errors.New("discovery: token not found")
+ ErrDuplicateID = errors.New("discovery: found duplicate id")
+ ErrDuplicateName = errors.New("discovery: found duplicate name")
+ ErrFullCluster = errors.New("discovery: cluster is full")
+ ErrTooManyRetries = errors.New("discovery: too many retries")
+ ErrBadDiscoveryEndpoint = errors.New("discovery: bad discovery endpoint")
+)
+
+var (
+ // Number of retries discovery will attempt before giving up and erroring out.
+ nRetries = uint(math.MaxUint32)
+ maxExpoentialRetries = uint(8)
+)
+
+// JoinCluster will connect to the discovery service at the given url, and
+// register the server represented by the given id and config to the cluster
+func JoinCluster(durl, dproxyurl string, id types.ID, config string) (string, error) {
+ d, err := newDiscovery(durl, dproxyurl, id)
+ if err != nil {
+ return "", err
+ }
+ return d.joinCluster(config)
+}
+
+// GetCluster will connect to the discovery service at the given url and
+// retrieve a string describing the cluster
+func GetCluster(durl, dproxyurl string) (string, error) {
+ d, err := newDiscovery(durl, dproxyurl, 0)
+ if err != nil {
+ return "", err
+ }
+ return d.getCluster()
+}
+
+type discovery struct {
+ cluster string
+ id types.ID
+ c client.KeysAPI
+ retries uint
+ url *url.URL
+
+ clock clockwork.Clock
+}
+
+// newProxyFunc builds a proxy function from the given string, which should
+// represent a URL that can be used as a proxy. It performs basic
+// sanitization of the URL and returns any error encountered.
+func newProxyFunc(proxy string) (func(*http.Request) (*url.URL, error), error) {
+ if proxy == "" {
+ return nil, nil
+ }
+ // Do a small amount of URL sanitization to help the user
+ // Derived from net/http.ProxyFromEnvironment
+ proxyURL, err := url.Parse(proxy)
+ if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") {
+ // proxy was bogus. Try prepending "http://" to it and
+ // see if that parses correctly. If not, we ignore the
+ // error and complain about the original one
+ var err2 error
+ proxyURL, err2 = url.Parse("http://" + proxy)
+ if err2 == nil {
+ err = nil
+ }
+ }
+ if err != nil {
+ return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
+ }
+
+ plog.Infof("using proxy %q", proxyURL.String())
+ return http.ProxyURL(proxyURL), nil
+}
+
+func newDiscovery(durl, dproxyurl string, id types.ID) (*discovery, error) {
+ u, err := url.Parse(durl)
+ if err != nil {
+ return nil, err
+ }
+ token := u.Path
+ u.Path = ""
+ pf, err := newProxyFunc(dproxyurl)
+ if err != nil {
+ return nil, err
+ }
+
+ // TODO: add ResponseHeaderTimeout back when watch on discovery service writes header early
+ tr, err := transport.NewTransport(transport.TLSInfo{}, 30*time.Second)
+ if err != nil {
+ return nil, err
+ }
+ tr.Proxy = pf
+ cfg := client.Config{
+ Transport: tr,
+ Endpoints: []string{u.String()},
+ }
+ c, err := client.New(cfg)
+ if err != nil {
+ return nil, err
+ }
+ dc := client.NewKeysAPIWithPrefix(c, "")
+ return &discovery{
+ cluster: token,
+ c: dc,
+ id: id,
+ url: u,
+ clock: clockwork.NewRealClock(),
+ }, nil
+}
+
+func (d *discovery) joinCluster(config string) (string, error) {
+ // fast path: if the cluster is full, return the error
+ // do not need to register to the cluster in this case.
+ if _, _, _, err := d.checkCluster(); err != nil {
+ return "", err
+ }
+
+ if err := d.createSelf(config); err != nil {
+ // Fails, even on a timeout, if createSelf times out.
+ // TODO(barakmich): Retrying the same node might want to succeed here
+ // (ie, createSelf should be idempotent for discovery).
+ return "", err
+ }
+
+ nodes, size, index, err := d.checkCluster()
+ if err != nil {
+ return "", err
+ }
+
+ all, err := d.waitNodes(nodes, size, index)
+ if err != nil {
+ return "", err
+ }
+
+ return nodesToCluster(all, size)
+}
+
+func (d *discovery) getCluster() (string, error) {
+ nodes, size, index, err := d.checkCluster()
+ if err != nil {
+ if err == ErrFullCluster {
+ return nodesToCluster(nodes, size)
+ }
+ return "", err
+ }
+
+ all, err := d.waitNodes(nodes, size, index)
+ if err != nil {
+ return "", err
+ }
+ return nodesToCluster(all, size)
+}
+
+func (d *discovery) createSelf(contents string) error {
+ ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
+ resp, err := d.c.Create(ctx, d.selfKey(), contents)
+ cancel()
+ if err != nil {
+ if eerr, ok := err.(client.Error); ok && eerr.Code == client.ErrorCodeNodeExist {
+ return ErrDuplicateID
+ }
+ return err
+ }
+
+ // ensure self appears on the server we connected to
+ w := d.c.Watcher(d.selfKey(), &client.WatcherOptions{AfterIndex: resp.Node.CreatedIndex - 1})
+ _, err = w.Next(context.Background())
+ return err
+}
+
+func (d *discovery) checkCluster() ([]*client.Node, int, uint64, error) {
+ configKey := path.Join("/", d.cluster, "_config")
+ ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
+ // find cluster size
+ resp, err := d.c.Get(ctx, path.Join(configKey, "size"), nil)
+ cancel()
+ if err != nil {
+ if eerr, ok := err.(*client.Error); ok && eerr.Code == client.ErrorCodeKeyNotFound {
+ return nil, 0, 0, ErrSizeNotFound
+ }
+ if err == client.ErrInvalidJSON {
+ return nil, 0, 0, ErrBadDiscoveryEndpoint
+ }
+ if ce, ok := err.(*client.ClusterError); ok {
+ plog.Error(ce.Detail())
+ return d.checkClusterRetry()
+ }
+ return nil, 0, 0, err
+ }
+ size, err := strconv.Atoi(resp.Node.Value)
+ if err != nil {
+ return nil, 0, 0, ErrBadSizeKey
+ }
+
+ ctx, cancel = context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
+ resp, err = d.c.Get(ctx, d.cluster, nil)
+ cancel()
+ if err != nil {
+ if ce, ok := err.(*client.ClusterError); ok {
+ plog.Error(ce.Detail())
+ return d.checkClusterRetry()
+ }
+ return nil, 0, 0, err
+ }
+ var nodes []*client.Node
+ // append non-config keys to nodes
+ for _, n := range resp.Node.Nodes {
+ if !(path.Base(n.Key) == path.Base(configKey)) {
+ nodes = append(nodes, n)
+ }
+ }
+
+ snodes := sortableNodes{nodes}
+ sort.Sort(snodes)
+
+ // find self position
+ for i := range nodes {
+ if path.Base(nodes[i].Key) == path.Base(d.selfKey()) {
+ break
+ }
+ if i >= size-1 {
+ return nodes[:size], size, resp.Index, ErrFullCluster
+ }
+ }
+ return nodes, size, resp.Index, nil
+}
+
+func (d *discovery) logAndBackoffForRetry(step string) {
+ d.retries++
+ // logAndBackoffForRetry stops exponential backoff when the retries are more than maxExpoentialRetries and is set to a constant backoff afterward.
+ retries := d.retries
+ if retries > maxExpoentialRetries {
+ retries = maxExpoentialRetries
+ }
+ retryTimeInSecond := time.Duration(0x1< size {
+ nodes = nodes[:size]
+ }
+ // watch from the next index
+ w := d.c.Watcher(d.cluster, &client.WatcherOptions{AfterIndex: index, Recursive: true})
+ all := make([]*client.Node, len(nodes))
+ copy(all, nodes)
+ for _, n := range all {
+ if path.Base(n.Key) == path.Base(d.selfKey()) {
+ plog.Noticef("found self %s in the cluster", path.Base(d.selfKey()))
+ } else {
+ plog.Noticef("found peer %s in the cluster", path.Base(n.Key))
+ }
+ }
+
+ // wait for others
+ for len(all) < size {
+ plog.Noticef("found %d peer(s), waiting for %d more", len(all), size-len(all))
+ resp, err := w.Next(context.Background())
+ if err != nil {
+ if ce, ok := err.(*client.ClusterError); ok {
+ plog.Error(ce.Detail())
+ return d.waitNodesRetry()
+ }
+ return nil, err
+ }
+ plog.Noticef("found peer %s in the cluster", path.Base(resp.Node.Key))
+ all = append(all, resp.Node)
+ }
+ plog.Noticef("found %d needed peer(s)", len(all))
+ return all, nil
+}
+
+func (d *discovery) selfKey() string {
+ return path.Join("/", d.cluster, d.id.String())
+}
+
+func nodesToCluster(ns []*client.Node, size int) (string, error) {
+ s := make([]string, len(ns))
+ for i, n := range ns {
+ s[i] = n.Value
+ }
+ us := strings.Join(s, ",")
+ m, err := types.NewURLsMap(us)
+ if err != nil {
+ return us, ErrInvalidURL
+ }
+ if m.Len() != size {
+ return us, ErrDuplicateName
+ }
+ return us, nil
+}
+
+type sortableNodes struct{ Nodes []*client.Node }
+
+func (ns sortableNodes) Len() int { return len(ns.Nodes) }
+func (ns sortableNodes) Less(i, j int) bool {
+ return ns.Nodes[i].CreatedIndex < ns.Nodes[j].CreatedIndex
+}
+func (ns sortableNodes) Swap(i, j int) { ns.Nodes[i], ns.Nodes[j] = ns.Nodes[j], ns.Nodes[i] }
diff --git a/vendor/github.com/coreos/etcd/error/error.go b/vendor/github.com/coreos/etcd/error/error.go
new file mode 100644
index 00000000..b541a628
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/error/error.go
@@ -0,0 +1,163 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package error describes errors in etcd project. When any change happens,
+// Documentation/v2/errorcode.md needs to be updated correspondingly.
+package error
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+)
+
+var errors = map[int]string{
+ // command related errors
+ EcodeKeyNotFound: "Key not found",
+ EcodeTestFailed: "Compare failed", //test and set
+ EcodeNotFile: "Not a file",
+ ecodeNoMorePeer: "Reached the max number of peers in the cluster",
+ EcodeNotDir: "Not a directory",
+ EcodeNodeExist: "Key already exists", // create
+ ecodeKeyIsPreserved: "The prefix of given key is a keyword in etcd",
+ EcodeRootROnly: "Root is read only",
+ EcodeDirNotEmpty: "Directory not empty",
+ ecodeExistingPeerAddr: "Peer address has existed",
+ EcodeUnauthorized: "The request requires user authentication",
+
+ // Post form related errors
+ ecodeValueRequired: "Value is Required in POST form",
+ EcodePrevValueRequired: "PrevValue is Required in POST form",
+ EcodeTTLNaN: "The given TTL in POST form is not a number",
+ EcodeIndexNaN: "The given index in POST form is not a number",
+ ecodeValueOrTTLRequired: "Value or TTL is required in POST form",
+ ecodeTimeoutNaN: "The given timeout in POST form is not a number",
+ ecodeNameRequired: "Name is required in POST form",
+ ecodeIndexOrValueRequired: "Index or value is required",
+ ecodeIndexValueMutex: "Index and value cannot both be specified",
+ EcodeInvalidField: "Invalid field",
+ EcodeInvalidForm: "Invalid POST form",
+ EcodeRefreshValue: "Value provided on refresh",
+ EcodeRefreshTTLRequired: "A TTL must be provided on refresh",
+
+ // raft related errors
+ EcodeRaftInternal: "Raft Internal Error",
+ EcodeLeaderElect: "During Leader Election",
+
+ // etcd related errors
+ EcodeWatcherCleared: "watcher is cleared due to etcd recovery",
+ EcodeEventIndexCleared: "The event in requested index is outdated and cleared",
+ ecodeStandbyInternal: "Standby Internal Error",
+ ecodeInvalidActiveSize: "Invalid active size",
+ ecodeInvalidRemoveDelay: "Standby remove delay",
+
+ // client related errors
+ ecodeClientInternal: "Client Internal Error",
+}
+
+var errorStatus = map[int]int{
+ EcodeKeyNotFound: http.StatusNotFound,
+ EcodeNotFile: http.StatusForbidden,
+ EcodeDirNotEmpty: http.StatusForbidden,
+ EcodeUnauthorized: http.StatusUnauthorized,
+ EcodeTestFailed: http.StatusPreconditionFailed,
+ EcodeNodeExist: http.StatusPreconditionFailed,
+ EcodeRaftInternal: http.StatusInternalServerError,
+ EcodeLeaderElect: http.StatusInternalServerError,
+}
+
+const (
+ EcodeKeyNotFound = 100
+ EcodeTestFailed = 101
+ EcodeNotFile = 102
+ ecodeNoMorePeer = 103
+ EcodeNotDir = 104
+ EcodeNodeExist = 105
+ ecodeKeyIsPreserved = 106
+ EcodeRootROnly = 107
+ EcodeDirNotEmpty = 108
+ ecodeExistingPeerAddr = 109
+ EcodeUnauthorized = 110
+
+ ecodeValueRequired = 200
+ EcodePrevValueRequired = 201
+ EcodeTTLNaN = 202
+ EcodeIndexNaN = 203
+ ecodeValueOrTTLRequired = 204
+ ecodeTimeoutNaN = 205
+ ecodeNameRequired = 206
+ ecodeIndexOrValueRequired = 207
+ ecodeIndexValueMutex = 208
+ EcodeInvalidField = 209
+ EcodeInvalidForm = 210
+ EcodeRefreshValue = 211
+ EcodeRefreshTTLRequired = 212
+
+ EcodeRaftInternal = 300
+ EcodeLeaderElect = 301
+
+ EcodeWatcherCleared = 400
+ EcodeEventIndexCleared = 401
+ ecodeStandbyInternal = 402
+ ecodeInvalidActiveSize = 403
+ ecodeInvalidRemoveDelay = 404
+
+ ecodeClientInternal = 500
+)
+
+type Error struct {
+ ErrorCode int `json:"errorCode"`
+ Message string `json:"message"`
+ Cause string `json:"cause,omitempty"`
+ Index uint64 `json:"index"`
+}
+
+func NewRequestError(errorCode int, cause string) *Error {
+ return NewError(errorCode, cause, 0)
+}
+
+func NewError(errorCode int, cause string, index uint64) *Error {
+ return &Error{
+ ErrorCode: errorCode,
+ Message: errors[errorCode],
+ Cause: cause,
+ Index: index,
+ }
+}
+
+// Error is for the error interface
+func (e Error) Error() string {
+ return e.Message + " (" + e.Cause + ")"
+}
+
+func (e Error) toJsonString() string {
+ b, _ := json.Marshal(e)
+ return string(b)
+}
+
+func (e Error) StatusCode() int {
+ status, ok := errorStatus[e.ErrorCode]
+ if !ok {
+ status = http.StatusBadRequest
+ }
+ return status
+}
+
+func (e Error) WriteTo(w http.ResponseWriter) error {
+ w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index))
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(e.StatusCode())
+ _, err := w.Write([]byte(e.toJsonString() + "\n"))
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/capability.go b/vendor/github.com/coreos/etcd/etcdserver/api/capability.go
new file mode 100644
index 00000000..eb34383d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/capability.go
@@ -0,0 +1,87 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package api
+
+import (
+ "sync"
+
+ "github.com/coreos/etcd/version"
+ "github.com/coreos/go-semver/semver"
+ "github.com/coreos/pkg/capnslog"
+)
+
+type Capability string
+
+const (
+ AuthCapability Capability = "auth"
+ V3rpcCapability Capability = "v3rpc"
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "etcdserver/api")
+
+ // capabilityMaps is a static map of version to capability map.
+ capabilityMaps = map[string]map[Capability]bool{
+ "3.0.0": {AuthCapability: true, V3rpcCapability: true},
+ "3.1.0": {AuthCapability: true, V3rpcCapability: true},
+ "3.2.0": {AuthCapability: true, V3rpcCapability: true},
+ "3.3.0": {AuthCapability: true, V3rpcCapability: true},
+ }
+
+ enableMapMu sync.RWMutex
+ // enabledMap points to a map in capabilityMaps
+ enabledMap map[Capability]bool
+
+ curVersion *semver.Version
+)
+
+func init() {
+ enabledMap = map[Capability]bool{
+ AuthCapability: true,
+ V3rpcCapability: true,
+ }
+}
+
+// UpdateCapability updates the enabledMap when the cluster version increases.
+func UpdateCapability(v *semver.Version) {
+ if v == nil {
+ // if recovered but version was never set by cluster
+ return
+ }
+ enableMapMu.Lock()
+ if curVersion != nil && !curVersion.LessThan(*v) {
+ enableMapMu.Unlock()
+ return
+ }
+ curVersion = v
+ enabledMap = capabilityMaps[curVersion.String()]
+ enableMapMu.Unlock()
+ plog.Infof("enabled capabilities for version %s", version.Cluster(v.String()))
+}
+
+func IsCapabilityEnabled(c Capability) bool {
+ enableMapMu.RLock()
+ defer enableMapMu.RUnlock()
+ if enabledMap == nil {
+ return false
+ }
+ return enabledMap[c]
+}
+
+func EnableCapability(c Capability) {
+ enableMapMu.Lock()
+ defer enableMapMu.Unlock()
+ enabledMap[c] = true
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/cluster.go b/vendor/github.com/coreos/etcd/etcdserver/api/cluster.go
new file mode 100644
index 00000000..654c2580
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/cluster.go
@@ -0,0 +1,38 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package api
+
+import (
+ "github.com/coreos/etcd/etcdserver/membership"
+ "github.com/coreos/etcd/pkg/types"
+
+ "github.com/coreos/go-semver/semver"
+)
+
+// Cluster is an interface representing a collection of members in one etcd cluster.
+type Cluster interface {
+ // ID returns the cluster ID
+ ID() types.ID
+ // ClientURLs returns an aggregate set of all URLs on which this
+ // cluster is listening for client requests
+ ClientURLs() []string
+ // Members returns a slice of members sorted by their ID
+ Members() []*membership.Member
+ // Member retrieves a particular member based on ID, or nil if the
+ // member does not exist in the cluster
+ Member(id types.ID) *membership.Member
+ // Version is the cluster-wide minimum major.minor version.
+ Version() *semver.Version
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/doc.go b/vendor/github.com/coreos/etcd/etcdserver/api/doc.go
new file mode 100644
index 00000000..f44881be
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package api manages the capabilities and features that are exposed to clients by the etcd cluster.
+package api
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes/errors.go b/vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes/errors.go
new file mode 100644
index 00000000..0657604c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes/errors.go
@@ -0,0 +1,56 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package httptypes
+
+import (
+ "encoding/json"
+ "net/http"
+
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "etcdserver/api/v2http/httptypes")
+)
+
+type HTTPError struct {
+ Message string `json:"message"`
+ // Code is the HTTP status code
+ Code int `json:"-"`
+}
+
+func (e HTTPError) Error() string {
+ return e.Message
+}
+
+func (e HTTPError) WriteTo(w http.ResponseWriter) error {
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(e.Code)
+ b, err := json.Marshal(e)
+ if err != nil {
+ plog.Panicf("marshal HTTPError should never fail (%v)", err)
+ }
+ if _, err := w.Write(b); err != nil {
+ return err
+ }
+ return nil
+}
+
+func NewHTTPError(code int, m string) *HTTPError {
+ return &HTTPError{
+ Message: m,
+ Code: code,
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes/member.go b/vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes/member.go
new file mode 100644
index 00000000..738d7443
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/v2http/httptypes/member.go
@@ -0,0 +1,69 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package httptypes defines how etcd's HTTP API entities are serialized to and
+// deserialized from JSON.
+package httptypes
+
+import (
+ "encoding/json"
+
+ "github.com/coreos/etcd/pkg/types"
+)
+
+type Member struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ PeerURLs []string `json:"peerURLs"`
+ ClientURLs []string `json:"clientURLs"`
+}
+
+type MemberCreateRequest struct {
+ PeerURLs types.URLs
+}
+
+type MemberUpdateRequest struct {
+ MemberCreateRequest
+}
+
+func (m *MemberCreateRequest) UnmarshalJSON(data []byte) error {
+ s := struct {
+ PeerURLs []string `json:"peerURLs"`
+ }{}
+
+ err := json.Unmarshal(data, &s)
+ if err != nil {
+ return err
+ }
+
+ urls, err := types.NewURLs(s.PeerURLs)
+ if err != nil {
+ return err
+ }
+
+ m.PeerURLs = urls
+ return nil
+}
+
+type MemberCollection []Member
+
+func (c *MemberCollection) MarshalJSON() ([]byte, error) {
+ d := struct {
+ Members []Member `json:"members"`
+ }{
+ Members: []Member(*c),
+ }
+
+ return json.Marshal(d)
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/doc.go b/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/doc.go
new file mode 100644
index 00000000..f72c6a64
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package rpctypes has types and values shared by the etcd server and client for v3 RPC interaction.
+package rpctypes
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/error.go b/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/error.go
new file mode 100644
index 00000000..55eab38e
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/error.go
@@ -0,0 +1,215 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rpctypes
+
+import (
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+// server-side error
+var (
+ ErrGRPCEmptyKey = status.New(codes.InvalidArgument, "etcdserver: key is not provided").Err()
+ ErrGRPCKeyNotFound = status.New(codes.InvalidArgument, "etcdserver: key not found").Err()
+ ErrGRPCValueProvided = status.New(codes.InvalidArgument, "etcdserver: value is provided").Err()
+ ErrGRPCLeaseProvided = status.New(codes.InvalidArgument, "etcdserver: lease is provided").Err()
+ ErrGRPCTooManyOps = status.New(codes.InvalidArgument, "etcdserver: too many operations in txn request").Err()
+ ErrGRPCDuplicateKey = status.New(codes.InvalidArgument, "etcdserver: duplicate key given in txn request").Err()
+ ErrGRPCCompacted = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted").Err()
+ ErrGRPCFutureRev = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision").Err()
+ ErrGRPCNoSpace = status.New(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded").Err()
+
+ ErrGRPCLeaseNotFound = status.New(codes.NotFound, "etcdserver: requested lease not found").Err()
+ ErrGRPCLeaseExist = status.New(codes.FailedPrecondition, "etcdserver: lease already exists").Err()
+ ErrGRPCLeaseTTLTooLarge = status.New(codes.OutOfRange, "etcdserver: too large lease TTL").Err()
+
+ ErrGRPCMemberExist = status.New(codes.FailedPrecondition, "etcdserver: member ID already exist").Err()
+ ErrGRPCPeerURLExist = status.New(codes.FailedPrecondition, "etcdserver: Peer URLs already exists").Err()
+ ErrGRPCMemberNotEnoughStarted = status.New(codes.FailedPrecondition, "etcdserver: re-configuration failed due to not enough started members").Err()
+ ErrGRPCMemberBadURLs = status.New(codes.InvalidArgument, "etcdserver: given member URLs are invalid").Err()
+ ErrGRPCMemberNotFound = status.New(codes.NotFound, "etcdserver: member not found").Err()
+
+ ErrGRPCRequestTooLarge = status.New(codes.InvalidArgument, "etcdserver: request is too large").Err()
+ ErrGRPCRequestTooManyRequests = status.New(codes.ResourceExhausted, "etcdserver: too many requests").Err()
+
+ ErrGRPCRootUserNotExist = status.New(codes.FailedPrecondition, "etcdserver: root user does not exist").Err()
+ ErrGRPCRootRoleNotExist = status.New(codes.FailedPrecondition, "etcdserver: root user does not have root role").Err()
+ ErrGRPCUserAlreadyExist = status.New(codes.FailedPrecondition, "etcdserver: user name already exists").Err()
+ ErrGRPCUserEmpty = status.New(codes.InvalidArgument, "etcdserver: user name is empty").Err()
+ ErrGRPCUserNotFound = status.New(codes.FailedPrecondition, "etcdserver: user name not found").Err()
+ ErrGRPCRoleAlreadyExist = status.New(codes.FailedPrecondition, "etcdserver: role name already exists").Err()
+ ErrGRPCRoleNotFound = status.New(codes.FailedPrecondition, "etcdserver: role name not found").Err()
+ ErrGRPCAuthFailed = status.New(codes.InvalidArgument, "etcdserver: authentication failed, invalid user ID or password").Err()
+ ErrGRPCPermissionDenied = status.New(codes.PermissionDenied, "etcdserver: permission denied").Err()
+ ErrGRPCRoleNotGranted = status.New(codes.FailedPrecondition, "etcdserver: role is not granted to the user").Err()
+ ErrGRPCPermissionNotGranted = status.New(codes.FailedPrecondition, "etcdserver: permission is not granted to the role").Err()
+ ErrGRPCAuthNotEnabled = status.New(codes.FailedPrecondition, "etcdserver: authentication is not enabled").Err()
+ ErrGRPCInvalidAuthToken = status.New(codes.Unauthenticated, "etcdserver: invalid auth token").Err()
+ ErrGRPCInvalidAuthMgmt = status.New(codes.InvalidArgument, "etcdserver: invalid auth management").Err()
+
+ ErrGRPCNoLeader = status.New(codes.Unavailable, "etcdserver: no leader").Err()
+ ErrGRPCNotLeader = status.New(codes.FailedPrecondition, "etcdserver: not leader").Err()
+ ErrGRPCNotCapable = status.New(codes.Unavailable, "etcdserver: not capable").Err()
+ ErrGRPCStopped = status.New(codes.Unavailable, "etcdserver: server stopped").Err()
+ ErrGRPCTimeout = status.New(codes.Unavailable, "etcdserver: request timed out").Err()
+ ErrGRPCTimeoutDueToLeaderFail = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to previous leader failure").Err()
+ ErrGRPCTimeoutDueToConnectionLost = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to connection lost").Err()
+ ErrGRPCUnhealthy = status.New(codes.Unavailable, "etcdserver: unhealthy cluster").Err()
+ ErrGRPCCorrupt = status.New(codes.DataLoss, "etcdserver: corrupt cluster").Err()
+
+ errStringToError = map[string]error{
+ ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey,
+ ErrorDesc(ErrGRPCKeyNotFound): ErrGRPCKeyNotFound,
+ ErrorDesc(ErrGRPCValueProvided): ErrGRPCValueProvided,
+ ErrorDesc(ErrGRPCLeaseProvided): ErrGRPCLeaseProvided,
+
+ ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps,
+ ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey,
+ ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted,
+ ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev,
+ ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace,
+
+ ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound,
+ ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist,
+ ErrorDesc(ErrGRPCLeaseTTLTooLarge): ErrGRPCLeaseTTLTooLarge,
+
+ ErrorDesc(ErrGRPCMemberExist): ErrGRPCMemberExist,
+ ErrorDesc(ErrGRPCPeerURLExist): ErrGRPCPeerURLExist,
+ ErrorDesc(ErrGRPCMemberNotEnoughStarted): ErrGRPCMemberNotEnoughStarted,
+ ErrorDesc(ErrGRPCMemberBadURLs): ErrGRPCMemberBadURLs,
+ ErrorDesc(ErrGRPCMemberNotFound): ErrGRPCMemberNotFound,
+
+ ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge,
+ ErrorDesc(ErrGRPCRequestTooManyRequests): ErrGRPCRequestTooManyRequests,
+
+ ErrorDesc(ErrGRPCRootUserNotExist): ErrGRPCRootUserNotExist,
+ ErrorDesc(ErrGRPCRootRoleNotExist): ErrGRPCRootRoleNotExist,
+ ErrorDesc(ErrGRPCUserAlreadyExist): ErrGRPCUserAlreadyExist,
+ ErrorDesc(ErrGRPCUserEmpty): ErrGRPCUserEmpty,
+ ErrorDesc(ErrGRPCUserNotFound): ErrGRPCUserNotFound,
+ ErrorDesc(ErrGRPCRoleAlreadyExist): ErrGRPCRoleAlreadyExist,
+ ErrorDesc(ErrGRPCRoleNotFound): ErrGRPCRoleNotFound,
+ ErrorDesc(ErrGRPCAuthFailed): ErrGRPCAuthFailed,
+ ErrorDesc(ErrGRPCPermissionDenied): ErrGRPCPermissionDenied,
+ ErrorDesc(ErrGRPCRoleNotGranted): ErrGRPCRoleNotGranted,
+ ErrorDesc(ErrGRPCPermissionNotGranted): ErrGRPCPermissionNotGranted,
+ ErrorDesc(ErrGRPCAuthNotEnabled): ErrGRPCAuthNotEnabled,
+ ErrorDesc(ErrGRPCInvalidAuthToken): ErrGRPCInvalidAuthToken,
+ ErrorDesc(ErrGRPCInvalidAuthMgmt): ErrGRPCInvalidAuthMgmt,
+
+ ErrorDesc(ErrGRPCNoLeader): ErrGRPCNoLeader,
+ ErrorDesc(ErrGRPCNotLeader): ErrGRPCNotLeader,
+ ErrorDesc(ErrGRPCNotCapable): ErrGRPCNotCapable,
+ ErrorDesc(ErrGRPCStopped): ErrGRPCStopped,
+ ErrorDesc(ErrGRPCTimeout): ErrGRPCTimeout,
+ ErrorDesc(ErrGRPCTimeoutDueToLeaderFail): ErrGRPCTimeoutDueToLeaderFail,
+ ErrorDesc(ErrGRPCTimeoutDueToConnectionLost): ErrGRPCTimeoutDueToConnectionLost,
+ ErrorDesc(ErrGRPCUnhealthy): ErrGRPCUnhealthy,
+ ErrorDesc(ErrGRPCCorrupt): ErrGRPCCorrupt,
+ }
+)
+
+// client-side error
+var (
+ ErrEmptyKey = Error(ErrGRPCEmptyKey)
+ ErrKeyNotFound = Error(ErrGRPCKeyNotFound)
+ ErrValueProvided = Error(ErrGRPCValueProvided)
+ ErrLeaseProvided = Error(ErrGRPCLeaseProvided)
+ ErrTooManyOps = Error(ErrGRPCTooManyOps)
+ ErrDuplicateKey = Error(ErrGRPCDuplicateKey)
+ ErrCompacted = Error(ErrGRPCCompacted)
+ ErrFutureRev = Error(ErrGRPCFutureRev)
+ ErrNoSpace = Error(ErrGRPCNoSpace)
+
+ ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound)
+ ErrLeaseExist = Error(ErrGRPCLeaseExist)
+ ErrLeaseTTLTooLarge = Error(ErrGRPCLeaseTTLTooLarge)
+
+ ErrMemberExist = Error(ErrGRPCMemberExist)
+ ErrPeerURLExist = Error(ErrGRPCPeerURLExist)
+ ErrMemberNotEnoughStarted = Error(ErrGRPCMemberNotEnoughStarted)
+ ErrMemberBadURLs = Error(ErrGRPCMemberBadURLs)
+ ErrMemberNotFound = Error(ErrGRPCMemberNotFound)
+
+ ErrRequestTooLarge = Error(ErrGRPCRequestTooLarge)
+ ErrTooManyRequests = Error(ErrGRPCRequestTooManyRequests)
+
+ ErrRootUserNotExist = Error(ErrGRPCRootUserNotExist)
+ ErrRootRoleNotExist = Error(ErrGRPCRootRoleNotExist)
+ ErrUserAlreadyExist = Error(ErrGRPCUserAlreadyExist)
+ ErrUserEmpty = Error(ErrGRPCUserEmpty)
+ ErrUserNotFound = Error(ErrGRPCUserNotFound)
+ ErrRoleAlreadyExist = Error(ErrGRPCRoleAlreadyExist)
+ ErrRoleNotFound = Error(ErrGRPCRoleNotFound)
+ ErrAuthFailed = Error(ErrGRPCAuthFailed)
+ ErrPermissionDenied = Error(ErrGRPCPermissionDenied)
+ ErrRoleNotGranted = Error(ErrGRPCRoleNotGranted)
+ ErrPermissionNotGranted = Error(ErrGRPCPermissionNotGranted)
+ ErrAuthNotEnabled = Error(ErrGRPCAuthNotEnabled)
+ ErrInvalidAuthToken = Error(ErrGRPCInvalidAuthToken)
+ ErrInvalidAuthMgmt = Error(ErrGRPCInvalidAuthMgmt)
+
+ ErrNoLeader = Error(ErrGRPCNoLeader)
+ ErrNotLeader = Error(ErrGRPCNotLeader)
+ ErrNotCapable = Error(ErrGRPCNotCapable)
+ ErrStopped = Error(ErrGRPCStopped)
+ ErrTimeout = Error(ErrGRPCTimeout)
+ ErrTimeoutDueToLeaderFail = Error(ErrGRPCTimeoutDueToLeaderFail)
+ ErrTimeoutDueToConnectionLost = Error(ErrGRPCTimeoutDueToConnectionLost)
+ ErrUnhealthy = Error(ErrGRPCUnhealthy)
+ ErrCorrupt = Error(ErrGRPCCorrupt)
+)
+
+// EtcdError defines gRPC server errors.
+// (https://github.com/grpc/grpc-go/blob/master/rpc_util.go#L319-L323)
+type EtcdError struct {
+ code codes.Code
+ desc string
+}
+
+// Code returns grpc/codes.Code.
+// TODO: define clientv3/codes.Code.
+func (e EtcdError) Code() codes.Code {
+ return e.code
+}
+
+func (e EtcdError) Error() string {
+ return e.desc
+}
+
+func Error(err error) error {
+ if err == nil {
+ return nil
+ }
+ verr, ok := errStringToError[ErrorDesc(err)]
+ if !ok { // not gRPC error
+ return err
+ }
+ ev, ok := status.FromError(verr)
+ var desc string
+ if ok {
+ desc = ev.Message()
+ } else {
+ desc = verr.Error()
+ }
+ return EtcdError{code: ev.Code(), desc: desc}
+}
+
+func ErrorDesc(err error) string {
+ if s, ok := status.FromError(err); ok {
+ return s.Message()
+ }
+ return err.Error()
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/md.go b/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/md.go
new file mode 100644
index 00000000..5c590e1a
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes/md.go
@@ -0,0 +1,20 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rpctypes
+
+var (
+ MetadataRequireLeaderKey = "hasleader"
+ MetadataHasLeader = "true"
+)
diff --git a/vendor/github.com/coreos/etcd/etcdserver/apply.go b/vendor/github.com/coreos/etcd/etcdserver/apply.go
new file mode 100644
index 00000000..93e78e39
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/apply.go
@@ -0,0 +1,972 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "bytes"
+ "context"
+ "sort"
+ "time"
+
+ "github.com/coreos/etcd/auth"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/mvcc"
+ "github.com/coreos/etcd/mvcc/mvccpb"
+ "github.com/coreos/etcd/pkg/types"
+
+ "github.com/gogo/protobuf/proto"
+)
+
+const (
+ warnApplyDuration = 100 * time.Millisecond
+)
+
+type applyResult struct {
+ resp proto.Message
+ err error
+ // physc signals the physical effect of the request has completed in addition
+ // to being logically reflected by the node. Currently only used for
+ // Compaction requests.
+ physc <-chan struct{}
+}
+
+// applierV3 is the interface for processing V3 raft messages
+type applierV3 interface {
+ Apply(r *pb.InternalRaftRequest) *applyResult
+
+ Put(txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, error)
+ Range(txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error)
+ DeleteRange(txn mvcc.TxnWrite, dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error)
+ Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error)
+ Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, error)
+
+ LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error)
+ LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error)
+
+ Alarm(*pb.AlarmRequest) (*pb.AlarmResponse, error)
+
+ Authenticate(r *pb.InternalAuthenticateRequest) (*pb.AuthenticateResponse, error)
+
+ AuthEnable() (*pb.AuthEnableResponse, error)
+ AuthDisable() (*pb.AuthDisableResponse, error)
+
+ UserAdd(ua *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error)
+ UserDelete(ua *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error)
+ UserChangePassword(ua *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error)
+ UserGrantRole(ua *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error)
+ UserGet(ua *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error)
+ UserRevokeRole(ua *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error)
+ RoleAdd(ua *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
+ RoleGrantPermission(ua *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error)
+ RoleGet(ua *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error)
+ RoleRevokePermission(ua *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error)
+ RoleDelete(ua *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error)
+ UserList(ua *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error)
+ RoleList(ua *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error)
+}
+
+type checkReqFunc func(mvcc.ReadView, *pb.RequestOp) error
+
+type applierV3backend struct {
+ s *EtcdServer
+
+ checkPut checkReqFunc
+ checkRange checkReqFunc
+}
+
+func (s *EtcdServer) newApplierV3Backend() applierV3 {
+ base := &applierV3backend{s: s}
+ base.checkPut = func(rv mvcc.ReadView, req *pb.RequestOp) error {
+ return base.checkRequestPut(rv, req)
+ }
+ base.checkRange = func(rv mvcc.ReadView, req *pb.RequestOp) error {
+ return base.checkRequestRange(rv, req)
+ }
+ return base
+}
+
+func (s *EtcdServer) newApplierV3() applierV3 {
+ return newAuthApplierV3(
+ s.AuthStore(),
+ newQuotaApplierV3(s, s.newApplierV3Backend()),
+ s.lessor,
+ )
+}
+
+func (a *applierV3backend) Apply(r *pb.InternalRaftRequest) *applyResult {
+ ar := &applyResult{}
+ defer func(start time.Time) {
+ warnOfExpensiveRequest(start, &pb.InternalRaftStringer{Request: r}, ar.resp, ar.err)
+ }(time.Now())
+
+ // call into a.s.applyV3.F instead of a.F so upper appliers can check individual calls
+ switch {
+ case r.Range != nil:
+ ar.resp, ar.err = a.s.applyV3.Range(nil, r.Range)
+ case r.Put != nil:
+ ar.resp, ar.err = a.s.applyV3.Put(nil, r.Put)
+ case r.DeleteRange != nil:
+ ar.resp, ar.err = a.s.applyV3.DeleteRange(nil, r.DeleteRange)
+ case r.Txn != nil:
+ ar.resp, ar.err = a.s.applyV3.Txn(r.Txn)
+ case r.Compaction != nil:
+ ar.resp, ar.physc, ar.err = a.s.applyV3.Compaction(r.Compaction)
+ case r.LeaseGrant != nil:
+ ar.resp, ar.err = a.s.applyV3.LeaseGrant(r.LeaseGrant)
+ case r.LeaseRevoke != nil:
+ ar.resp, ar.err = a.s.applyV3.LeaseRevoke(r.LeaseRevoke)
+ case r.Alarm != nil:
+ ar.resp, ar.err = a.s.applyV3.Alarm(r.Alarm)
+ case r.Authenticate != nil:
+ ar.resp, ar.err = a.s.applyV3.Authenticate(r.Authenticate)
+ case r.AuthEnable != nil:
+ ar.resp, ar.err = a.s.applyV3.AuthEnable()
+ case r.AuthDisable != nil:
+ ar.resp, ar.err = a.s.applyV3.AuthDisable()
+ case r.AuthUserAdd != nil:
+ ar.resp, ar.err = a.s.applyV3.UserAdd(r.AuthUserAdd)
+ case r.AuthUserDelete != nil:
+ ar.resp, ar.err = a.s.applyV3.UserDelete(r.AuthUserDelete)
+ case r.AuthUserChangePassword != nil:
+ ar.resp, ar.err = a.s.applyV3.UserChangePassword(r.AuthUserChangePassword)
+ case r.AuthUserGrantRole != nil:
+ ar.resp, ar.err = a.s.applyV3.UserGrantRole(r.AuthUserGrantRole)
+ case r.AuthUserGet != nil:
+ ar.resp, ar.err = a.s.applyV3.UserGet(r.AuthUserGet)
+ case r.AuthUserRevokeRole != nil:
+ ar.resp, ar.err = a.s.applyV3.UserRevokeRole(r.AuthUserRevokeRole)
+ case r.AuthRoleAdd != nil:
+ ar.resp, ar.err = a.s.applyV3.RoleAdd(r.AuthRoleAdd)
+ case r.AuthRoleGrantPermission != nil:
+ ar.resp, ar.err = a.s.applyV3.RoleGrantPermission(r.AuthRoleGrantPermission)
+ case r.AuthRoleGet != nil:
+ ar.resp, ar.err = a.s.applyV3.RoleGet(r.AuthRoleGet)
+ case r.AuthRoleRevokePermission != nil:
+ ar.resp, ar.err = a.s.applyV3.RoleRevokePermission(r.AuthRoleRevokePermission)
+ case r.AuthRoleDelete != nil:
+ ar.resp, ar.err = a.s.applyV3.RoleDelete(r.AuthRoleDelete)
+ case r.AuthUserList != nil:
+ ar.resp, ar.err = a.s.applyV3.UserList(r.AuthUserList)
+ case r.AuthRoleList != nil:
+ ar.resp, ar.err = a.s.applyV3.RoleList(r.AuthRoleList)
+ default:
+ panic("not implemented")
+ }
+ return ar
+}
+
+func (a *applierV3backend) Put(txn mvcc.TxnWrite, p *pb.PutRequest) (resp *pb.PutResponse, err error) {
+ resp = &pb.PutResponse{}
+ resp.Header = &pb.ResponseHeader{}
+
+ val, leaseID := p.Value, lease.LeaseID(p.Lease)
+ if txn == nil {
+ if leaseID != lease.NoLease {
+ if l := a.s.lessor.Lookup(leaseID); l == nil {
+ return nil, lease.ErrLeaseNotFound
+ }
+ }
+ txn = a.s.KV().Write()
+ defer txn.End()
+ }
+
+ var rr *mvcc.RangeResult
+ if p.IgnoreValue || p.IgnoreLease || p.PrevKv {
+ rr, err = txn.Range(p.Key, nil, mvcc.RangeOptions{})
+ if err != nil {
+ return nil, err
+ }
+ }
+ if p.IgnoreValue || p.IgnoreLease {
+ if rr == nil || len(rr.KVs) == 0 {
+ // ignore_{lease,value} flag expects previous key-value pair
+ return nil, ErrKeyNotFound
+ }
+ }
+ if p.IgnoreValue {
+ val = rr.KVs[0].Value
+ }
+ if p.IgnoreLease {
+ leaseID = lease.LeaseID(rr.KVs[0].Lease)
+ }
+ if p.PrevKv {
+ if rr != nil && len(rr.KVs) != 0 {
+ resp.PrevKv = &rr.KVs[0]
+ }
+ }
+
+ resp.Header.Revision = txn.Put(p.Key, val, leaseID)
+ return resp, nil
+}
+
+func (a *applierV3backend) DeleteRange(txn mvcc.TxnWrite, dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
+ resp := &pb.DeleteRangeResponse{}
+ resp.Header = &pb.ResponseHeader{}
+ end := mkGteRange(dr.RangeEnd)
+
+ if txn == nil {
+ txn = a.s.kv.Write()
+ defer txn.End()
+ }
+
+ if dr.PrevKv {
+ rr, err := txn.Range(dr.Key, end, mvcc.RangeOptions{})
+ if err != nil {
+ return nil, err
+ }
+ if rr != nil {
+ resp.PrevKvs = make([]*mvccpb.KeyValue, len(rr.KVs))
+ for i := range rr.KVs {
+ resp.PrevKvs[i] = &rr.KVs[i]
+ }
+ }
+ }
+
+ resp.Deleted, resp.Header.Revision = txn.DeleteRange(dr.Key, end)
+ return resp, nil
+}
+
+func (a *applierV3backend) Range(txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error) {
+ resp := &pb.RangeResponse{}
+ resp.Header = &pb.ResponseHeader{}
+
+ if txn == nil {
+ txn = a.s.kv.Read()
+ defer txn.End()
+ }
+
+ limit := r.Limit
+ if r.SortOrder != pb.RangeRequest_NONE ||
+ r.MinModRevision != 0 || r.MaxModRevision != 0 ||
+ r.MinCreateRevision != 0 || r.MaxCreateRevision != 0 {
+ // fetch everything; sort and truncate afterwards
+ limit = 0
+ }
+ if limit > 0 {
+ // fetch one extra for 'more' flag
+ limit = limit + 1
+ }
+
+ ro := mvcc.RangeOptions{
+ Limit: limit,
+ Rev: r.Revision,
+ Count: r.CountOnly,
+ }
+
+ rr, err := txn.Range(r.Key, mkGteRange(r.RangeEnd), ro)
+ if err != nil {
+ return nil, err
+ }
+
+ if r.MaxModRevision != 0 {
+ f := func(kv *mvccpb.KeyValue) bool { return kv.ModRevision > r.MaxModRevision }
+ pruneKVs(rr, f)
+ }
+ if r.MinModRevision != 0 {
+ f := func(kv *mvccpb.KeyValue) bool { return kv.ModRevision < r.MinModRevision }
+ pruneKVs(rr, f)
+ }
+ if r.MaxCreateRevision != 0 {
+ f := func(kv *mvccpb.KeyValue) bool { return kv.CreateRevision > r.MaxCreateRevision }
+ pruneKVs(rr, f)
+ }
+ if r.MinCreateRevision != 0 {
+ f := func(kv *mvccpb.KeyValue) bool { return kv.CreateRevision < r.MinCreateRevision }
+ pruneKVs(rr, f)
+ }
+
+ sortOrder := r.SortOrder
+ if r.SortTarget != pb.RangeRequest_KEY && sortOrder == pb.RangeRequest_NONE {
+ // Since current mvcc.Range implementation returns results
+ // sorted by keys in lexiographically ascending order,
+ // sort ASCEND by default only when target is not 'KEY'
+ sortOrder = pb.RangeRequest_ASCEND
+ }
+ if sortOrder != pb.RangeRequest_NONE {
+ var sorter sort.Interface
+ switch {
+ case r.SortTarget == pb.RangeRequest_KEY:
+ sorter = &kvSortByKey{&kvSort{rr.KVs}}
+ case r.SortTarget == pb.RangeRequest_VERSION:
+ sorter = &kvSortByVersion{&kvSort{rr.KVs}}
+ case r.SortTarget == pb.RangeRequest_CREATE:
+ sorter = &kvSortByCreate{&kvSort{rr.KVs}}
+ case r.SortTarget == pb.RangeRequest_MOD:
+ sorter = &kvSortByMod{&kvSort{rr.KVs}}
+ case r.SortTarget == pb.RangeRequest_VALUE:
+ sorter = &kvSortByValue{&kvSort{rr.KVs}}
+ }
+ switch {
+ case sortOrder == pb.RangeRequest_ASCEND:
+ sort.Sort(sorter)
+ case sortOrder == pb.RangeRequest_DESCEND:
+ sort.Sort(sort.Reverse(sorter))
+ }
+ }
+
+ if r.Limit > 0 && len(rr.KVs) > int(r.Limit) {
+ rr.KVs = rr.KVs[:r.Limit]
+ resp.More = true
+ }
+
+ resp.Header.Revision = rr.Rev
+ resp.Count = int64(rr.Count)
+ resp.Kvs = make([]*mvccpb.KeyValue, len(rr.KVs))
+ for i := range rr.KVs {
+ if r.KeysOnly {
+ rr.KVs[i].Value = nil
+ }
+ resp.Kvs[i] = &rr.KVs[i]
+ }
+ return resp, nil
+}
+
+func (a *applierV3backend) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) {
+ isWrite := !isTxnReadonly(rt)
+ txn := mvcc.NewReadOnlyTxnWrite(a.s.KV().Read())
+
+ txnPath := compareToPath(txn, rt)
+ if isWrite {
+ if _, err := checkRequests(txn, rt, txnPath, a.checkPut); err != nil {
+ txn.End()
+ return nil, err
+ }
+ }
+ if _, err := checkRequests(txn, rt, txnPath, a.checkRange); err != nil {
+ txn.End()
+ return nil, err
+ }
+
+ txnResp, _ := newTxnResp(rt, txnPath)
+
+ // When executing mutable txn ops, etcd must hold the txn lock so
+ // readers do not see any intermediate results. Since writes are
+ // serialized on the raft loop, the revision in the read view will
+ // be the revision of the write txn.
+ if isWrite {
+ txn.End()
+ txn = a.s.KV().Write()
+ }
+ a.applyTxn(txn, rt, txnPath, txnResp)
+ rev := txn.Rev()
+ if len(txn.Changes()) != 0 {
+ rev++
+ }
+ txn.End()
+
+ txnResp.Header.Revision = rev
+ return txnResp, nil
+}
+
+// newTxnResp allocates a txn response for a txn request given a path.
+func newTxnResp(rt *pb.TxnRequest, txnPath []bool) (txnResp *pb.TxnResponse, txnCount int) {
+ reqs := rt.Success
+ if !txnPath[0] {
+ reqs = rt.Failure
+ }
+ resps := make([]*pb.ResponseOp, len(reqs))
+ txnResp = &pb.TxnResponse{
+ Responses: resps,
+ Succeeded: txnPath[0],
+ Header: &pb.ResponseHeader{},
+ }
+ for i, req := range reqs {
+ switch tv := req.Request.(type) {
+ case *pb.RequestOp_RequestRange:
+ resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseRange{}}
+ case *pb.RequestOp_RequestPut:
+ resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponsePut{}}
+ case *pb.RequestOp_RequestDeleteRange:
+ resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseDeleteRange{}}
+ case *pb.RequestOp_RequestTxn:
+ resp, txns := newTxnResp(tv.RequestTxn, txnPath[1:])
+ resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseTxn{ResponseTxn: resp}}
+ txnPath = txnPath[1+txns:]
+ txnCount += txns + 1
+ default:
+ }
+ }
+ return txnResp, txnCount
+}
+
+func compareToPath(rv mvcc.ReadView, rt *pb.TxnRequest) []bool {
+ txnPath := make([]bool, 1)
+ ops := rt.Success
+ if txnPath[0] = applyCompares(rv, rt.Compare); !txnPath[0] {
+ ops = rt.Failure
+ }
+ for _, op := range ops {
+ tv, ok := op.Request.(*pb.RequestOp_RequestTxn)
+ if !ok || tv.RequestTxn == nil {
+ continue
+ }
+ txnPath = append(txnPath, compareToPath(rv, tv.RequestTxn)...)
+ }
+ return txnPath
+}
+
+func applyCompares(rv mvcc.ReadView, cmps []*pb.Compare) bool {
+ for _, c := range cmps {
+ if !applyCompare(rv, c) {
+ return false
+ }
+ }
+ return true
+}
+
+// applyCompare applies the compare request.
+// If the comparison succeeds, it returns true. Otherwise, returns false.
+func applyCompare(rv mvcc.ReadView, c *pb.Compare) bool {
+ // TODO: possible optimizations
+ // * chunk reads for large ranges to conserve memory
+ // * rewrite rules for common patterns:
+ // ex. "[a, b) createrev > 0" => "limit 1 /\ kvs > 0"
+ // * caching
+ rr, err := rv.Range(c.Key, mkGteRange(c.RangeEnd), mvcc.RangeOptions{})
+ if err != nil {
+ return false
+ }
+ if len(rr.KVs) == 0 {
+ if c.Target == pb.Compare_VALUE {
+ // Always fail if comparing a value on a key/keys that doesn't exist;
+ // nil == empty string in grpc; no way to represent missing value
+ return false
+ }
+ return compareKV(c, mvccpb.KeyValue{})
+ }
+ for _, kv := range rr.KVs {
+ if !compareKV(c, kv) {
+ return false
+ }
+ }
+ return true
+}
+
+func compareKV(c *pb.Compare, ckv mvccpb.KeyValue) bool {
+ var result int
+ rev := int64(0)
+ switch c.Target {
+ case pb.Compare_VALUE:
+ v := []byte{}
+ if tv, _ := c.TargetUnion.(*pb.Compare_Value); tv != nil {
+ v = tv.Value
+ }
+ result = bytes.Compare(ckv.Value, v)
+ case pb.Compare_CREATE:
+ if tv, _ := c.TargetUnion.(*pb.Compare_CreateRevision); tv != nil {
+ rev = tv.CreateRevision
+ }
+ result = compareInt64(ckv.CreateRevision, rev)
+ case pb.Compare_MOD:
+ if tv, _ := c.TargetUnion.(*pb.Compare_ModRevision); tv != nil {
+ rev = tv.ModRevision
+ }
+ result = compareInt64(ckv.ModRevision, rev)
+ case pb.Compare_VERSION:
+ if tv, _ := c.TargetUnion.(*pb.Compare_Version); tv != nil {
+ rev = tv.Version
+ }
+ result = compareInt64(ckv.Version, rev)
+ case pb.Compare_LEASE:
+ if tv, _ := c.TargetUnion.(*pb.Compare_Lease); tv != nil {
+ rev = tv.Lease
+ }
+ result = compareInt64(ckv.Lease, rev)
+ }
+ switch c.Result {
+ case pb.Compare_EQUAL:
+ return result == 0
+ case pb.Compare_NOT_EQUAL:
+ return result != 0
+ case pb.Compare_GREATER:
+ return result > 0
+ case pb.Compare_LESS:
+ return result < 0
+ }
+ return true
+}
+
+func (a *applierV3backend) applyTxn(txn mvcc.TxnWrite, rt *pb.TxnRequest, txnPath []bool, tresp *pb.TxnResponse) (txns int) {
+ reqs := rt.Success
+ if !txnPath[0] {
+ reqs = rt.Failure
+ }
+ for i, req := range reqs {
+ respi := tresp.Responses[i].Response
+ switch tv := req.Request.(type) {
+ case *pb.RequestOp_RequestRange:
+ resp, err := a.Range(txn, tv.RequestRange)
+ if err != nil {
+ plog.Panicf("unexpected error during txn: %v", err)
+ }
+ respi.(*pb.ResponseOp_ResponseRange).ResponseRange = resp
+ case *pb.RequestOp_RequestPut:
+ resp, err := a.Put(txn, tv.RequestPut)
+ if err != nil {
+ plog.Panicf("unexpected error during txn: %v", err)
+ }
+ respi.(*pb.ResponseOp_ResponsePut).ResponsePut = resp
+ case *pb.RequestOp_RequestDeleteRange:
+ resp, err := a.DeleteRange(txn, tv.RequestDeleteRange)
+ if err != nil {
+ plog.Panicf("unexpected error during txn: %v", err)
+ }
+ respi.(*pb.ResponseOp_ResponseDeleteRange).ResponseDeleteRange = resp
+ case *pb.RequestOp_RequestTxn:
+ resp := respi.(*pb.ResponseOp_ResponseTxn).ResponseTxn
+ applyTxns := a.applyTxn(txn, tv.RequestTxn, txnPath[1:], resp)
+ txns += applyTxns + 1
+ txnPath = txnPath[applyTxns+1:]
+ default:
+ // empty union
+ }
+ }
+ return txns
+}
+
+func (a *applierV3backend) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, error) {
+ resp := &pb.CompactionResponse{}
+ resp.Header = &pb.ResponseHeader{}
+ ch, err := a.s.KV().Compact(compaction.Revision)
+ if err != nil {
+ return nil, ch, err
+ }
+ // get the current revision. which key to get is not important.
+ rr, _ := a.s.KV().Range([]byte("compaction"), nil, mvcc.RangeOptions{})
+ resp.Header.Revision = rr.Rev
+ return resp, ch, err
+}
+
+func (a *applierV3backend) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ l, err := a.s.lessor.Grant(lease.LeaseID(lc.ID), lc.TTL)
+ resp := &pb.LeaseGrantResponse{}
+ if err == nil {
+ resp.ID = int64(l.ID)
+ resp.TTL = l.TTL()
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) {
+ err := a.s.lessor.Revoke(lease.LeaseID(lc.ID))
+ return &pb.LeaseRevokeResponse{Header: newHeader(a.s)}, err
+}
+
+func (a *applierV3backend) Alarm(ar *pb.AlarmRequest) (*pb.AlarmResponse, error) {
+ resp := &pb.AlarmResponse{}
+ oldCount := len(a.s.alarmStore.Get(ar.Alarm))
+
+ switch ar.Action {
+ case pb.AlarmRequest_GET:
+ resp.Alarms = a.s.alarmStore.Get(ar.Alarm)
+ case pb.AlarmRequest_ACTIVATE:
+ m := a.s.alarmStore.Activate(types.ID(ar.MemberID), ar.Alarm)
+ if m == nil {
+ break
+ }
+ resp.Alarms = append(resp.Alarms, m)
+ activated := oldCount == 0 && len(a.s.alarmStore.Get(m.Alarm)) == 1
+ if !activated {
+ break
+ }
+
+ plog.Warningf("alarm %v raised by peer %s", m.Alarm, types.ID(m.MemberID))
+ switch m.Alarm {
+ case pb.AlarmType_CORRUPT:
+ a.s.applyV3 = newApplierV3Corrupt(a)
+ case pb.AlarmType_NOSPACE:
+ a.s.applyV3 = newApplierV3Capped(a)
+ default:
+ plog.Errorf("unimplemented alarm activation (%+v)", m)
+ }
+ case pb.AlarmRequest_DEACTIVATE:
+ m := a.s.alarmStore.Deactivate(types.ID(ar.MemberID), ar.Alarm)
+ if m == nil {
+ break
+ }
+ resp.Alarms = append(resp.Alarms, m)
+ deactivated := oldCount > 0 && len(a.s.alarmStore.Get(ar.Alarm)) == 0
+ if !deactivated {
+ break
+ }
+
+ switch m.Alarm {
+ case pb.AlarmType_NOSPACE, pb.AlarmType_CORRUPT:
+ // TODO: check kv hash before deactivating CORRUPT?
+ plog.Infof("alarm disarmed %+v", ar)
+ a.s.applyV3 = a.s.newApplierV3()
+ default:
+ plog.Errorf("unimplemented alarm deactivation (%+v)", m)
+ }
+ default:
+ return nil, nil
+ }
+ return resp, nil
+}
+
+type applierV3Capped struct {
+ applierV3
+ q backendQuota
+}
+
+// newApplierV3Capped creates an applyV3 that will reject Puts and transactions
+// with Puts so that the number of keys in the store is capped.
+func newApplierV3Capped(base applierV3) applierV3 { return &applierV3Capped{applierV3: base} }
+
+func (a *applierV3Capped) Put(txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, error) {
+ return nil, ErrNoSpace
+}
+
+func (a *applierV3Capped) Txn(r *pb.TxnRequest) (*pb.TxnResponse, error) {
+ if a.q.Cost(r) > 0 {
+ return nil, ErrNoSpace
+ }
+ return a.applierV3.Txn(r)
+}
+
+func (a *applierV3Capped) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ return nil, ErrNoSpace
+}
+
+func (a *applierV3backend) AuthEnable() (*pb.AuthEnableResponse, error) {
+ err := a.s.AuthStore().AuthEnable()
+ if err != nil {
+ return nil, err
+ }
+ return &pb.AuthEnableResponse{Header: newHeader(a.s)}, nil
+}
+
+func (a *applierV3backend) AuthDisable() (*pb.AuthDisableResponse, error) {
+ a.s.AuthStore().AuthDisable()
+ return &pb.AuthDisableResponse{Header: newHeader(a.s)}, nil
+}
+
+func (a *applierV3backend) Authenticate(r *pb.InternalAuthenticateRequest) (*pb.AuthenticateResponse, error) {
+ ctx := context.WithValue(context.WithValue(a.s.ctx, auth.AuthenticateParamIndex{}, a.s.consistIndex.ConsistentIndex()), auth.AuthenticateParamSimpleTokenPrefix{}, r.SimpleToken)
+ resp, err := a.s.AuthStore().Authenticate(ctx, r.Name, r.Password)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
+ resp, err := a.s.AuthStore().UserAdd(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) {
+ resp, err := a.s.AuthStore().UserDelete(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) {
+ resp, err := a.s.AuthStore().UserChangePassword(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) {
+ resp, err := a.s.AuthStore().UserGrantRole(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
+ resp, err := a.s.AuthStore().UserGet(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) {
+ resp, err := a.s.AuthStore().UserRevokeRole(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
+ resp, err := a.s.AuthStore().RoleAdd(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) {
+ resp, err := a.s.AuthStore().RoleGrantPermission(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
+ resp, err := a.s.AuthStore().RoleGet(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) RoleRevokePermission(r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) {
+ resp, err := a.s.AuthStore().RoleRevokePermission(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) {
+ resp, err := a.s.AuthStore().RoleDelete(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) UserList(r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) {
+ resp, err := a.s.AuthStore().UserList(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+func (a *applierV3backend) RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) {
+ resp, err := a.s.AuthStore().RoleList(r)
+ if resp != nil {
+ resp.Header = newHeader(a.s)
+ }
+ return resp, err
+}
+
+type quotaApplierV3 struct {
+ applierV3
+ q Quota
+}
+
+func newQuotaApplierV3(s *EtcdServer, app applierV3) applierV3 {
+ return "aApplierV3{app, NewBackendQuota(s)}
+}
+
+func (a *quotaApplierV3) Put(txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, error) {
+ ok := a.q.Available(p)
+ resp, err := a.applierV3.Put(txn, p)
+ if err == nil && !ok {
+ err = ErrNoSpace
+ }
+ return resp, err
+}
+
+func (a *quotaApplierV3) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) {
+ ok := a.q.Available(rt)
+ resp, err := a.applierV3.Txn(rt)
+ if err == nil && !ok {
+ err = ErrNoSpace
+ }
+ return resp, err
+}
+
+func (a *quotaApplierV3) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ ok := a.q.Available(lc)
+ resp, err := a.applierV3.LeaseGrant(lc)
+ if err == nil && !ok {
+ err = ErrNoSpace
+ }
+ return resp, err
+}
+
+type kvSort struct{ kvs []mvccpb.KeyValue }
+
+func (s *kvSort) Swap(i, j int) {
+ t := s.kvs[i]
+ s.kvs[i] = s.kvs[j]
+ s.kvs[j] = t
+}
+func (s *kvSort) Len() int { return len(s.kvs) }
+
+type kvSortByKey struct{ *kvSort }
+
+func (s *kvSortByKey) Less(i, j int) bool {
+ return bytes.Compare(s.kvs[i].Key, s.kvs[j].Key) < 0
+}
+
+type kvSortByVersion struct{ *kvSort }
+
+func (s *kvSortByVersion) Less(i, j int) bool {
+ return (s.kvs[i].Version - s.kvs[j].Version) < 0
+}
+
+type kvSortByCreate struct{ *kvSort }
+
+func (s *kvSortByCreate) Less(i, j int) bool {
+ return (s.kvs[i].CreateRevision - s.kvs[j].CreateRevision) < 0
+}
+
+type kvSortByMod struct{ *kvSort }
+
+func (s *kvSortByMod) Less(i, j int) bool {
+ return (s.kvs[i].ModRevision - s.kvs[j].ModRevision) < 0
+}
+
+type kvSortByValue struct{ *kvSort }
+
+func (s *kvSortByValue) Less(i, j int) bool {
+ return bytes.Compare(s.kvs[i].Value, s.kvs[j].Value) < 0
+}
+
+func checkRequests(rv mvcc.ReadView, rt *pb.TxnRequest, txnPath []bool, f checkReqFunc) (int, error) {
+ txnCount := 0
+ reqs := rt.Success
+ if !txnPath[0] {
+ reqs = rt.Failure
+ }
+ for _, req := range reqs {
+ if tv, ok := req.Request.(*pb.RequestOp_RequestTxn); ok && tv.RequestTxn != nil {
+ txns, err := checkRequests(rv, tv.RequestTxn, txnPath[1:], f)
+ if err != nil {
+ return 0, err
+ }
+ txnCount += txns + 1
+ txnPath = txnPath[txns+1:]
+ continue
+ }
+ if err := f(rv, req); err != nil {
+ return 0, err
+ }
+ }
+ return txnCount, nil
+}
+
+func (a *applierV3backend) checkRequestPut(rv mvcc.ReadView, reqOp *pb.RequestOp) error {
+ tv, ok := reqOp.Request.(*pb.RequestOp_RequestPut)
+ if !ok || tv.RequestPut == nil {
+ return nil
+ }
+ req := tv.RequestPut
+ if req.IgnoreValue || req.IgnoreLease {
+ // expects previous key-value, error if not exist
+ rr, err := rv.Range(req.Key, nil, mvcc.RangeOptions{})
+ if err != nil {
+ return err
+ }
+ if rr == nil || len(rr.KVs) == 0 {
+ return ErrKeyNotFound
+ }
+ }
+ if lease.LeaseID(req.Lease) != lease.NoLease {
+ if l := a.s.lessor.Lookup(lease.LeaseID(req.Lease)); l == nil {
+ return lease.ErrLeaseNotFound
+ }
+ }
+ return nil
+}
+
+func (a *applierV3backend) checkRequestRange(rv mvcc.ReadView, reqOp *pb.RequestOp) error {
+ tv, ok := reqOp.Request.(*pb.RequestOp_RequestRange)
+ if !ok || tv.RequestRange == nil {
+ return nil
+ }
+ req := tv.RequestRange
+ switch {
+ case req.Revision == 0:
+ return nil
+ case req.Revision > rv.Rev():
+ return mvcc.ErrFutureRev
+ case req.Revision < rv.FirstRev():
+ return mvcc.ErrCompacted
+ }
+ return nil
+}
+
+func compareInt64(a, b int64) int {
+ switch {
+ case a < b:
+ return -1
+ case a > b:
+ return 1
+ default:
+ return 0
+ }
+}
+
+// mkGteRange determines if the range end is a >= range. This works around grpc
+// sending empty byte strings as nil; >= is encoded in the range end as '\0'.
+// If it is a GTE range, then []byte{} is returned to indicate the empty byte
+// string (vs nil being no byte string).
+func mkGteRange(rangeEnd []byte) []byte {
+ if len(rangeEnd) == 1 && rangeEnd[0] == 0 {
+ return []byte{}
+ }
+ return rangeEnd
+}
+
+func noSideEffect(r *pb.InternalRaftRequest) bool {
+ return r.Range != nil || r.AuthUserGet != nil || r.AuthRoleGet != nil
+}
+
+func removeNeedlessRangeReqs(txn *pb.TxnRequest) {
+ f := func(ops []*pb.RequestOp) []*pb.RequestOp {
+ j := 0
+ for i := 0; i < len(ops); i++ {
+ if _, ok := ops[i].Request.(*pb.RequestOp_RequestRange); ok {
+ continue
+ }
+ ops[j] = ops[i]
+ j++
+ }
+
+ return ops[:j]
+ }
+
+ txn.Success = f(txn.Success)
+ txn.Failure = f(txn.Failure)
+}
+
+func pruneKVs(rr *mvcc.RangeResult, isPrunable func(*mvccpb.KeyValue) bool) {
+ j := 0
+ for i := range rr.KVs {
+ rr.KVs[j] = rr.KVs[i]
+ if !isPrunable(&rr.KVs[i]) {
+ j++
+ }
+ }
+ rr.KVs = rr.KVs[:j]
+}
+
+func newHeader(s *EtcdServer) *pb.ResponseHeader {
+ return &pb.ResponseHeader{
+ ClusterId: uint64(s.Cluster().ID()),
+ MemberId: uint64(s.ID()),
+ Revision: s.KV().Rev(),
+ RaftTerm: s.Term(),
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/apply_auth.go b/vendor/github.com/coreos/etcd/etcdserver/apply_auth.go
new file mode 100644
index 00000000..ec939143
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/apply_auth.go
@@ -0,0 +1,245 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "sync"
+
+ "github.com/coreos/etcd/auth"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/mvcc"
+)
+
+type authApplierV3 struct {
+ applierV3
+ as auth.AuthStore
+ lessor lease.Lessor
+
+ // mu serializes Apply so that user isn't corrupted and so that
+ // serialized requests don't leak data from TOCTOU errors
+ mu sync.Mutex
+
+ authInfo auth.AuthInfo
+}
+
+func newAuthApplierV3(as auth.AuthStore, base applierV3, lessor lease.Lessor) *authApplierV3 {
+ return &authApplierV3{applierV3: base, as: as, lessor: lessor}
+}
+
+func (aa *authApplierV3) Apply(r *pb.InternalRaftRequest) *applyResult {
+ aa.mu.Lock()
+ defer aa.mu.Unlock()
+ if r.Header != nil {
+ // backward-compatible with pre-3.0 releases when internalRaftRequest
+ // does not have header field
+ aa.authInfo.Username = r.Header.Username
+ aa.authInfo.Revision = r.Header.AuthRevision
+ }
+ if needAdminPermission(r) {
+ if err := aa.as.IsAdminPermitted(&aa.authInfo); err != nil {
+ aa.authInfo.Username = ""
+ aa.authInfo.Revision = 0
+ return &applyResult{err: err}
+ }
+ }
+ ret := aa.applierV3.Apply(r)
+ aa.authInfo.Username = ""
+ aa.authInfo.Revision = 0
+ return ret
+}
+
+func (aa *authApplierV3) Put(txn mvcc.TxnWrite, r *pb.PutRequest) (*pb.PutResponse, error) {
+ if err := aa.as.IsPutPermitted(&aa.authInfo, r.Key); err != nil {
+ return nil, err
+ }
+
+ if err := aa.checkLeasePuts(lease.LeaseID(r.Lease)); err != nil {
+ // The specified lease is already attached with a key that cannot
+ // be written by this user. It means the user cannot revoke the
+ // lease so attaching the lease to the newly written key should
+ // be forbidden.
+ return nil, err
+ }
+
+ if r.PrevKv {
+ err := aa.as.IsRangePermitted(&aa.authInfo, r.Key, nil)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return aa.applierV3.Put(txn, r)
+}
+
+func (aa *authApplierV3) Range(txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error) {
+ if err := aa.as.IsRangePermitted(&aa.authInfo, r.Key, r.RangeEnd); err != nil {
+ return nil, err
+ }
+ return aa.applierV3.Range(txn, r)
+}
+
+func (aa *authApplierV3) DeleteRange(txn mvcc.TxnWrite, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
+ if err := aa.as.IsDeleteRangePermitted(&aa.authInfo, r.Key, r.RangeEnd); err != nil {
+ return nil, err
+ }
+ if r.PrevKv {
+ err := aa.as.IsRangePermitted(&aa.authInfo, r.Key, r.RangeEnd)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return aa.applierV3.DeleteRange(txn, r)
+}
+
+func checkTxnReqsPermission(as auth.AuthStore, ai *auth.AuthInfo, reqs []*pb.RequestOp) error {
+ for _, requ := range reqs {
+ switch tv := requ.Request.(type) {
+ case *pb.RequestOp_RequestRange:
+ if tv.RequestRange == nil {
+ continue
+ }
+
+ if err := as.IsRangePermitted(ai, tv.RequestRange.Key, tv.RequestRange.RangeEnd); err != nil {
+ return err
+ }
+
+ case *pb.RequestOp_RequestPut:
+ if tv.RequestPut == nil {
+ continue
+ }
+
+ if err := as.IsPutPermitted(ai, tv.RequestPut.Key); err != nil {
+ return err
+ }
+
+ case *pb.RequestOp_RequestDeleteRange:
+ if tv.RequestDeleteRange == nil {
+ continue
+ }
+
+ if tv.RequestDeleteRange.PrevKv {
+ err := as.IsRangePermitted(ai, tv.RequestDeleteRange.Key, tv.RequestDeleteRange.RangeEnd)
+ if err != nil {
+ return err
+ }
+ }
+
+ err := as.IsDeleteRangePermitted(ai, tv.RequestDeleteRange.Key, tv.RequestDeleteRange.RangeEnd)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+func checkTxnAuth(as auth.AuthStore, ai *auth.AuthInfo, rt *pb.TxnRequest) error {
+ for _, c := range rt.Compare {
+ if err := as.IsRangePermitted(ai, c.Key, c.RangeEnd); err != nil {
+ return err
+ }
+ }
+ if err := checkTxnReqsPermission(as, ai, rt.Success); err != nil {
+ return err
+ }
+ if err := checkTxnReqsPermission(as, ai, rt.Failure); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (aa *authApplierV3) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) {
+ if err := checkTxnAuth(aa.as, &aa.authInfo, rt); err != nil {
+ return nil, err
+ }
+ return aa.applierV3.Txn(rt)
+}
+
+func (aa *authApplierV3) LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) {
+ if err := aa.checkLeasePuts(lease.LeaseID(lc.ID)); err != nil {
+ return nil, err
+ }
+ return aa.applierV3.LeaseRevoke(lc)
+}
+
+func (aa *authApplierV3) checkLeasePuts(leaseID lease.LeaseID) error {
+ lease := aa.lessor.Lookup(leaseID)
+ if lease != nil {
+ for _, key := range lease.Keys() {
+ if err := aa.as.IsPutPermitted(&aa.authInfo, []byte(key)); err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+func (aa *authApplierV3) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
+ err := aa.as.IsAdminPermitted(&aa.authInfo)
+ if err != nil && r.Name != aa.authInfo.Username {
+ aa.authInfo.Username = ""
+ aa.authInfo.Revision = 0
+ return &pb.AuthUserGetResponse{}, err
+ }
+
+ return aa.applierV3.UserGet(r)
+}
+
+func (aa *authApplierV3) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
+ err := aa.as.IsAdminPermitted(&aa.authInfo)
+ if err != nil && !aa.as.HasRole(aa.authInfo.Username, r.Role) {
+ aa.authInfo.Username = ""
+ aa.authInfo.Revision = 0
+ return &pb.AuthRoleGetResponse{}, err
+ }
+
+ return aa.applierV3.RoleGet(r)
+}
+
+func needAdminPermission(r *pb.InternalRaftRequest) bool {
+ switch {
+ case r.AuthEnable != nil:
+ return true
+ case r.AuthDisable != nil:
+ return true
+ case r.AuthUserAdd != nil:
+ return true
+ case r.AuthUserDelete != nil:
+ return true
+ case r.AuthUserChangePassword != nil:
+ return true
+ case r.AuthUserGrantRole != nil:
+ return true
+ case r.AuthUserRevokeRole != nil:
+ return true
+ case r.AuthRoleAdd != nil:
+ return true
+ case r.AuthRoleGrantPermission != nil:
+ return true
+ case r.AuthRoleRevokePermission != nil:
+ return true
+ case r.AuthRoleDelete != nil:
+ return true
+ case r.AuthUserList != nil:
+ return true
+ case r.AuthRoleList != nil:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/apply_v2.go b/vendor/github.com/coreos/etcd/etcdserver/apply_v2.go
new file mode 100644
index 00000000..a49b6823
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/apply_v2.go
@@ -0,0 +1,140 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "encoding/json"
+ "path"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/api"
+ "github.com/coreos/etcd/etcdserver/membership"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/store"
+ "github.com/coreos/go-semver/semver"
+)
+
+// ApplierV2 is the interface for processing V2 raft messages
+type ApplierV2 interface {
+ Delete(r *RequestV2) Response
+ Post(r *RequestV2) Response
+ Put(r *RequestV2) Response
+ QGet(r *RequestV2) Response
+ Sync(r *RequestV2) Response
+}
+
+func NewApplierV2(s store.Store, c *membership.RaftCluster) ApplierV2 {
+ return &applierV2store{store: s, cluster: c}
+}
+
+type applierV2store struct {
+ store store.Store
+ cluster *membership.RaftCluster
+}
+
+func (a *applierV2store) Delete(r *RequestV2) Response {
+ switch {
+ case r.PrevIndex > 0 || r.PrevValue != "":
+ return toResponse(a.store.CompareAndDelete(r.Path, r.PrevValue, r.PrevIndex))
+ default:
+ return toResponse(a.store.Delete(r.Path, r.Dir, r.Recursive))
+ }
+}
+
+func (a *applierV2store) Post(r *RequestV2) Response {
+ return toResponse(a.store.Create(r.Path, r.Dir, r.Val, true, r.TTLOptions()))
+}
+
+func (a *applierV2store) Put(r *RequestV2) Response {
+ ttlOptions := r.TTLOptions()
+ exists, existsSet := pbutil.GetBool(r.PrevExist)
+ switch {
+ case existsSet:
+ if exists {
+ if r.PrevIndex == 0 && r.PrevValue == "" {
+ return toResponse(a.store.Update(r.Path, r.Val, ttlOptions))
+ }
+ return toResponse(a.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions))
+ }
+ return toResponse(a.store.Create(r.Path, r.Dir, r.Val, false, ttlOptions))
+ case r.PrevIndex > 0 || r.PrevValue != "":
+ return toResponse(a.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions))
+ default:
+ if storeMemberAttributeRegexp.MatchString(r.Path) {
+ id := membership.MustParseMemberIDFromKey(path.Dir(r.Path))
+ var attr membership.Attributes
+ if err := json.Unmarshal([]byte(r.Val), &attr); err != nil {
+ plog.Panicf("unmarshal %s should never fail: %v", r.Val, err)
+ }
+ if a.cluster != nil {
+ a.cluster.UpdateAttributes(id, attr)
+ }
+ // return an empty response since there is no consumer.
+ return Response{}
+ }
+ if r.Path == membership.StoreClusterVersionKey() {
+ if a.cluster != nil {
+ a.cluster.SetVersion(semver.Must(semver.NewVersion(r.Val)), api.UpdateCapability)
+ }
+ // return an empty response since there is no consumer.
+ return Response{}
+ }
+ return toResponse(a.store.Set(r.Path, r.Dir, r.Val, ttlOptions))
+ }
+}
+
+func (a *applierV2store) QGet(r *RequestV2) Response {
+ return toResponse(a.store.Get(r.Path, r.Recursive, r.Sorted))
+}
+
+func (a *applierV2store) Sync(r *RequestV2) Response {
+ a.store.DeleteExpiredKeys(time.Unix(0, r.Time))
+ return Response{}
+}
+
+// applyV2Request interprets r as a call to store.X and returns a Response interpreted
+// from store.Event
+func (s *EtcdServer) applyV2Request(r *RequestV2) Response {
+ defer warnOfExpensiveRequest(time.Now(), r, nil, nil)
+
+ switch r.Method {
+ case "POST":
+ return s.applyV2.Post(r)
+ case "PUT":
+ return s.applyV2.Put(r)
+ case "DELETE":
+ return s.applyV2.Delete(r)
+ case "QGET":
+ return s.applyV2.QGet(r)
+ case "SYNC":
+ return s.applyV2.Sync(r)
+ default:
+ // This should never be reached, but just in case:
+ return Response{Err: ErrUnknownMethod}
+ }
+}
+
+func (r *RequestV2) TTLOptions() store.TTLOptionSet {
+ refresh, _ := pbutil.GetBool(r.Refresh)
+ ttlOptions := store.TTLOptionSet{Refresh: refresh}
+ if r.Expiration != 0 {
+ ttlOptions.ExpireTime = time.Unix(0, r.Expiration)
+ }
+ return ttlOptions
+}
+
+func toResponse(ev *store.Event, err error) Response {
+ return Response{Event: ev, Err: err}
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/backend.go b/vendor/github.com/coreos/etcd/etcdserver/backend.go
new file mode 100644
index 00000000..647773d4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/backend.go
@@ -0,0 +1,81 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/mvcc"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/snap"
+)
+
+func newBackend(cfg ServerConfig) backend.Backend {
+ bcfg := backend.DefaultBackendConfig()
+ bcfg.Path = cfg.backendPath()
+ if cfg.QuotaBackendBytes > 0 && cfg.QuotaBackendBytes != DefaultQuotaBytes {
+ // permit 10% excess over quota for disarm
+ bcfg.MmapSize = uint64(cfg.QuotaBackendBytes + cfg.QuotaBackendBytes/10)
+ }
+ return backend.New(bcfg)
+}
+
+// openSnapshotBackend renames a snapshot db to the current etcd db and opens it.
+func openSnapshotBackend(cfg ServerConfig, ss *snap.Snapshotter, snapshot raftpb.Snapshot) (backend.Backend, error) {
+ snapPath, err := ss.DBFilePath(snapshot.Metadata.Index)
+ if err != nil {
+ return nil, fmt.Errorf("database snapshot file path error: %v", err)
+ }
+ if err := os.Rename(snapPath, cfg.backendPath()); err != nil {
+ return nil, fmt.Errorf("rename snapshot file error: %v", err)
+ }
+ return openBackend(cfg), nil
+}
+
+// openBackend returns a backend using the current etcd db.
+func openBackend(cfg ServerConfig) backend.Backend {
+ fn := cfg.backendPath()
+ beOpened := make(chan backend.Backend)
+ go func() {
+ beOpened <- newBackend(cfg)
+ }()
+ select {
+ case be := <-beOpened:
+ return be
+ case <-time.After(10 * time.Second):
+ plog.Warningf("another etcd process is using %q and holds the file lock, or loading backend file is taking >10 seconds", fn)
+ plog.Warningf("waiting for it to exit before starting...")
+ }
+ return <-beOpened
+}
+
+// recoverBackendSnapshot recovers the DB from a snapshot in case etcd crashes
+// before updating the backend db after persisting raft snapshot to disk,
+// violating the invariant snapshot.Metadata.Index < db.consistentIndex. In this
+// case, replace the db with the snapshot db sent by the leader.
+func recoverSnapshotBackend(cfg ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot) (backend.Backend, error) {
+ var cIndex consistentIndex
+ kv := mvcc.New(oldbe, &lease.FakeLessor{}, &cIndex)
+ defer kv.Close()
+ if snapshot.Metadata.Index <= kv.ConsistentIndex() {
+ return oldbe, nil
+ }
+ oldbe.Close()
+ return openSnapshotBackend(cfg, snap.New(cfg.SnapDir()), snapshot)
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/cluster_util.go b/vendor/github.com/coreos/etcd/etcdserver/cluster_util.go
new file mode 100644
index 00000000..f44862a4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/cluster_util.go
@@ -0,0 +1,258 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "sort"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/membership"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/version"
+ "github.com/coreos/go-semver/semver"
+)
+
+// isMemberBootstrapped tries to check if the given member has been bootstrapped
+// in the given cluster.
+func isMemberBootstrapped(cl *membership.RaftCluster, member string, rt http.RoundTripper, timeout time.Duration) bool {
+ rcl, err := getClusterFromRemotePeers(getRemotePeerURLs(cl, member), timeout, false, rt)
+ if err != nil {
+ return false
+ }
+ id := cl.MemberByName(member).ID
+ m := rcl.Member(id)
+ if m == nil {
+ return false
+ }
+ if len(m.ClientURLs) > 0 {
+ return true
+ }
+ return false
+}
+
+// GetClusterFromRemotePeers takes a set of URLs representing etcd peers, and
+// attempts to construct a Cluster by accessing the members endpoint on one of
+// these URLs. The first URL to provide a response is used. If no URLs provide
+// a response, or a Cluster cannot be successfully created from a received
+// response, an error is returned.
+// Each request has a 10-second timeout. Because the upper limit of TTL is 5s,
+// 10 second is enough for building connection and finishing request.
+func GetClusterFromRemotePeers(urls []string, rt http.RoundTripper) (*membership.RaftCluster, error) {
+ return getClusterFromRemotePeers(urls, 10*time.Second, true, rt)
+}
+
+// If logerr is true, it prints out more error messages.
+func getClusterFromRemotePeers(urls []string, timeout time.Duration, logerr bool, rt http.RoundTripper) (*membership.RaftCluster, error) {
+ cc := &http.Client{
+ Transport: rt,
+ Timeout: timeout,
+ }
+ for _, u := range urls {
+ resp, err := cc.Get(u + "/members")
+ if err != nil {
+ if logerr {
+ plog.Warningf("could not get cluster response from %s: %v", u, err)
+ }
+ continue
+ }
+ b, err := ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ if err != nil {
+ if logerr {
+ plog.Warningf("could not read the body of cluster response: %v", err)
+ }
+ continue
+ }
+ var membs []*membership.Member
+ if err = json.Unmarshal(b, &membs); err != nil {
+ if logerr {
+ plog.Warningf("could not unmarshal cluster response: %v", err)
+ }
+ continue
+ }
+ id, err := types.IDFromString(resp.Header.Get("X-Etcd-Cluster-ID"))
+ if err != nil {
+ if logerr {
+ plog.Warningf("could not parse the cluster ID from cluster res: %v", err)
+ }
+ continue
+ }
+
+ // check the length of membership members
+ // if the membership members are present then prepare and return raft cluster
+ // if membership members are not present then the raft cluster formed will be
+ // an invalid empty cluster hence return failed to get raft cluster member(s) from the given urls error
+ if len(membs) > 0 {
+ return membership.NewClusterFromMembers("", id, membs), nil
+ }
+
+ return nil, fmt.Errorf("failed to get raft cluster member(s) from the given urls.")
+ }
+ return nil, fmt.Errorf("could not retrieve cluster information from the given urls")
+}
+
+// getRemotePeerURLs returns peer urls of remote members in the cluster. The
+// returned list is sorted in ascending lexicographical order.
+func getRemotePeerURLs(cl *membership.RaftCluster, local string) []string {
+ us := make([]string, 0)
+ for _, m := range cl.Members() {
+ if m.Name == local {
+ continue
+ }
+ us = append(us, m.PeerURLs...)
+ }
+ sort.Strings(us)
+ return us
+}
+
+// getVersions returns the versions of the members in the given cluster.
+// The key of the returned map is the member's ID. The value of the returned map
+// is the semver versions string, including server and cluster.
+// If it fails to get the version of a member, the key will be nil.
+func getVersions(cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) map[string]*version.Versions {
+ members := cl.Members()
+ vers := make(map[string]*version.Versions)
+ for _, m := range members {
+ if m.ID == local {
+ cv := "not_decided"
+ if cl.Version() != nil {
+ cv = cl.Version().String()
+ }
+ vers[m.ID.String()] = &version.Versions{Server: version.Version, Cluster: cv}
+ continue
+ }
+ ver, err := getVersion(m, rt)
+ if err != nil {
+ plog.Warningf("cannot get the version of member %s (%v)", m.ID, err)
+ vers[m.ID.String()] = nil
+ } else {
+ vers[m.ID.String()] = ver
+ }
+ }
+ return vers
+}
+
+// decideClusterVersion decides the cluster version based on the versions map.
+// The returned version is the min server version in the map, or nil if the min
+// version in unknown.
+func decideClusterVersion(vers map[string]*version.Versions) *semver.Version {
+ var cv *semver.Version
+ lv := semver.Must(semver.NewVersion(version.Version))
+
+ for mid, ver := range vers {
+ if ver == nil {
+ return nil
+ }
+ v, err := semver.NewVersion(ver.Server)
+ if err != nil {
+ plog.Errorf("cannot understand the version of member %s (%v)", mid, err)
+ return nil
+ }
+ if lv.LessThan(*v) {
+ plog.Warningf("the local etcd version %s is not up-to-date", lv.String())
+ plog.Warningf("member %s has a higher version %s", mid, ver.Server)
+ }
+ if cv == nil {
+ cv = v
+ } else if v.LessThan(*cv) {
+ cv = v
+ }
+ }
+ return cv
+}
+
+// isCompatibleWithCluster return true if the local member has a compatible version with
+// the current running cluster.
+// The version is considered as compatible when at least one of the other members in the cluster has a
+// cluster version in the range of [MinClusterVersion, Version] and no known members has a cluster version
+// out of the range.
+// We set this rule since when the local member joins, another member might be offline.
+func isCompatibleWithCluster(cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) bool {
+ vers := getVersions(cl, local, rt)
+ minV := semver.Must(semver.NewVersion(version.MinClusterVersion))
+ maxV := semver.Must(semver.NewVersion(version.Version))
+ maxV = &semver.Version{
+ Major: maxV.Major,
+ Minor: maxV.Minor,
+ }
+
+ return isCompatibleWithVers(vers, local, minV, maxV)
+}
+
+func isCompatibleWithVers(vers map[string]*version.Versions, local types.ID, minV, maxV *semver.Version) bool {
+ var ok bool
+ for id, v := range vers {
+ // ignore comparison with local version
+ if id == local.String() {
+ continue
+ }
+ if v == nil {
+ continue
+ }
+ clusterv, err := semver.NewVersion(v.Cluster)
+ if err != nil {
+ plog.Errorf("cannot understand the cluster version of member %s (%v)", id, err)
+ continue
+ }
+ if clusterv.LessThan(*minV) {
+ plog.Warningf("the running cluster version(%v) is lower than the minimal cluster version(%v) supported", clusterv.String(), minV.String())
+ return false
+ }
+ if maxV.LessThan(*clusterv) {
+ plog.Warningf("the running cluster version(%v) is higher than the maximum cluster version(%v) supported", clusterv.String(), maxV.String())
+ return false
+ }
+ ok = true
+ }
+ return ok
+}
+
+// getVersion returns the Versions of the given member via its
+// peerURLs. Returns the last error if it fails to get the version.
+func getVersion(m *membership.Member, rt http.RoundTripper) (*version.Versions, error) {
+ cc := &http.Client{
+ Transport: rt,
+ }
+ var (
+ err error
+ resp *http.Response
+ )
+
+ for _, u := range m.PeerURLs {
+ resp, err = cc.Get(u + "/version")
+ if err != nil {
+ plog.Warningf("failed to reach the peerURL(%s) of member %s (%v)", u, m.ID, err)
+ continue
+ }
+ var b []byte
+ b, err = ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ if err != nil {
+ plog.Warningf("failed to read out the response body from the peerURL(%s) of member %s (%v)", u, m.ID, err)
+ continue
+ }
+ var vers version.Versions
+ if err = json.Unmarshal(b, &vers); err != nil {
+ plog.Warningf("failed to unmarshal the response body got from the peerURL(%s) of member %s (%v)", u, m.ID, err)
+ continue
+ }
+ return &vers, nil
+ }
+ return nil, err
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/config.go b/vendor/github.com/coreos/etcd/etcdserver/config.go
new file mode 100644
index 00000000..295d9529
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/config.go
@@ -0,0 +1,282 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "context"
+ "fmt"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/coreos/etcd/pkg/netutil"
+ "github.com/coreos/etcd/pkg/transport"
+ "github.com/coreos/etcd/pkg/types"
+)
+
+// ServerConfig holds the configuration of etcd as taken from the command line or discovery.
+type ServerConfig struct {
+ Name string
+ DiscoveryURL string
+ DiscoveryProxy string
+ ClientURLs types.URLs
+ PeerURLs types.URLs
+ DataDir string
+ // DedicatedWALDir config will make the etcd to write the WAL to the WALDir
+ // rather than the dataDir/member/wal.
+ DedicatedWALDir string
+ SnapCount uint64
+ MaxSnapFiles uint
+ MaxWALFiles uint
+ InitialPeerURLsMap types.URLsMap
+ InitialClusterToken string
+ NewCluster bool
+ ForceNewCluster bool
+ PeerTLSInfo transport.TLSInfo
+
+ TickMs uint
+ ElectionTicks int
+
+ // InitialElectionTickAdvance is true, then local member fast-forwards
+ // election ticks to speed up "initial" leader election trigger. This
+ // benefits the case of larger election ticks. For instance, cross
+ // datacenter deployment may require longer election timeout of 10-second.
+ // If true, local node does not need wait up to 10-second. Instead,
+ // forwards its election ticks to 8-second, and have only 2-second left
+ // before leader election.
+ //
+ // Major assumptions are that:
+ // - cluster has no active leader thus advancing ticks enables faster
+ // leader election, or
+ // - cluster already has an established leader, and rejoining follower
+ // is likely to receive heartbeats from the leader after tick advance
+ // and before election timeout.
+ //
+ // However, when network from leader to rejoining follower is congested,
+ // and the follower does not receive leader heartbeat within left election
+ // ticks, disruptive election has to happen thus affecting cluster
+ // availabilities.
+ //
+ // Disabling this would slow down initial bootstrap process for cross
+ // datacenter deployments. Make your own tradeoffs by configuring
+ // --initial-election-tick-advance at the cost of slow initial bootstrap.
+ //
+ // If single-node, it advances ticks regardless.
+ //
+ // See https://github.com/coreos/etcd/issues/9333 for more detail.
+ InitialElectionTickAdvance bool
+
+ BootstrapTimeout time.Duration
+
+ AutoCompactionRetention time.Duration
+ AutoCompactionMode string
+ QuotaBackendBytes int64
+ MaxTxnOps uint
+
+ // MaxRequestBytes is the maximum request size to send over raft.
+ MaxRequestBytes uint
+
+ StrictReconfigCheck bool
+
+ // ClientCertAuthEnabled is true when cert has been signed by the client CA.
+ ClientCertAuthEnabled bool
+
+ AuthToken string
+
+ // InitialCorruptCheck is true to check data corruption on boot
+ // before serving any peer/client traffic.
+ InitialCorruptCheck bool
+ CorruptCheckTime time.Duration
+
+ Debug bool
+}
+
+// VerifyBootstrap sanity-checks the initial config for bootstrap case
+// and returns an error for things that should never happen.
+func (c *ServerConfig) VerifyBootstrap() error {
+ if err := c.hasLocalMember(); err != nil {
+ return err
+ }
+ if err := c.advertiseMatchesCluster(); err != nil {
+ return err
+ }
+ if checkDuplicateURL(c.InitialPeerURLsMap) {
+ return fmt.Errorf("initial cluster %s has duplicate url", c.InitialPeerURLsMap)
+ }
+ if c.InitialPeerURLsMap.String() == "" && c.DiscoveryURL == "" {
+ return fmt.Errorf("initial cluster unset and no discovery URL found")
+ }
+ return nil
+}
+
+// VerifyJoinExisting sanity-checks the initial config for join existing cluster
+// case and returns an error for things that should never happen.
+func (c *ServerConfig) VerifyJoinExisting() error {
+ // The member has announced its peer urls to the cluster before starting; no need to
+ // set the configuration again.
+ if err := c.hasLocalMember(); err != nil {
+ return err
+ }
+ if checkDuplicateURL(c.InitialPeerURLsMap) {
+ return fmt.Errorf("initial cluster %s has duplicate url", c.InitialPeerURLsMap)
+ }
+ if c.DiscoveryURL != "" {
+ return fmt.Errorf("discovery URL should not be set when joining existing initial cluster")
+ }
+ return nil
+}
+
+// hasLocalMember checks that the cluster at least contains the local server.
+func (c *ServerConfig) hasLocalMember() error {
+ if urls := c.InitialPeerURLsMap[c.Name]; urls == nil {
+ return fmt.Errorf("couldn't find local name %q in the initial cluster configuration", c.Name)
+ }
+ return nil
+}
+
+// advertiseMatchesCluster confirms peer URLs match those in the cluster peer list.
+func (c *ServerConfig) advertiseMatchesCluster() error {
+ urls, apurls := c.InitialPeerURLsMap[c.Name], c.PeerURLs.StringSlice()
+ urls.Sort()
+ sort.Strings(apurls)
+ ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
+ defer cancel()
+ ok, err := netutil.URLStringsEqual(ctx, apurls, urls.StringSlice())
+ if ok {
+ return nil
+ }
+
+ initMap, apMap := make(map[string]struct{}), make(map[string]struct{})
+ for _, url := range c.PeerURLs {
+ apMap[url.String()] = struct{}{}
+ }
+ for _, url := range c.InitialPeerURLsMap[c.Name] {
+ initMap[url.String()] = struct{}{}
+ }
+
+ missing := []string{}
+ for url := range initMap {
+ if _, ok := apMap[url]; !ok {
+ missing = append(missing, url)
+ }
+ }
+ if len(missing) > 0 {
+ for i := range missing {
+ missing[i] = c.Name + "=" + missing[i]
+ }
+ mstr := strings.Join(missing, ",")
+ apStr := strings.Join(apurls, ",")
+ return fmt.Errorf("--initial-cluster has %s but missing from --initial-advertise-peer-urls=%s (%v)", mstr, apStr, err)
+ }
+
+ for url := range apMap {
+ if _, ok := initMap[url]; !ok {
+ missing = append(missing, url)
+ }
+ }
+ if len(missing) > 0 {
+ mstr := strings.Join(missing, ",")
+ umap := types.URLsMap(map[string]types.URLs{c.Name: c.PeerURLs})
+ return fmt.Errorf("--initial-advertise-peer-urls has %s but missing from --initial-cluster=%s", mstr, umap.String())
+ }
+
+ // resolved URLs from "--initial-advertise-peer-urls" and "--initial-cluster" did not match or failed
+ apStr := strings.Join(apurls, ",")
+ umap := types.URLsMap(map[string]types.URLs{c.Name: c.PeerURLs})
+ return fmt.Errorf("failed to resolve %s to match --initial-cluster=%s (%v)", apStr, umap.String(), err)
+}
+
+func (c *ServerConfig) MemberDir() string { return filepath.Join(c.DataDir, "member") }
+
+func (c *ServerConfig) WALDir() string {
+ if c.DedicatedWALDir != "" {
+ return c.DedicatedWALDir
+ }
+ return filepath.Join(c.MemberDir(), "wal")
+}
+
+func (c *ServerConfig) SnapDir() string { return filepath.Join(c.MemberDir(), "snap") }
+
+func (c *ServerConfig) ShouldDiscover() bool { return c.DiscoveryURL != "" }
+
+// ReqTimeout returns timeout for request to finish.
+func (c *ServerConfig) ReqTimeout() time.Duration {
+ // 5s for queue waiting, computation and disk IO delay
+ // + 2 * election timeout for possible leader election
+ return 5*time.Second + 2*time.Duration(c.ElectionTicks*int(c.TickMs))*time.Millisecond
+}
+
+func (c *ServerConfig) electionTimeout() time.Duration {
+ return time.Duration(c.ElectionTicks*int(c.TickMs)) * time.Millisecond
+}
+
+func (c *ServerConfig) peerDialTimeout() time.Duration {
+ // 1s for queue wait and election timeout
+ return time.Second + time.Duration(c.ElectionTicks*int(c.TickMs))*time.Millisecond
+}
+
+func (c *ServerConfig) PrintWithInitial() { c.print(true) }
+
+func (c *ServerConfig) Print() { c.print(false) }
+
+func (c *ServerConfig) print(initial bool) {
+ plog.Infof("name = %s", c.Name)
+ if c.ForceNewCluster {
+ plog.Infof("force new cluster")
+ }
+ plog.Infof("data dir = %s", c.DataDir)
+ plog.Infof("member dir = %s", c.MemberDir())
+ if c.DedicatedWALDir != "" {
+ plog.Infof("dedicated WAL dir = %s", c.DedicatedWALDir)
+ }
+ plog.Infof("heartbeat = %dms", c.TickMs)
+ plog.Infof("election = %dms", c.ElectionTicks*int(c.TickMs))
+ plog.Infof("snapshot count = %d", c.SnapCount)
+ if len(c.DiscoveryURL) != 0 {
+ plog.Infof("discovery URL= %s", c.DiscoveryURL)
+ if len(c.DiscoveryProxy) != 0 {
+ plog.Infof("discovery proxy = %s", c.DiscoveryProxy)
+ }
+ }
+ plog.Infof("advertise client URLs = %s", c.ClientURLs)
+ if initial {
+ plog.Infof("initial advertise peer URLs = %s", c.PeerURLs)
+ plog.Infof("initial cluster = %s", c.InitialPeerURLsMap)
+ }
+}
+
+func checkDuplicateURL(urlsmap types.URLsMap) bool {
+ um := make(map[string]bool)
+ for _, urls := range urlsmap {
+ for _, url := range urls {
+ u := url.String()
+ if um[u] {
+ return true
+ }
+ um[u] = true
+ }
+ }
+ return false
+}
+
+func (c *ServerConfig) bootstrapTimeout() time.Duration {
+ if c.BootstrapTimeout != 0 {
+ return c.BootstrapTimeout
+ }
+ return time.Second
+}
+
+func (c *ServerConfig) backendPath() string { return filepath.Join(c.SnapDir(), "db") }
diff --git a/vendor/github.com/coreos/etcd/etcdserver/consistent_index.go b/vendor/github.com/coreos/etcd/etcdserver/consistent_index.go
new file mode 100644
index 00000000..d513f670
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/consistent_index.go
@@ -0,0 +1,33 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "sync/atomic"
+)
+
+// consistentIndex represents the offset of an entry in a consistent replica log.
+// It implements the mvcc.ConsistentIndexGetter interface.
+// It is always set to the offset of current entry before executing the entry,
+// so ConsistentWatchableKV could get the consistent index from it.
+type consistentIndex uint64
+
+func (i *consistentIndex) setConsistentIndex(v uint64) {
+ atomic.StoreUint64((*uint64)(i), v)
+}
+
+func (i *consistentIndex) ConsistentIndex() uint64 {
+ return atomic.LoadUint64((*uint64)(i))
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/corrupt.go b/vendor/github.com/coreos/etcd/etcdserver/corrupt.go
new file mode 100644
index 00000000..d998ec59
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/corrupt.go
@@ -0,0 +1,262 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/coreos/etcd/clientv3"
+ "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/mvcc"
+ "github.com/coreos/etcd/pkg/types"
+)
+
+// CheckInitialHashKV compares initial hash values with its peers
+// before serving any peer/client traffic. Only mismatch when hashes
+// are different at requested revision, with same compact revision.
+func (s *EtcdServer) CheckInitialHashKV() error {
+ if !s.Cfg.InitialCorruptCheck {
+ return nil
+ }
+
+ plog.Infof("%s starting initial corruption check with timeout %v...", s.ID(), s.Cfg.ReqTimeout())
+ h, rev, crev, err := s.kv.HashByRev(0)
+ if err != nil {
+ return fmt.Errorf("%s failed to fetch hash (%v)", s.ID(), err)
+ }
+ peers := s.getPeerHashKVs(rev)
+ mismatch := 0
+ for _, p := range peers {
+ if p.resp != nil {
+ peerID := types.ID(p.resp.Header.MemberId)
+ if h != p.resp.Hash {
+ if crev == p.resp.CompactRevision {
+ plog.Errorf("%s's hash %d != %s's hash %d (revision %d, peer revision %d, compact revision %d)", s.ID(), h, peerID, p.resp.Hash, rev, p.resp.Header.Revision, crev)
+ mismatch++
+ } else {
+ plog.Warningf("%s cannot check hash of peer(%s): peer has a different compact revision %d (revision:%d)", s.ID(), peerID, p.resp.CompactRevision, rev)
+ }
+ }
+ continue
+ }
+ if p.err != nil {
+ switch p.err {
+ case rpctypes.ErrFutureRev:
+ plog.Warningf("%s cannot check the hash of peer(%q) at revision %d: peer is lagging behind(%q)", s.ID(), p.eps, rev, p.err.Error())
+ case rpctypes.ErrCompacted:
+ plog.Warningf("%s cannot check the hash of peer(%q) at revision %d: local node is lagging behind(%q)", s.ID(), p.eps, rev, p.err.Error())
+ }
+ }
+ }
+ if mismatch > 0 {
+ return fmt.Errorf("%s found data inconsistency with peers", s.ID())
+ }
+
+ plog.Infof("%s succeeded on initial corruption checking: no corruption", s.ID())
+ return nil
+}
+
+func (s *EtcdServer) monitorKVHash() {
+ t := s.Cfg.CorruptCheckTime
+ if t == 0 {
+ return
+ }
+ plog.Infof("enabled corruption checking with %s interval", t)
+ for {
+ select {
+ case <-s.stopping:
+ return
+ case <-time.After(t):
+ }
+ if !s.isLeader() {
+ continue
+ }
+ if err := s.checkHashKV(); err != nil {
+ plog.Debugf("check hash kv failed %v", err)
+ }
+ }
+}
+
+func (s *EtcdServer) checkHashKV() error {
+ h, rev, crev, err := s.kv.HashByRev(0)
+ if err != nil {
+ plog.Fatalf("failed to hash kv store (%v)", err)
+ }
+ peers := s.getPeerHashKVs(rev)
+
+ ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout())
+ err = s.linearizableReadNotify(ctx)
+ cancel()
+ if err != nil {
+ return err
+ }
+
+ h2, rev2, crev2, err := s.kv.HashByRev(0)
+ if err != nil {
+ plog.Warningf("failed to hash kv store (%v)", err)
+ return err
+ }
+
+ alarmed := false
+ mismatch := func(id uint64) {
+ if alarmed {
+ return
+ }
+ alarmed = true
+ a := &pb.AlarmRequest{
+ MemberID: uint64(id),
+ Action: pb.AlarmRequest_ACTIVATE,
+ Alarm: pb.AlarmType_CORRUPT,
+ }
+ s.goAttach(func() {
+ s.raftRequest(s.ctx, pb.InternalRaftRequest{Alarm: a})
+ })
+ }
+
+ if h2 != h && rev2 == rev && crev == crev2 {
+ plog.Warningf("mismatched hashes %d and %d for revision %d", h, h2, rev)
+ mismatch(uint64(s.ID()))
+ }
+
+ for _, p := range peers {
+ if p.resp == nil {
+ continue
+ }
+ id := p.resp.Header.MemberId
+
+ // leader expects follower's latest revision less than or equal to leader's
+ if p.resp.Header.Revision > rev2 {
+ plog.Warningf(
+ "revision %d from member %v, expected at most %d",
+ p.resp.Header.Revision,
+ types.ID(id),
+ rev2)
+ mismatch(id)
+ }
+
+ // leader expects follower's latest compact revision less than or equal to leader's
+ if p.resp.CompactRevision > crev2 {
+ plog.Warningf(
+ "compact revision %d from member %v, expected at most %d",
+ p.resp.CompactRevision,
+ types.ID(id),
+ crev2,
+ )
+ mismatch(id)
+ }
+
+ // follower's compact revision is leader's old one, then hashes must match
+ if p.resp.CompactRevision == crev && p.resp.Hash != h {
+ plog.Warningf(
+ "hash %d at revision %d from member %v, expected hash %d",
+ p.resp.Hash,
+ rev,
+ types.ID(id),
+ h,
+ )
+ mismatch(id)
+ }
+ }
+ return nil
+}
+
+type peerHashKVResp struct {
+ resp *clientv3.HashKVResponse
+ err error
+ eps []string
+}
+
+func (s *EtcdServer) getPeerHashKVs(rev int64) (resps []*peerHashKVResp) {
+ // TODO: handle the case when "s.cluster.Members" have not
+ // been populated (e.g. no snapshot to load from disk)
+ mbs := s.cluster.Members()
+ pURLs := make([][]string, len(mbs))
+ for _, m := range mbs {
+ if m.ID == s.ID() {
+ continue
+ }
+ pURLs = append(pURLs, m.PeerURLs)
+ }
+
+ for _, purls := range pURLs {
+ if len(purls) == 0 {
+ continue
+ }
+ cli, cerr := clientv3.New(clientv3.Config{
+ DialTimeout: s.Cfg.ReqTimeout(),
+ Endpoints: purls,
+ })
+ if cerr != nil {
+ plog.Warningf("%s failed to create client to peer %q for hash checking (%q)", s.ID(), purls, cerr.Error())
+ continue
+ }
+
+ respsLen := len(resps)
+ for _, c := range cli.Endpoints() {
+ ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout())
+ var resp *clientv3.HashKVResponse
+ resp, cerr = cli.HashKV(ctx, c, rev)
+ cancel()
+ if cerr == nil {
+ resps = append(resps, &peerHashKVResp{resp: resp})
+ break
+ }
+ plog.Warningf("%s hash-kv error %q on peer %q with revision %d", s.ID(), cerr.Error(), c, rev)
+ }
+ cli.Close()
+
+ if respsLen == len(resps) {
+ resps = append(resps, &peerHashKVResp{err: cerr, eps: purls})
+ }
+ }
+ return resps
+}
+
+type applierV3Corrupt struct {
+ applierV3
+}
+
+func newApplierV3Corrupt(a applierV3) *applierV3Corrupt { return &applierV3Corrupt{a} }
+
+func (a *applierV3Corrupt) Put(txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, error) {
+ return nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) Range(txn mvcc.TxnRead, p *pb.RangeRequest) (*pb.RangeResponse, error) {
+ return nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) DeleteRange(txn mvcc.TxnWrite, p *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
+ return nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) {
+ return nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, error) {
+ return nil, nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ return nil, ErrCorrupt
+}
+
+func (a *applierV3Corrupt) LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) {
+ return nil, ErrCorrupt
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/doc.go b/vendor/github.com/coreos/etcd/etcdserver/doc.go
new file mode 100644
index 00000000..b195d2d1
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package etcdserver defines how etcd servers interact and store their states.
+package etcdserver
diff --git a/vendor/github.com/coreos/etcd/etcdserver/errors.go b/vendor/github.com/coreos/etcd/etcdserver/errors.go
new file mode 100644
index 00000000..fb93c4b2
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/errors.go
@@ -0,0 +1,48 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "errors"
+ "fmt"
+)
+
+var (
+ ErrUnknownMethod = errors.New("etcdserver: unknown method")
+ ErrStopped = errors.New("etcdserver: server stopped")
+ ErrCanceled = errors.New("etcdserver: request cancelled")
+ ErrTimeout = errors.New("etcdserver: request timed out")
+ ErrTimeoutDueToLeaderFail = errors.New("etcdserver: request timed out, possibly due to previous leader failure")
+ ErrTimeoutDueToConnectionLost = errors.New("etcdserver: request timed out, possibly due to connection lost")
+ ErrTimeoutLeaderTransfer = errors.New("etcdserver: request timed out, leader transfer took too long")
+ ErrNotEnoughStartedMembers = errors.New("etcdserver: re-configuration failed due to not enough started members")
+ ErrNoLeader = errors.New("etcdserver: no leader")
+ ErrNotLeader = errors.New("etcdserver: not leader")
+ ErrRequestTooLarge = errors.New("etcdserver: request is too large")
+ ErrNoSpace = errors.New("etcdserver: no space")
+ ErrTooManyRequests = errors.New("etcdserver: too many requests")
+ ErrUnhealthy = errors.New("etcdserver: unhealthy cluster")
+ ErrKeyNotFound = errors.New("etcdserver: key not found")
+ ErrCorrupt = errors.New("etcdserver: corrupt cluster")
+)
+
+type DiscoveryError struct {
+ Op string
+ Err error
+}
+
+func (e DiscoveryError) Error() string {
+ return fmt.Sprintf("failed to %s discovery cluster (%v)", e.Op, e.Err)
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/etcdserver.pb.go b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/etcdserver.pb.go
new file mode 100644
index 00000000..90045a5c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/etcdserver.pb.go
@@ -0,0 +1,1035 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: etcdserver.proto
+
+/*
+ Package etcdserverpb is a generated protocol buffer package.
+
+ It is generated from these files:
+ etcdserver.proto
+ raft_internal.proto
+ rpc.proto
+
+ It has these top-level messages:
+ Request
+ Metadata
+ RequestHeader
+ InternalRaftRequest
+ EmptyResponse
+ InternalAuthenticateRequest
+ ResponseHeader
+ RangeRequest
+ RangeResponse
+ PutRequest
+ PutResponse
+ DeleteRangeRequest
+ DeleteRangeResponse
+ RequestOp
+ ResponseOp
+ Compare
+ TxnRequest
+ TxnResponse
+ CompactionRequest
+ CompactionResponse
+ HashRequest
+ HashKVRequest
+ HashKVResponse
+ HashResponse
+ SnapshotRequest
+ SnapshotResponse
+ WatchRequest
+ WatchCreateRequest
+ WatchCancelRequest
+ WatchResponse
+ LeaseGrantRequest
+ LeaseGrantResponse
+ LeaseRevokeRequest
+ LeaseRevokeResponse
+ LeaseKeepAliveRequest
+ LeaseKeepAliveResponse
+ LeaseTimeToLiveRequest
+ LeaseTimeToLiveResponse
+ LeaseLeasesRequest
+ LeaseStatus
+ LeaseLeasesResponse
+ Member
+ MemberAddRequest
+ MemberAddResponse
+ MemberRemoveRequest
+ MemberRemoveResponse
+ MemberUpdateRequest
+ MemberUpdateResponse
+ MemberListRequest
+ MemberListResponse
+ DefragmentRequest
+ DefragmentResponse
+ MoveLeaderRequest
+ MoveLeaderResponse
+ AlarmRequest
+ AlarmMember
+ AlarmResponse
+ StatusRequest
+ StatusResponse
+ AuthEnableRequest
+ AuthDisableRequest
+ AuthenticateRequest
+ AuthUserAddRequest
+ AuthUserGetRequest
+ AuthUserDeleteRequest
+ AuthUserChangePasswordRequest
+ AuthUserGrantRoleRequest
+ AuthUserRevokeRoleRequest
+ AuthRoleAddRequest
+ AuthRoleGetRequest
+ AuthUserListRequest
+ AuthRoleListRequest
+ AuthRoleDeleteRequest
+ AuthRoleGrantPermissionRequest
+ AuthRoleRevokePermissionRequest
+ AuthEnableResponse
+ AuthDisableResponse
+ AuthenticateResponse
+ AuthUserAddResponse
+ AuthUserGetResponse
+ AuthUserDeleteResponse
+ AuthUserChangePasswordResponse
+ AuthUserGrantRoleResponse
+ AuthUserRevokeRoleResponse
+ AuthRoleAddResponse
+ AuthRoleGetResponse
+ AuthRoleListResponse
+ AuthUserListResponse
+ AuthRoleDeleteResponse
+ AuthRoleGrantPermissionResponse
+ AuthRoleRevokePermissionResponse
+*/
+package etcdserverpb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Request struct {
+ ID uint64 `protobuf:"varint,1,opt,name=ID" json:"ID"`
+ Method string `protobuf:"bytes,2,opt,name=Method" json:"Method"`
+ Path string `protobuf:"bytes,3,opt,name=Path" json:"Path"`
+ Val string `protobuf:"bytes,4,opt,name=Val" json:"Val"`
+ Dir bool `protobuf:"varint,5,opt,name=Dir" json:"Dir"`
+ PrevValue string `protobuf:"bytes,6,opt,name=PrevValue" json:"PrevValue"`
+ PrevIndex uint64 `protobuf:"varint,7,opt,name=PrevIndex" json:"PrevIndex"`
+ PrevExist *bool `protobuf:"varint,8,opt,name=PrevExist" json:"PrevExist,omitempty"`
+ Expiration int64 `protobuf:"varint,9,opt,name=Expiration" json:"Expiration"`
+ Wait bool `protobuf:"varint,10,opt,name=Wait" json:"Wait"`
+ Since uint64 `protobuf:"varint,11,opt,name=Since" json:"Since"`
+ Recursive bool `protobuf:"varint,12,opt,name=Recursive" json:"Recursive"`
+ Sorted bool `protobuf:"varint,13,opt,name=Sorted" json:"Sorted"`
+ Quorum bool `protobuf:"varint,14,opt,name=Quorum" json:"Quorum"`
+ Time int64 `protobuf:"varint,15,opt,name=Time" json:"Time"`
+ Stream bool `protobuf:"varint,16,opt,name=Stream" json:"Stream"`
+ Refresh *bool `protobuf:"varint,17,opt,name=Refresh" json:"Refresh,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Request) Reset() { *m = Request{} }
+func (m *Request) String() string { return proto.CompactTextString(m) }
+func (*Request) ProtoMessage() {}
+func (*Request) Descriptor() ([]byte, []int) { return fileDescriptorEtcdserver, []int{0} }
+
+type Metadata struct {
+ NodeID uint64 `protobuf:"varint,1,opt,name=NodeID" json:"NodeID"`
+ ClusterID uint64 `protobuf:"varint,2,opt,name=ClusterID" json:"ClusterID"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Metadata) Reset() { *m = Metadata{} }
+func (m *Metadata) String() string { return proto.CompactTextString(m) }
+func (*Metadata) ProtoMessage() {}
+func (*Metadata) Descriptor() ([]byte, []int) { return fileDescriptorEtcdserver, []int{1} }
+
+func init() {
+ proto.RegisterType((*Request)(nil), "etcdserverpb.Request")
+ proto.RegisterType((*Metadata)(nil), "etcdserverpb.Metadata")
+}
+func (m *Request) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Request) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(m.ID))
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(len(m.Method)))
+ i += copy(dAtA[i:], m.Method)
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(len(m.Path)))
+ i += copy(dAtA[i:], m.Path)
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(len(m.Val)))
+ i += copy(dAtA[i:], m.Val)
+ dAtA[i] = 0x28
+ i++
+ if m.Dir {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ dAtA[i] = 0x32
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(len(m.PrevValue)))
+ i += copy(dAtA[i:], m.PrevValue)
+ dAtA[i] = 0x38
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(m.PrevIndex))
+ if m.PrevExist != nil {
+ dAtA[i] = 0x40
+ i++
+ if *m.PrevExist {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ dAtA[i] = 0x48
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(m.Expiration))
+ dAtA[i] = 0x50
+ i++
+ if m.Wait {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ dAtA[i] = 0x58
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(m.Since))
+ dAtA[i] = 0x60
+ i++
+ if m.Recursive {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ dAtA[i] = 0x68
+ i++
+ if m.Sorted {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ dAtA[i] = 0x70
+ i++
+ if m.Quorum {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ dAtA[i] = 0x78
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(m.Time))
+ dAtA[i] = 0x80
+ i++
+ dAtA[i] = 0x1
+ i++
+ if m.Stream {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ if m.Refresh != nil {
+ dAtA[i] = 0x88
+ i++
+ dAtA[i] = 0x1
+ i++
+ if *m.Refresh {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *Metadata) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Metadata) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(m.NodeID))
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintEtcdserver(dAtA, i, uint64(m.ClusterID))
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func encodeVarintEtcdserver(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Request) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovEtcdserver(uint64(m.ID))
+ l = len(m.Method)
+ n += 1 + l + sovEtcdserver(uint64(l))
+ l = len(m.Path)
+ n += 1 + l + sovEtcdserver(uint64(l))
+ l = len(m.Val)
+ n += 1 + l + sovEtcdserver(uint64(l))
+ n += 2
+ l = len(m.PrevValue)
+ n += 1 + l + sovEtcdserver(uint64(l))
+ n += 1 + sovEtcdserver(uint64(m.PrevIndex))
+ if m.PrevExist != nil {
+ n += 2
+ }
+ n += 1 + sovEtcdserver(uint64(m.Expiration))
+ n += 2
+ n += 1 + sovEtcdserver(uint64(m.Since))
+ n += 2
+ n += 2
+ n += 2
+ n += 1 + sovEtcdserver(uint64(m.Time))
+ n += 3
+ if m.Refresh != nil {
+ n += 3
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *Metadata) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovEtcdserver(uint64(m.NodeID))
+ n += 1 + sovEtcdserver(uint64(m.ClusterID))
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovEtcdserver(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozEtcdserver(x uint64) (n int) {
+ return sovEtcdserver(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Request) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Request: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Request: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Method", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEtcdserver
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Method = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEtcdserver
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Path = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Val", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEtcdserver
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Val = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Dir", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Dir = bool(v != 0)
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevValue", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthEtcdserver
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.PrevValue = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 7:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevIndex", wireType)
+ }
+ m.PrevIndex = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.PrevIndex |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevExist", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ b := bool(v != 0)
+ m.PrevExist = &b
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType)
+ }
+ m.Expiration = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Expiration |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 10:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Wait", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Wait = bool(v != 0)
+ case 11:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Since", wireType)
+ }
+ m.Since = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Since |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 12:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Recursive", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Recursive = bool(v != 0)
+ case 13:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Sorted", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Sorted = bool(v != 0)
+ case 14:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Quorum", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Quorum = bool(v != 0)
+ case 15:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
+ }
+ m.Time = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Time |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 16:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Stream", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Stream = bool(v != 0)
+ case 17:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Refresh", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ b := bool(v != 0)
+ m.Refresh = &b
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEtcdserver(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthEtcdserver
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Metadata) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Metadata: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Metadata: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NodeID", wireType)
+ }
+ m.NodeID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.NodeID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ClusterID", wireType)
+ }
+ m.ClusterID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ClusterID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipEtcdserver(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthEtcdserver
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipEtcdserver(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthEtcdserver
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowEtcdserver
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipEtcdserver(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthEtcdserver = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowEtcdserver = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("etcdserver.proto", fileDescriptorEtcdserver) }
+
+var fileDescriptorEtcdserver = []byte{
+ // 380 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0xd2, 0xdd, 0x6e, 0xda, 0x30,
+ 0x14, 0x07, 0x70, 0x0c, 0xe1, 0xcb, 0x63, 0x1b, 0xb3, 0xd0, 0x74, 0x84, 0xa6, 0x2c, 0x42, 0xbb,
+ 0xc8, 0xd5, 0xf6, 0x0e, 0x2c, 0x5c, 0x44, 0x2a, 0x15, 0x0d, 0x15, 0xbd, 0x76, 0xc9, 0x29, 0x58,
+ 0x02, 0x4c, 0x1d, 0x07, 0xf1, 0x06, 0x7d, 0x85, 0x3e, 0x12, 0x97, 0x7d, 0x82, 0xaa, 0xa5, 0x2f,
+ 0x52, 0x39, 0x24, 0xc4, 0xed, 0x5d, 0xf4, 0xfb, 0x9f, 0x1c, 0x1f, 0x7f, 0xd0, 0x2e, 0xea, 0x79,
+ 0x9c, 0xa0, 0xda, 0xa1, 0xfa, 0xbb, 0x55, 0x52, 0x4b, 0xd6, 0x29, 0x65, 0x7b, 0xdb, 0xef, 0x2d,
+ 0xe4, 0x42, 0x66, 0xc1, 0x3f, 0xf3, 0x75, 0xaa, 0x19, 0x3c, 0x38, 0xb4, 0x19, 0xe1, 0x7d, 0x8a,
+ 0x89, 0x66, 0x3d, 0x5a, 0x0d, 0x03, 0x20, 0x1e, 0xf1, 0x9d, 0xa1, 0x73, 0x78, 0xfe, 0x5d, 0x89,
+ 0xaa, 0x61, 0xc0, 0x7e, 0xd1, 0xc6, 0x18, 0xf5, 0x52, 0xc6, 0x50, 0xf5, 0x88, 0xdf, 0xce, 0x93,
+ 0xdc, 0x18, 0x50, 0x67, 0xc2, 0xf5, 0x12, 0x6a, 0x56, 0x96, 0x09, 0xfb, 0x49, 0x6b, 0x33, 0xbe,
+ 0x02, 0xc7, 0x0a, 0x0c, 0x18, 0x0f, 0x84, 0x82, 0xba, 0x47, 0xfc, 0x56, 0xe1, 0x81, 0x50, 0x6c,
+ 0x40, 0xdb, 0x13, 0x85, 0xbb, 0x19, 0x5f, 0xa5, 0x08, 0x0d, 0xeb, 0xaf, 0x92, 0x8b, 0x9a, 0x70,
+ 0x13, 0xe3, 0x1e, 0x9a, 0xd6, 0xa0, 0x25, 0x17, 0x35, 0xa3, 0xbd, 0x48, 0x34, 0xb4, 0xce, 0xab,
+ 0x90, 0xa8, 0x64, 0xf6, 0x87, 0xd2, 0xd1, 0x7e, 0x2b, 0x14, 0xd7, 0x42, 0x6e, 0xa0, 0xed, 0x11,
+ 0xbf, 0x96, 0x37, 0xb2, 0xdc, 0xec, 0xed, 0x86, 0x0b, 0x0d, 0xd4, 0x1a, 0x35, 0x13, 0xd6, 0xa7,
+ 0xf5, 0xa9, 0xd8, 0xcc, 0x11, 0xbe, 0x58, 0x33, 0x9c, 0xc8, 0xac, 0x1f, 0xe1, 0x3c, 0x55, 0x89,
+ 0xd8, 0x21, 0x74, 0xac, 0x5f, 0x4b, 0x36, 0x67, 0x3a, 0x95, 0x4a, 0x63, 0x0c, 0x5f, 0xad, 0x82,
+ 0xdc, 0x4c, 0x7a, 0x95, 0x4a, 0x95, 0xae, 0xe1, 0x9b, 0x9d, 0x9e, 0xcc, 0x4c, 0x75, 0x2d, 0xd6,
+ 0x08, 0xdf, 0xad, 0xa9, 0x33, 0xc9, 0xba, 0x6a, 0x85, 0x7c, 0x0d, 0xdd, 0x0f, 0x5d, 0x33, 0x63,
+ 0xae, 0xb9, 0xe8, 0x3b, 0x85, 0xc9, 0x12, 0x7e, 0x58, 0xa7, 0x52, 0xe0, 0xe0, 0x82, 0xb6, 0xc6,
+ 0xa8, 0x79, 0xcc, 0x35, 0x37, 0x9d, 0x2e, 0x65, 0x8c, 0x9f, 0x5e, 0x43, 0x6e, 0x66, 0x87, 0xff,
+ 0x57, 0x69, 0xa2, 0x51, 0x85, 0x41, 0xf6, 0x28, 0xce, 0xb7, 0x70, 0xe6, 0x61, 0xef, 0xf0, 0xea,
+ 0x56, 0x0e, 0x47, 0x97, 0x3c, 0x1d, 0x5d, 0xf2, 0x72, 0x74, 0xc9, 0xe3, 0x9b, 0x5b, 0x79, 0x0f,
+ 0x00, 0x00, 0xff, 0xff, 0xee, 0x40, 0xba, 0xd6, 0xa4, 0x02, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal.pb.go b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal.pb.go
new file mode 100644
index 00000000..3084c6cb
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal.pb.go
@@ -0,0 +1,2077 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: raft_internal.proto
+
+package etcdserverpb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+type RequestHeader struct {
+ ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ // username is a username that is associated with an auth token of gRPC connection
+ Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+ // auth_revision is a revision number of auth.authStore. It is not related to mvcc
+ AuthRevision uint64 `protobuf:"varint,3,opt,name=auth_revision,json=authRevision,proto3" json:"auth_revision,omitempty"`
+}
+
+func (m *RequestHeader) Reset() { *m = RequestHeader{} }
+func (m *RequestHeader) String() string { return proto.CompactTextString(m) }
+func (*RequestHeader) ProtoMessage() {}
+func (*RequestHeader) Descriptor() ([]byte, []int) { return fileDescriptorRaftInternal, []int{0} }
+
+// An InternalRaftRequest is the union of all requests which can be
+// sent via raft.
+type InternalRaftRequest struct {
+ Header *RequestHeader `protobuf:"bytes,100,opt,name=header" json:"header,omitempty"`
+ ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ V2 *Request `protobuf:"bytes,2,opt,name=v2" json:"v2,omitempty"`
+ Range *RangeRequest `protobuf:"bytes,3,opt,name=range" json:"range,omitempty"`
+ Put *PutRequest `protobuf:"bytes,4,opt,name=put" json:"put,omitempty"`
+ DeleteRange *DeleteRangeRequest `protobuf:"bytes,5,opt,name=delete_range,json=deleteRange" json:"delete_range,omitempty"`
+ Txn *TxnRequest `protobuf:"bytes,6,opt,name=txn" json:"txn,omitempty"`
+ Compaction *CompactionRequest `protobuf:"bytes,7,opt,name=compaction" json:"compaction,omitempty"`
+ LeaseGrant *LeaseGrantRequest `protobuf:"bytes,8,opt,name=lease_grant,json=leaseGrant" json:"lease_grant,omitempty"`
+ LeaseRevoke *LeaseRevokeRequest `protobuf:"bytes,9,opt,name=lease_revoke,json=leaseRevoke" json:"lease_revoke,omitempty"`
+ Alarm *AlarmRequest `protobuf:"bytes,10,opt,name=alarm" json:"alarm,omitempty"`
+ AuthEnable *AuthEnableRequest `protobuf:"bytes,1000,opt,name=auth_enable,json=authEnable" json:"auth_enable,omitempty"`
+ AuthDisable *AuthDisableRequest `protobuf:"bytes,1011,opt,name=auth_disable,json=authDisable" json:"auth_disable,omitempty"`
+ Authenticate *InternalAuthenticateRequest `protobuf:"bytes,1012,opt,name=authenticate" json:"authenticate,omitempty"`
+ AuthUserAdd *AuthUserAddRequest `protobuf:"bytes,1100,opt,name=auth_user_add,json=authUserAdd" json:"auth_user_add,omitempty"`
+ AuthUserDelete *AuthUserDeleteRequest `protobuf:"bytes,1101,opt,name=auth_user_delete,json=authUserDelete" json:"auth_user_delete,omitempty"`
+ AuthUserGet *AuthUserGetRequest `protobuf:"bytes,1102,opt,name=auth_user_get,json=authUserGet" json:"auth_user_get,omitempty"`
+ AuthUserChangePassword *AuthUserChangePasswordRequest `protobuf:"bytes,1103,opt,name=auth_user_change_password,json=authUserChangePassword" json:"auth_user_change_password,omitempty"`
+ AuthUserGrantRole *AuthUserGrantRoleRequest `protobuf:"bytes,1104,opt,name=auth_user_grant_role,json=authUserGrantRole" json:"auth_user_grant_role,omitempty"`
+ AuthUserRevokeRole *AuthUserRevokeRoleRequest `protobuf:"bytes,1105,opt,name=auth_user_revoke_role,json=authUserRevokeRole" json:"auth_user_revoke_role,omitempty"`
+ AuthUserList *AuthUserListRequest `protobuf:"bytes,1106,opt,name=auth_user_list,json=authUserList" json:"auth_user_list,omitempty"`
+ AuthRoleList *AuthRoleListRequest `protobuf:"bytes,1107,opt,name=auth_role_list,json=authRoleList" json:"auth_role_list,omitempty"`
+ AuthRoleAdd *AuthRoleAddRequest `protobuf:"bytes,1200,opt,name=auth_role_add,json=authRoleAdd" json:"auth_role_add,omitempty"`
+ AuthRoleDelete *AuthRoleDeleteRequest `protobuf:"bytes,1201,opt,name=auth_role_delete,json=authRoleDelete" json:"auth_role_delete,omitempty"`
+ AuthRoleGet *AuthRoleGetRequest `protobuf:"bytes,1202,opt,name=auth_role_get,json=authRoleGet" json:"auth_role_get,omitempty"`
+ AuthRoleGrantPermission *AuthRoleGrantPermissionRequest `protobuf:"bytes,1203,opt,name=auth_role_grant_permission,json=authRoleGrantPermission" json:"auth_role_grant_permission,omitempty"`
+ AuthRoleRevokePermission *AuthRoleRevokePermissionRequest `protobuf:"bytes,1204,opt,name=auth_role_revoke_permission,json=authRoleRevokePermission" json:"auth_role_revoke_permission,omitempty"`
+}
+
+func (m *InternalRaftRequest) Reset() { *m = InternalRaftRequest{} }
+func (m *InternalRaftRequest) String() string { return proto.CompactTextString(m) }
+func (*InternalRaftRequest) ProtoMessage() {}
+func (*InternalRaftRequest) Descriptor() ([]byte, []int) { return fileDescriptorRaftInternal, []int{1} }
+
+type EmptyResponse struct {
+}
+
+func (m *EmptyResponse) Reset() { *m = EmptyResponse{} }
+func (m *EmptyResponse) String() string { return proto.CompactTextString(m) }
+func (*EmptyResponse) ProtoMessage() {}
+func (*EmptyResponse) Descriptor() ([]byte, []int) { return fileDescriptorRaftInternal, []int{2} }
+
+// What is the difference between AuthenticateRequest (defined in rpc.proto) and InternalAuthenticateRequest?
+// InternalAuthenticateRequest has a member that is filled by etcdserver and shouldn't be user-facing.
+// For avoiding misusage the field, we have an internal version of AuthenticateRequest.
+type InternalAuthenticateRequest struct {
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+ // simple_token is generated in API layer (etcdserver/v3_server.go)
+ SimpleToken string `protobuf:"bytes,3,opt,name=simple_token,json=simpleToken,proto3" json:"simple_token,omitempty"`
+}
+
+func (m *InternalAuthenticateRequest) Reset() { *m = InternalAuthenticateRequest{} }
+func (m *InternalAuthenticateRequest) String() string { return proto.CompactTextString(m) }
+func (*InternalAuthenticateRequest) ProtoMessage() {}
+func (*InternalAuthenticateRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptorRaftInternal, []int{3}
+}
+
+func init() {
+ proto.RegisterType((*RequestHeader)(nil), "etcdserverpb.RequestHeader")
+ proto.RegisterType((*InternalRaftRequest)(nil), "etcdserverpb.InternalRaftRequest")
+ proto.RegisterType((*EmptyResponse)(nil), "etcdserverpb.EmptyResponse")
+ proto.RegisterType((*InternalAuthenticateRequest)(nil), "etcdserverpb.InternalAuthenticateRequest")
+}
+func (m *RequestHeader) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *RequestHeader) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.ID))
+ }
+ if len(m.Username) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(len(m.Username)))
+ i += copy(dAtA[i:], m.Username)
+ }
+ if m.AuthRevision != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthRevision))
+ }
+ return i, nil
+}
+
+func (m *InternalRaftRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *InternalRaftRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.ID))
+ }
+ if m.V2 != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.V2.Size()))
+ n1, err := m.V2.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ }
+ if m.Range != nil {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.Range.Size()))
+ n2, err := m.Range.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n2
+ }
+ if m.Put != nil {
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.Put.Size()))
+ n3, err := m.Put.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n3
+ }
+ if m.DeleteRange != nil {
+ dAtA[i] = 0x2a
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.DeleteRange.Size()))
+ n4, err := m.DeleteRange.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n4
+ }
+ if m.Txn != nil {
+ dAtA[i] = 0x32
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.Txn.Size()))
+ n5, err := m.Txn.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n5
+ }
+ if m.Compaction != nil {
+ dAtA[i] = 0x3a
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.Compaction.Size()))
+ n6, err := m.Compaction.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n6
+ }
+ if m.LeaseGrant != nil {
+ dAtA[i] = 0x42
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.LeaseGrant.Size()))
+ n7, err := m.LeaseGrant.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n7
+ }
+ if m.LeaseRevoke != nil {
+ dAtA[i] = 0x4a
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.LeaseRevoke.Size()))
+ n8, err := m.LeaseRevoke.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n8
+ }
+ if m.Alarm != nil {
+ dAtA[i] = 0x52
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.Alarm.Size()))
+ n9, err := m.Alarm.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n9
+ }
+ if m.Header != nil {
+ dAtA[i] = 0xa2
+ i++
+ dAtA[i] = 0x6
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.Header.Size()))
+ n10, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n10
+ }
+ if m.AuthEnable != nil {
+ dAtA[i] = 0xc2
+ i++
+ dAtA[i] = 0x3e
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthEnable.Size()))
+ n11, err := m.AuthEnable.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n11
+ }
+ if m.AuthDisable != nil {
+ dAtA[i] = 0x9a
+ i++
+ dAtA[i] = 0x3f
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthDisable.Size()))
+ n12, err := m.AuthDisable.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n12
+ }
+ if m.Authenticate != nil {
+ dAtA[i] = 0xa2
+ i++
+ dAtA[i] = 0x3f
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.Authenticate.Size()))
+ n13, err := m.Authenticate.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n13
+ }
+ if m.AuthUserAdd != nil {
+ dAtA[i] = 0xe2
+ i++
+ dAtA[i] = 0x44
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthUserAdd.Size()))
+ n14, err := m.AuthUserAdd.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n14
+ }
+ if m.AuthUserDelete != nil {
+ dAtA[i] = 0xea
+ i++
+ dAtA[i] = 0x44
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthUserDelete.Size()))
+ n15, err := m.AuthUserDelete.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n15
+ }
+ if m.AuthUserGet != nil {
+ dAtA[i] = 0xf2
+ i++
+ dAtA[i] = 0x44
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthUserGet.Size()))
+ n16, err := m.AuthUserGet.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n16
+ }
+ if m.AuthUserChangePassword != nil {
+ dAtA[i] = 0xfa
+ i++
+ dAtA[i] = 0x44
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthUserChangePassword.Size()))
+ n17, err := m.AuthUserChangePassword.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n17
+ }
+ if m.AuthUserGrantRole != nil {
+ dAtA[i] = 0x82
+ i++
+ dAtA[i] = 0x45
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthUserGrantRole.Size()))
+ n18, err := m.AuthUserGrantRole.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n18
+ }
+ if m.AuthUserRevokeRole != nil {
+ dAtA[i] = 0x8a
+ i++
+ dAtA[i] = 0x45
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthUserRevokeRole.Size()))
+ n19, err := m.AuthUserRevokeRole.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n19
+ }
+ if m.AuthUserList != nil {
+ dAtA[i] = 0x92
+ i++
+ dAtA[i] = 0x45
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthUserList.Size()))
+ n20, err := m.AuthUserList.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n20
+ }
+ if m.AuthRoleList != nil {
+ dAtA[i] = 0x9a
+ i++
+ dAtA[i] = 0x45
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthRoleList.Size()))
+ n21, err := m.AuthRoleList.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n21
+ }
+ if m.AuthRoleAdd != nil {
+ dAtA[i] = 0x82
+ i++
+ dAtA[i] = 0x4b
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthRoleAdd.Size()))
+ n22, err := m.AuthRoleAdd.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n22
+ }
+ if m.AuthRoleDelete != nil {
+ dAtA[i] = 0x8a
+ i++
+ dAtA[i] = 0x4b
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthRoleDelete.Size()))
+ n23, err := m.AuthRoleDelete.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n23
+ }
+ if m.AuthRoleGet != nil {
+ dAtA[i] = 0x92
+ i++
+ dAtA[i] = 0x4b
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthRoleGet.Size()))
+ n24, err := m.AuthRoleGet.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n24
+ }
+ if m.AuthRoleGrantPermission != nil {
+ dAtA[i] = 0x9a
+ i++
+ dAtA[i] = 0x4b
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthRoleGrantPermission.Size()))
+ n25, err := m.AuthRoleGrantPermission.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n25
+ }
+ if m.AuthRoleRevokePermission != nil {
+ dAtA[i] = 0xa2
+ i++
+ dAtA[i] = 0x4b
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(m.AuthRoleRevokePermission.Size()))
+ n26, err := m.AuthRoleRevokePermission.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n26
+ }
+ return i, nil
+}
+
+func (m *EmptyResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *EmptyResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *InternalAuthenticateRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *InternalAuthenticateRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.Password) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(len(m.Password)))
+ i += copy(dAtA[i:], m.Password)
+ }
+ if len(m.SimpleToken) > 0 {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRaftInternal(dAtA, i, uint64(len(m.SimpleToken)))
+ i += copy(dAtA[i:], m.SimpleToken)
+ }
+ return i, nil
+}
+
+func encodeVarintRaftInternal(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *RequestHeader) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRaftInternal(uint64(m.ID))
+ }
+ l = len(m.Username)
+ if l > 0 {
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthRevision != 0 {
+ n += 1 + sovRaftInternal(uint64(m.AuthRevision))
+ }
+ return n
+}
+
+func (m *InternalRaftRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRaftInternal(uint64(m.ID))
+ }
+ if m.V2 != nil {
+ l = m.V2.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.Range != nil {
+ l = m.Range.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.Put != nil {
+ l = m.Put.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.DeleteRange != nil {
+ l = m.DeleteRange.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.Txn != nil {
+ l = m.Txn.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.Compaction != nil {
+ l = m.Compaction.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.LeaseGrant != nil {
+ l = m.LeaseGrant.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.LeaseRevoke != nil {
+ l = m.LeaseRevoke.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.Alarm != nil {
+ l = m.Alarm.Size()
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthEnable != nil {
+ l = m.AuthEnable.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthDisable != nil {
+ l = m.AuthDisable.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.Authenticate != nil {
+ l = m.Authenticate.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthUserAdd != nil {
+ l = m.AuthUserAdd.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthUserDelete != nil {
+ l = m.AuthUserDelete.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthUserGet != nil {
+ l = m.AuthUserGet.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthUserChangePassword != nil {
+ l = m.AuthUserChangePassword.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthUserGrantRole != nil {
+ l = m.AuthUserGrantRole.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthUserRevokeRole != nil {
+ l = m.AuthUserRevokeRole.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthUserList != nil {
+ l = m.AuthUserList.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthRoleList != nil {
+ l = m.AuthRoleList.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthRoleAdd != nil {
+ l = m.AuthRoleAdd.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthRoleDelete != nil {
+ l = m.AuthRoleDelete.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthRoleGet != nil {
+ l = m.AuthRoleGet.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthRoleGrantPermission != nil {
+ l = m.AuthRoleGrantPermission.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ if m.AuthRoleRevokePermission != nil {
+ l = m.AuthRoleRevokePermission.Size()
+ n += 2 + l + sovRaftInternal(uint64(l))
+ }
+ return n
+}
+
+func (m *EmptyResponse) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *InternalAuthenticateRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ l = len(m.Password)
+ if l > 0 {
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ l = len(m.SimpleToken)
+ if l > 0 {
+ n += 1 + l + sovRaftInternal(uint64(l))
+ }
+ return n
+}
+
+func sovRaftInternal(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozRaftInternal(x uint64) (n int) {
+ return sovRaftInternal(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *RequestHeader) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: RequestHeader: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: RequestHeader: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Username", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Username = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthRevision", wireType)
+ }
+ m.AuthRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.AuthRevision |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaftInternal(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *InternalRaftRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: InternalRaftRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: InternalRaftRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field V2", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.V2 == nil {
+ m.V2 = &Request{}
+ }
+ if err := m.V2.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Range", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Range == nil {
+ m.Range = &RangeRequest{}
+ }
+ if err := m.Range.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Put", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Put == nil {
+ m.Put = &PutRequest{}
+ }
+ if err := m.Put.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DeleteRange", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.DeleteRange == nil {
+ m.DeleteRange = &DeleteRangeRequest{}
+ }
+ if err := m.DeleteRange.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Txn", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Txn == nil {
+ m.Txn = &TxnRequest{}
+ }
+ if err := m.Txn.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Compaction", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Compaction == nil {
+ m.Compaction = &CompactionRequest{}
+ }
+ if err := m.Compaction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LeaseGrant", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.LeaseGrant == nil {
+ m.LeaseGrant = &LeaseGrantRequest{}
+ }
+ if err := m.LeaseGrant.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LeaseRevoke", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.LeaseRevoke == nil {
+ m.LeaseRevoke = &LeaseRevokeRequest{}
+ }
+ if err := m.LeaseRevoke.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 10:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Alarm", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Alarm == nil {
+ m.Alarm = &AlarmRequest{}
+ }
+ if err := m.Alarm.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 100:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &RequestHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1000:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthEnable", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthEnable == nil {
+ m.AuthEnable = &AuthEnableRequest{}
+ }
+ if err := m.AuthEnable.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1011:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthDisable", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthDisable == nil {
+ m.AuthDisable = &AuthDisableRequest{}
+ }
+ if err := m.AuthDisable.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1012:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Authenticate", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Authenticate == nil {
+ m.Authenticate = &InternalAuthenticateRequest{}
+ }
+ if err := m.Authenticate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1100:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthUserAdd", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthUserAdd == nil {
+ m.AuthUserAdd = &AuthUserAddRequest{}
+ }
+ if err := m.AuthUserAdd.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1101:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthUserDelete", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthUserDelete == nil {
+ m.AuthUserDelete = &AuthUserDeleteRequest{}
+ }
+ if err := m.AuthUserDelete.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1102:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthUserGet", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthUserGet == nil {
+ m.AuthUserGet = &AuthUserGetRequest{}
+ }
+ if err := m.AuthUserGet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1103:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthUserChangePassword", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthUserChangePassword == nil {
+ m.AuthUserChangePassword = &AuthUserChangePasswordRequest{}
+ }
+ if err := m.AuthUserChangePassword.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1104:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthUserGrantRole", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthUserGrantRole == nil {
+ m.AuthUserGrantRole = &AuthUserGrantRoleRequest{}
+ }
+ if err := m.AuthUserGrantRole.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1105:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthUserRevokeRole", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthUserRevokeRole == nil {
+ m.AuthUserRevokeRole = &AuthUserRevokeRoleRequest{}
+ }
+ if err := m.AuthUserRevokeRole.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1106:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthUserList", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthUserList == nil {
+ m.AuthUserList = &AuthUserListRequest{}
+ }
+ if err := m.AuthUserList.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1107:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthRoleList", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthRoleList == nil {
+ m.AuthRoleList = &AuthRoleListRequest{}
+ }
+ if err := m.AuthRoleList.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1200:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthRoleAdd", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthRoleAdd == nil {
+ m.AuthRoleAdd = &AuthRoleAddRequest{}
+ }
+ if err := m.AuthRoleAdd.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1201:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthRoleDelete", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthRoleDelete == nil {
+ m.AuthRoleDelete = &AuthRoleDeleteRequest{}
+ }
+ if err := m.AuthRoleDelete.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1202:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthRoleGet", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthRoleGet == nil {
+ m.AuthRoleGet = &AuthRoleGetRequest{}
+ }
+ if err := m.AuthRoleGet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1203:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthRoleGrantPermission", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthRoleGrantPermission == nil {
+ m.AuthRoleGrantPermission = &AuthRoleGrantPermissionRequest{}
+ }
+ if err := m.AuthRoleGrantPermission.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 1204:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field AuthRoleRevokePermission", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.AuthRoleRevokePermission == nil {
+ m.AuthRoleRevokePermission = &AuthRoleRevokePermissionRequest{}
+ }
+ if err := m.AuthRoleRevokePermission.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaftInternal(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *EmptyResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: EmptyResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: EmptyResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaftInternal(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *InternalAuthenticateRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: InternalAuthenticateRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: InternalAuthenticateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Password = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field SimpleToken", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.SimpleToken = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaftInternal(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaftInternal
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipRaftInternal(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthRaftInternal
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaftInternal
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipRaftInternal(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthRaftInternal = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowRaftInternal = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("raft_internal.proto", fileDescriptorRaftInternal) }
+
+var fileDescriptorRaftInternal = []byte{
+ // 837 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x96, 0xdd, 0x52, 0xd3, 0x40,
+ 0x14, 0xc7, 0x69, 0xf9, 0xec, 0xb6, 0x54, 0x5c, 0x40, 0xd7, 0x32, 0x53, 0xa1, 0x8c, 0x8a, 0x5f,
+ 0xe8, 0x94, 0x07, 0xd0, 0x4a, 0x19, 0x60, 0x86, 0x61, 0x98, 0x0c, 0xce, 0x38, 0xe3, 0x45, 0x5c,
+ 0x9a, 0x43, 0x1b, 0x49, 0x93, 0xb8, 0xd9, 0x56, 0x7c, 0x13, 0x1f, 0xc3, 0xaf, 0x87, 0xe0, 0xc2,
+ 0x0f, 0xd4, 0x17, 0x50, 0xbc, 0xf1, 0xca, 0x1b, 0x7d, 0x00, 0x67, 0x3f, 0x92, 0x34, 0x6d, 0xca,
+ 0x5d, 0x72, 0xce, 0xff, 0xfc, 0xce, 0xd9, 0xec, 0x7f, 0xbb, 0x45, 0xb3, 0x8c, 0x1e, 0x72, 0xd3,
+ 0x76, 0x39, 0x30, 0x97, 0x3a, 0xab, 0x3e, 0xf3, 0xb8, 0x87, 0x0b, 0xc0, 0x1b, 0x56, 0x00, 0xac,
+ 0x0b, 0xcc, 0x3f, 0x28, 0xcd, 0x35, 0xbd, 0xa6, 0x27, 0x13, 0xf7, 0xc4, 0x93, 0xd2, 0x94, 0x66,
+ 0x62, 0x8d, 0x8e, 0xe4, 0x98, 0xdf, 0x50, 0x8f, 0x95, 0x67, 0x68, 0xda, 0x80, 0x17, 0x1d, 0x08,
+ 0xf8, 0x16, 0x50, 0x0b, 0x18, 0x2e, 0xa2, 0xec, 0x76, 0x9d, 0x64, 0x16, 0x33, 0x2b, 0x63, 0x46,
+ 0x76, 0xbb, 0x8e, 0x4b, 0x68, 0xaa, 0x13, 0x88, 0x96, 0x6d, 0x20, 0xd9, 0xc5, 0xcc, 0x4a, 0xce,
+ 0x88, 0xde, 0xf1, 0x32, 0x9a, 0xa6, 0x1d, 0xde, 0x32, 0x19, 0x74, 0xed, 0xc0, 0xf6, 0x5c, 0x32,
+ 0x2a, 0xcb, 0x0a, 0x22, 0x68, 0xe8, 0x58, 0xe5, 0x4f, 0x11, 0xcd, 0x6e, 0xeb, 0xa9, 0x0d, 0x7a,
+ 0xc8, 0x75, 0xbb, 0x81, 0x46, 0xd7, 0x50, 0xb6, 0x5b, 0x95, 0x2d, 0xf2, 0xd5, 0xf9, 0xd5, 0xde,
+ 0x75, 0xad, 0xea, 0x12, 0x23, 0xdb, 0xad, 0xe2, 0xfb, 0x68, 0x9c, 0x51, 0xb7, 0x09, 0xb2, 0x57,
+ 0xbe, 0x5a, 0xea, 0x53, 0x8a, 0x54, 0x28, 0x57, 0x42, 0x7c, 0x0b, 0x8d, 0xfa, 0x1d, 0x4e, 0xc6,
+ 0xa4, 0x9e, 0x24, 0xf5, 0x7b, 0x9d, 0x70, 0x1e, 0x43, 0x88, 0xf0, 0x3a, 0x2a, 0x58, 0xe0, 0x00,
+ 0x07, 0x53, 0x35, 0x19, 0x97, 0x45, 0x8b, 0xc9, 0xa2, 0xba, 0x54, 0x24, 0x5a, 0xe5, 0xad, 0x38,
+ 0x26, 0x1a, 0xf2, 0x63, 0x97, 0x4c, 0xa4, 0x35, 0xdc, 0x3f, 0x76, 0xa3, 0x86, 0xfc, 0xd8, 0xc5,
+ 0x0f, 0x10, 0x6a, 0x78, 0x6d, 0x9f, 0x36, 0xb8, 0xf8, 0x7e, 0x93, 0xb2, 0xe4, 0x6a, 0xb2, 0x64,
+ 0x3d, 0xca, 0x87, 0x95, 0x3d, 0x25, 0xf8, 0x21, 0xca, 0x3b, 0x40, 0x03, 0x30, 0x9b, 0x8c, 0xba,
+ 0x9c, 0x4c, 0xa5, 0x11, 0x76, 0x84, 0x60, 0x53, 0xe4, 0x23, 0x82, 0x13, 0x85, 0xc4, 0x9a, 0x15,
+ 0x81, 0x41, 0xd7, 0x3b, 0x02, 0x92, 0x4b, 0x5b, 0xb3, 0x44, 0x18, 0x52, 0x10, 0xad, 0xd9, 0x89,
+ 0x63, 0x62, 0x5b, 0xa8, 0x43, 0x59, 0x9b, 0xa0, 0xb4, 0x6d, 0xa9, 0x89, 0x54, 0xb4, 0x2d, 0x52,
+ 0x88, 0xd7, 0xd0, 0x44, 0x4b, 0x5a, 0x8e, 0x58, 0xb2, 0x64, 0x21, 0x75, 0xcf, 0x95, 0x2b, 0x0d,
+ 0x2d, 0xc5, 0x35, 0x94, 0x97, 0x8e, 0x03, 0x97, 0x1e, 0x38, 0x40, 0x7e, 0xa7, 0x7e, 0xb0, 0x5a,
+ 0x87, 0xb7, 0x36, 0xa4, 0x20, 0x5a, 0x2e, 0x8d, 0x42, 0xb8, 0x8e, 0xa4, 0x3f, 0x4d, 0xcb, 0x0e,
+ 0x24, 0xe3, 0xef, 0x64, 0xda, 0x7a, 0x05, 0xa3, 0xae, 0x14, 0xd1, 0x7a, 0x69, 0x1c, 0xc3, 0xbb,
+ 0x8a, 0x02, 0x2e, 0xb7, 0x1b, 0x94, 0x03, 0xf9, 0xa7, 0x28, 0x37, 0x93, 0x94, 0xd0, 0xf7, 0xb5,
+ 0x1e, 0x69, 0x88, 0x4b, 0xd4, 0xe3, 0x0d, 0x7d, 0x94, 0xc4, 0xd9, 0x32, 0xa9, 0x65, 0x91, 0x8f,
+ 0x53, 0xc3, 0xc6, 0x7a, 0x1c, 0x00, 0xab, 0x59, 0x56, 0x62, 0x2c, 0x1d, 0xc3, 0xbb, 0x68, 0x26,
+ 0xc6, 0x28, 0x4f, 0x92, 0x4f, 0x8a, 0xb4, 0x9c, 0x4e, 0xd2, 0x66, 0xd6, 0xb0, 0x22, 0x4d, 0x84,
+ 0x93, 0x63, 0x35, 0x81, 0x93, 0xcf, 0xe7, 0x8e, 0xb5, 0x09, 0x7c, 0x60, 0xac, 0x4d, 0xe0, 0xb8,
+ 0x89, 0xae, 0xc4, 0x98, 0x46, 0x4b, 0x9c, 0x12, 0xd3, 0xa7, 0x41, 0xf0, 0xd2, 0x63, 0x16, 0xf9,
+ 0xa2, 0x90, 0xb7, 0xd3, 0x91, 0xeb, 0x52, 0xbd, 0xa7, 0xc5, 0x21, 0xfd, 0x12, 0x4d, 0x4d, 0xe3,
+ 0x27, 0x68, 0xae, 0x67, 0x5e, 0x61, 0x6f, 0x93, 0x79, 0x0e, 0x90, 0x53, 0xd5, 0xe3, 0xfa, 0x90,
+ 0xb1, 0xe5, 0xd1, 0xf0, 0xe2, 0xad, 0xbe, 0x48, 0xfb, 0x33, 0xf8, 0x29, 0x9a, 0x8f, 0xc9, 0xea,
+ 0xa4, 0x28, 0xf4, 0x57, 0x85, 0xbe, 0x91, 0x8e, 0xd6, 0x47, 0xa6, 0x87, 0x8d, 0xe9, 0x40, 0x0a,
+ 0x6f, 0xa1, 0x62, 0x0c, 0x77, 0xec, 0x80, 0x93, 0x6f, 0x8a, 0xba, 0x94, 0x4e, 0xdd, 0xb1, 0x03,
+ 0x9e, 0xf0, 0x51, 0x18, 0x8c, 0x48, 0x62, 0x34, 0x45, 0xfa, 0x3e, 0x94, 0x24, 0x5a, 0x0f, 0x90,
+ 0xc2, 0x60, 0xb4, 0xf5, 0x92, 0x24, 0x1c, 0xf9, 0x26, 0x37, 0x6c, 0xeb, 0x45, 0x4d, 0xbf, 0x23,
+ 0x75, 0x2c, 0x72, 0xa4, 0xc4, 0x68, 0x47, 0xbe, 0xcd, 0x0d, 0x73, 0xa4, 0xa8, 0x4a, 0x71, 0x64,
+ 0x1c, 0x4e, 0x8e, 0x25, 0x1c, 0xf9, 0xee, 0xdc, 0xb1, 0xfa, 0x1d, 0xa9, 0x63, 0xf8, 0x39, 0x2a,
+ 0xf5, 0x60, 0xa4, 0x51, 0x7c, 0x60, 0x6d, 0x3b, 0x90, 0xf7, 0xd8, 0x7b, 0xc5, 0xbc, 0x33, 0x84,
+ 0x29, 0xe4, 0x7b, 0x91, 0x3a, 0xe4, 0x5f, 0xa6, 0xe9, 0x79, 0xdc, 0x46, 0x0b, 0x71, 0x2f, 0x6d,
+ 0x9d, 0x9e, 0x66, 0x1f, 0x54, 0xb3, 0xbb, 0xe9, 0xcd, 0x94, 0x4b, 0x06, 0xbb, 0x11, 0x3a, 0x44,
+ 0x50, 0xb9, 0x80, 0xa6, 0x37, 0xda, 0x3e, 0x7f, 0x65, 0x40, 0xe0, 0x7b, 0x6e, 0x00, 0x15, 0x1f,
+ 0x2d, 0x9c, 0xf3, 0x43, 0x84, 0x31, 0x1a, 0x93, 0xb7, 0x7b, 0x46, 0xde, 0xee, 0xf2, 0x59, 0xdc,
+ 0xfa, 0xd1, 0xf9, 0xd4, 0xb7, 0x7e, 0xf8, 0x8e, 0x97, 0x50, 0x21, 0xb0, 0xdb, 0xbe, 0x03, 0x26,
+ 0xf7, 0x8e, 0x40, 0x5d, 0xfa, 0x39, 0x23, 0xaf, 0x62, 0xfb, 0x22, 0xf4, 0x68, 0xee, 0xe4, 0x67,
+ 0x79, 0xe4, 0xe4, 0xac, 0x9c, 0x39, 0x3d, 0x2b, 0x67, 0x7e, 0x9c, 0x95, 0x33, 0xaf, 0x7f, 0x95,
+ 0x47, 0x0e, 0x26, 0xe4, 0x5f, 0x8e, 0xb5, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc9, 0xfc,
+ 0x0e, 0xca, 0x08, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
new file mode 100644
index 00000000..ec6b6397
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/raft_internal_stringer.go
@@ -0,0 +1,183 @@
+// Copyright 2018 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserverpb
+
+import (
+ "fmt"
+ "strings"
+
+ proto "github.com/golang/protobuf/proto"
+)
+
+// InternalRaftStringer implements custom proto Stringer:
+// redact password, replace value fields with value_size fields.
+type InternalRaftStringer struct {
+ Request *InternalRaftRequest
+}
+
+func (as *InternalRaftStringer) String() string {
+ switch {
+ case as.Request.LeaseGrant != nil:
+ return fmt.Sprintf("header:<%s> lease_grant:",
+ as.Request.Header.String(),
+ as.Request.LeaseGrant.TTL,
+ as.Request.LeaseGrant.ID,
+ )
+ case as.Request.LeaseRevoke != nil:
+ return fmt.Sprintf("header:<%s> lease_revoke:",
+ as.Request.Header.String(),
+ as.Request.LeaseRevoke.ID,
+ )
+ case as.Request.Authenticate != nil:
+ return fmt.Sprintf("header:<%s> authenticate:",
+ as.Request.Header.String(),
+ as.Request.Authenticate.Name,
+ as.Request.Authenticate.SimpleToken,
+ )
+ case as.Request.AuthUserAdd != nil:
+ return fmt.Sprintf("header:<%s> auth_user_add:",
+ as.Request.Header.String(),
+ as.Request.AuthUserAdd.Name,
+ )
+ case as.Request.AuthUserChangePassword != nil:
+ return fmt.Sprintf("header:<%s> auth_user_change_password:",
+ as.Request.Header.String(),
+ as.Request.AuthUserChangePassword.Name,
+ )
+ case as.Request.Put != nil:
+ return fmt.Sprintf("header:<%s> put:<%s>",
+ as.Request.Header.String(),
+ newLoggablePutRequest(as.Request.Put).String(),
+ )
+ case as.Request.Txn != nil:
+ return fmt.Sprintf("header:<%s> txn:<%s>",
+ as.Request.Header.String(),
+ NewLoggableTxnRequest(as.Request.Txn).String(),
+ )
+ default:
+ // nothing to redact
+ }
+ return as.Request.String()
+}
+
+// txnRequestStringer implements a custom proto String to replace value bytes fields with value size
+// fields in any nested txn and put operations.
+type txnRequestStringer struct {
+ Request *TxnRequest
+}
+
+func NewLoggableTxnRequest(request *TxnRequest) *txnRequestStringer {
+ return &txnRequestStringer{request}
+}
+
+func (as *txnRequestStringer) String() string {
+ var compare []string
+ for _, c := range as.Request.Compare {
+ switch cv := c.TargetUnion.(type) {
+ case *Compare_Value:
+ compare = append(compare, newLoggableValueCompare(c, cv).String())
+ default:
+ // nothing to redact
+ compare = append(compare, c.String())
+ }
+ }
+ var success []string
+ for _, s := range as.Request.Success {
+ success = append(success, newLoggableRequestOp(s).String())
+ }
+ var failure []string
+ for _, f := range as.Request.Failure {
+ failure = append(failure, newLoggableRequestOp(f).String())
+ }
+ return fmt.Sprintf("compare:<%s> success:<%s> failure:<%s>",
+ strings.Join(compare, " "),
+ strings.Join(success, " "),
+ strings.Join(failure, " "),
+ )
+}
+
+// requestOpStringer implements a custom proto String to replace value bytes fields with value
+// size fields in any nested txn and put operations.
+type requestOpStringer struct {
+ Op *RequestOp
+}
+
+func newLoggableRequestOp(op *RequestOp) *requestOpStringer {
+ return &requestOpStringer{op}
+}
+
+func (as *requestOpStringer) String() string {
+ switch op := as.Op.Request.(type) {
+ case *RequestOp_RequestPut:
+ return fmt.Sprintf("request_put:<%s>", newLoggablePutRequest(op.RequestPut).String())
+ case *RequestOp_RequestTxn:
+ return fmt.Sprintf("request_txn:<%s>", NewLoggableTxnRequest(op.RequestTxn).String())
+ default:
+ // nothing to redact
+ }
+ return as.Op.String()
+}
+
+// loggableValueCompare implements a custom proto String for Compare.Value union member types to
+// replace the value bytes field with a value size field.
+// To preserve proto encoding of the key and range_end bytes, a faked out proto type is used here.
+type loggableValueCompare struct {
+ Result Compare_CompareResult `protobuf:"varint,1,opt,name=result,proto3,enum=etcdserverpb.Compare_CompareResult"`
+ Target Compare_CompareTarget `protobuf:"varint,2,opt,name=target,proto3,enum=etcdserverpb.Compare_CompareTarget"`
+ Key []byte `protobuf:"bytes,3,opt,name=key,proto3"`
+ ValueSize int `protobuf:"bytes,7,opt,name=value_size,proto3"`
+ RangeEnd []byte `protobuf:"bytes,64,opt,name=range_end,proto3"`
+}
+
+func newLoggableValueCompare(c *Compare, cv *Compare_Value) *loggableValueCompare {
+ return &loggableValueCompare{
+ c.Result,
+ c.Target,
+ c.Key,
+ len(cv.Value),
+ c.RangeEnd,
+ }
+}
+
+func (m *loggableValueCompare) Reset() { *m = loggableValueCompare{} }
+func (m *loggableValueCompare) String() string { return proto.CompactTextString(m) }
+func (*loggableValueCompare) ProtoMessage() {}
+
+// loggablePutRequest implements a custom proto String to replace value bytes field with a value
+// size field.
+// To preserve proto encoding of the key bytes, a faked out proto type is used here.
+type loggablePutRequest struct {
+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3"`
+ ValueSize int `protobuf:"varint,2,opt,name=value_size,proto3"`
+ Lease int64 `protobuf:"varint,3,opt,name=lease,proto3"`
+ PrevKv bool `protobuf:"varint,4,opt,name=prev_kv,proto3"`
+ IgnoreValue bool `protobuf:"varint,5,opt,name=ignore_value,proto3"`
+ IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,proto3"`
+}
+
+func newLoggablePutRequest(request *PutRequest) *loggablePutRequest {
+ return &loggablePutRequest{
+ request.Key,
+ len(request.Value),
+ request.Lease,
+ request.PrevKv,
+ request.IgnoreValue,
+ request.IgnoreLease,
+ }
+}
+
+func (m *loggablePutRequest) Reset() { *m = loggablePutRequest{} }
+func (m *loggablePutRequest) String() string { return proto.CompactTextString(m) }
+func (*loggablePutRequest) ProtoMessage() {}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/rpc.pb.go b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/rpc.pb.go
new file mode 100644
index 00000000..40147f93
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/etcdserverpb/rpc.pb.go
@@ -0,0 +1,18665 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: rpc.proto
+
+package etcdserverpb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ mvccpb "github.com/coreos/etcd/mvcc/mvccpb"
+
+ authpb "github.com/coreos/etcd/auth/authpb"
+
+ context "golang.org/x/net/context"
+
+ grpc "google.golang.org/grpc"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+type AlarmType int32
+
+const (
+ AlarmType_NONE AlarmType = 0
+ AlarmType_NOSPACE AlarmType = 1
+ AlarmType_CORRUPT AlarmType = 2
+)
+
+var AlarmType_name = map[int32]string{
+ 0: "NONE",
+ 1: "NOSPACE",
+ 2: "CORRUPT",
+}
+var AlarmType_value = map[string]int32{
+ "NONE": 0,
+ "NOSPACE": 1,
+ "CORRUPT": 2,
+}
+
+func (x AlarmType) String() string {
+ return proto.EnumName(AlarmType_name, int32(x))
+}
+func (AlarmType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRpc, []int{0} }
+
+type RangeRequest_SortOrder int32
+
+const (
+ RangeRequest_NONE RangeRequest_SortOrder = 0
+ RangeRequest_ASCEND RangeRequest_SortOrder = 1
+ RangeRequest_DESCEND RangeRequest_SortOrder = 2
+)
+
+var RangeRequest_SortOrder_name = map[int32]string{
+ 0: "NONE",
+ 1: "ASCEND",
+ 2: "DESCEND",
+}
+var RangeRequest_SortOrder_value = map[string]int32{
+ "NONE": 0,
+ "ASCEND": 1,
+ "DESCEND": 2,
+}
+
+func (x RangeRequest_SortOrder) String() string {
+ return proto.EnumName(RangeRequest_SortOrder_name, int32(x))
+}
+func (RangeRequest_SortOrder) EnumDescriptor() ([]byte, []int) { return fileDescriptorRpc, []int{1, 0} }
+
+type RangeRequest_SortTarget int32
+
+const (
+ RangeRequest_KEY RangeRequest_SortTarget = 0
+ RangeRequest_VERSION RangeRequest_SortTarget = 1
+ RangeRequest_CREATE RangeRequest_SortTarget = 2
+ RangeRequest_MOD RangeRequest_SortTarget = 3
+ RangeRequest_VALUE RangeRequest_SortTarget = 4
+)
+
+var RangeRequest_SortTarget_name = map[int32]string{
+ 0: "KEY",
+ 1: "VERSION",
+ 2: "CREATE",
+ 3: "MOD",
+ 4: "VALUE",
+}
+var RangeRequest_SortTarget_value = map[string]int32{
+ "KEY": 0,
+ "VERSION": 1,
+ "CREATE": 2,
+ "MOD": 3,
+ "VALUE": 4,
+}
+
+func (x RangeRequest_SortTarget) String() string {
+ return proto.EnumName(RangeRequest_SortTarget_name, int32(x))
+}
+func (RangeRequest_SortTarget) EnumDescriptor() ([]byte, []int) { return fileDescriptorRpc, []int{1, 1} }
+
+type Compare_CompareResult int32
+
+const (
+ Compare_EQUAL Compare_CompareResult = 0
+ Compare_GREATER Compare_CompareResult = 1
+ Compare_LESS Compare_CompareResult = 2
+ Compare_NOT_EQUAL Compare_CompareResult = 3
+)
+
+var Compare_CompareResult_name = map[int32]string{
+ 0: "EQUAL",
+ 1: "GREATER",
+ 2: "LESS",
+ 3: "NOT_EQUAL",
+}
+var Compare_CompareResult_value = map[string]int32{
+ "EQUAL": 0,
+ "GREATER": 1,
+ "LESS": 2,
+ "NOT_EQUAL": 3,
+}
+
+func (x Compare_CompareResult) String() string {
+ return proto.EnumName(Compare_CompareResult_name, int32(x))
+}
+func (Compare_CompareResult) EnumDescriptor() ([]byte, []int) { return fileDescriptorRpc, []int{9, 0} }
+
+type Compare_CompareTarget int32
+
+const (
+ Compare_VERSION Compare_CompareTarget = 0
+ Compare_CREATE Compare_CompareTarget = 1
+ Compare_MOD Compare_CompareTarget = 2
+ Compare_VALUE Compare_CompareTarget = 3
+ Compare_LEASE Compare_CompareTarget = 4
+)
+
+var Compare_CompareTarget_name = map[int32]string{
+ 0: "VERSION",
+ 1: "CREATE",
+ 2: "MOD",
+ 3: "VALUE",
+ 4: "LEASE",
+}
+var Compare_CompareTarget_value = map[string]int32{
+ "VERSION": 0,
+ "CREATE": 1,
+ "MOD": 2,
+ "VALUE": 3,
+ "LEASE": 4,
+}
+
+func (x Compare_CompareTarget) String() string {
+ return proto.EnumName(Compare_CompareTarget_name, int32(x))
+}
+func (Compare_CompareTarget) EnumDescriptor() ([]byte, []int) { return fileDescriptorRpc, []int{9, 1} }
+
+type WatchCreateRequest_FilterType int32
+
+const (
+ // filter out put event.
+ WatchCreateRequest_NOPUT WatchCreateRequest_FilterType = 0
+ // filter out delete event.
+ WatchCreateRequest_NODELETE WatchCreateRequest_FilterType = 1
+)
+
+var WatchCreateRequest_FilterType_name = map[int32]string{
+ 0: "NOPUT",
+ 1: "NODELETE",
+}
+var WatchCreateRequest_FilterType_value = map[string]int32{
+ "NOPUT": 0,
+ "NODELETE": 1,
+}
+
+func (x WatchCreateRequest_FilterType) String() string {
+ return proto.EnumName(WatchCreateRequest_FilterType_name, int32(x))
+}
+func (WatchCreateRequest_FilterType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{21, 0}
+}
+
+type AlarmRequest_AlarmAction int32
+
+const (
+ AlarmRequest_GET AlarmRequest_AlarmAction = 0
+ AlarmRequest_ACTIVATE AlarmRequest_AlarmAction = 1
+ AlarmRequest_DEACTIVATE AlarmRequest_AlarmAction = 2
+)
+
+var AlarmRequest_AlarmAction_name = map[int32]string{
+ 0: "GET",
+ 1: "ACTIVATE",
+ 2: "DEACTIVATE",
+}
+var AlarmRequest_AlarmAction_value = map[string]int32{
+ "GET": 0,
+ "ACTIVATE": 1,
+ "DEACTIVATE": 2,
+}
+
+func (x AlarmRequest_AlarmAction) String() string {
+ return proto.EnumName(AlarmRequest_AlarmAction_name, int32(x))
+}
+func (AlarmRequest_AlarmAction) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{48, 0}
+}
+
+type ResponseHeader struct {
+ // cluster_id is the ID of the cluster which sent the response.
+ ClusterId uint64 `protobuf:"varint,1,opt,name=cluster_id,json=clusterId,proto3" json:"cluster_id,omitempty"`
+ // member_id is the ID of the member which sent the response.
+ MemberId uint64 `protobuf:"varint,2,opt,name=member_id,json=memberId,proto3" json:"member_id,omitempty"`
+ // revision is the key-value store revision when the request was applied.
+ Revision int64 `protobuf:"varint,3,opt,name=revision,proto3" json:"revision,omitempty"`
+ // raft_term is the raft term when the request was applied.
+ RaftTerm uint64 `protobuf:"varint,4,opt,name=raft_term,json=raftTerm,proto3" json:"raft_term,omitempty"`
+}
+
+func (m *ResponseHeader) Reset() { *m = ResponseHeader{} }
+func (m *ResponseHeader) String() string { return proto.CompactTextString(m) }
+func (*ResponseHeader) ProtoMessage() {}
+func (*ResponseHeader) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{0} }
+
+func (m *ResponseHeader) GetClusterId() uint64 {
+ if m != nil {
+ return m.ClusterId
+ }
+ return 0
+}
+
+func (m *ResponseHeader) GetMemberId() uint64 {
+ if m != nil {
+ return m.MemberId
+ }
+ return 0
+}
+
+func (m *ResponseHeader) GetRevision() int64 {
+ if m != nil {
+ return m.Revision
+ }
+ return 0
+}
+
+func (m *ResponseHeader) GetRaftTerm() uint64 {
+ if m != nil {
+ return m.RaftTerm
+ }
+ return 0
+}
+
+type RangeRequest struct {
+ // key is the first key for the range. If range_end is not given, the request only looks up key.
+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // range_end is the upper bound on the requested range [key, range_end).
+ // If range_end is '\0', the range is all keys >= key.
+ // If range_end is key plus one (e.g., "aa"+1 == "ab", "a\xff"+1 == "b"),
+ // then the range request gets all keys prefixed with key.
+ // If both key and range_end are '\0', then the range request returns all keys.
+ RangeEnd []byte `protobuf:"bytes,2,opt,name=range_end,json=rangeEnd,proto3" json:"range_end,omitempty"`
+ // limit is a limit on the number of keys returned for the request. When limit is set to 0,
+ // it is treated as no limit.
+ Limit int64 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"`
+ // revision is the point-in-time of the key-value store to use for the range.
+ // If revision is less or equal to zero, the range is over the newest key-value store.
+ // If the revision has been compacted, ErrCompacted is returned as a response.
+ Revision int64 `protobuf:"varint,4,opt,name=revision,proto3" json:"revision,omitempty"`
+ // sort_order is the order for returned sorted results.
+ SortOrder RangeRequest_SortOrder `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,proto3,enum=etcdserverpb.RangeRequest_SortOrder" json:"sort_order,omitempty"`
+ // sort_target is the key-value field to use for sorting.
+ SortTarget RangeRequest_SortTarget `protobuf:"varint,6,opt,name=sort_target,json=sortTarget,proto3,enum=etcdserverpb.RangeRequest_SortTarget" json:"sort_target,omitempty"`
+ // serializable sets the range request to use serializable member-local reads.
+ // Range requests are linearizable by default; linearizable requests have higher
+ // latency and lower throughput than serializable requests but reflect the current
+ // consensus of the cluster. For better performance, in exchange for possible stale reads,
+ // a serializable range request is served locally without needing to reach consensus
+ // with other nodes in the cluster.
+ Serializable bool `protobuf:"varint,7,opt,name=serializable,proto3" json:"serializable,omitempty"`
+ // keys_only when set returns only the keys and not the values.
+ KeysOnly bool `protobuf:"varint,8,opt,name=keys_only,json=keysOnly,proto3" json:"keys_only,omitempty"`
+ // count_only when set returns only the count of the keys in the range.
+ CountOnly bool `protobuf:"varint,9,opt,name=count_only,json=countOnly,proto3" json:"count_only,omitempty"`
+ // min_mod_revision is the lower bound for returned key mod revisions; all keys with
+ // lesser mod revisions will be filtered away.
+ MinModRevision int64 `protobuf:"varint,10,opt,name=min_mod_revision,json=minModRevision,proto3" json:"min_mod_revision,omitempty"`
+ // max_mod_revision is the upper bound for returned key mod revisions; all keys with
+ // greater mod revisions will be filtered away.
+ MaxModRevision int64 `protobuf:"varint,11,opt,name=max_mod_revision,json=maxModRevision,proto3" json:"max_mod_revision,omitempty"`
+ // min_create_revision is the lower bound for returned key create revisions; all keys with
+ // lesser create trevisions will be filtered away.
+ MinCreateRevision int64 `protobuf:"varint,12,opt,name=min_create_revision,json=minCreateRevision,proto3" json:"min_create_revision,omitempty"`
+ // max_create_revision is the upper bound for returned key create revisions; all keys with
+ // greater create revisions will be filtered away.
+ MaxCreateRevision int64 `protobuf:"varint,13,opt,name=max_create_revision,json=maxCreateRevision,proto3" json:"max_create_revision,omitempty"`
+}
+
+func (m *RangeRequest) Reset() { *m = RangeRequest{} }
+func (m *RangeRequest) String() string { return proto.CompactTextString(m) }
+func (*RangeRequest) ProtoMessage() {}
+func (*RangeRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{1} }
+
+func (m *RangeRequest) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+func (m *RangeRequest) GetRangeEnd() []byte {
+ if m != nil {
+ return m.RangeEnd
+ }
+ return nil
+}
+
+func (m *RangeRequest) GetLimit() int64 {
+ if m != nil {
+ return m.Limit
+ }
+ return 0
+}
+
+func (m *RangeRequest) GetRevision() int64 {
+ if m != nil {
+ return m.Revision
+ }
+ return 0
+}
+
+func (m *RangeRequest) GetSortOrder() RangeRequest_SortOrder {
+ if m != nil {
+ return m.SortOrder
+ }
+ return RangeRequest_NONE
+}
+
+func (m *RangeRequest) GetSortTarget() RangeRequest_SortTarget {
+ if m != nil {
+ return m.SortTarget
+ }
+ return RangeRequest_KEY
+}
+
+func (m *RangeRequest) GetSerializable() bool {
+ if m != nil {
+ return m.Serializable
+ }
+ return false
+}
+
+func (m *RangeRequest) GetKeysOnly() bool {
+ if m != nil {
+ return m.KeysOnly
+ }
+ return false
+}
+
+func (m *RangeRequest) GetCountOnly() bool {
+ if m != nil {
+ return m.CountOnly
+ }
+ return false
+}
+
+func (m *RangeRequest) GetMinModRevision() int64 {
+ if m != nil {
+ return m.MinModRevision
+ }
+ return 0
+}
+
+func (m *RangeRequest) GetMaxModRevision() int64 {
+ if m != nil {
+ return m.MaxModRevision
+ }
+ return 0
+}
+
+func (m *RangeRequest) GetMinCreateRevision() int64 {
+ if m != nil {
+ return m.MinCreateRevision
+ }
+ return 0
+}
+
+func (m *RangeRequest) GetMaxCreateRevision() int64 {
+ if m != nil {
+ return m.MaxCreateRevision
+ }
+ return 0
+}
+
+type RangeResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // kvs is the list of key-value pairs matched by the range request.
+ // kvs is empty when count is requested.
+ Kvs []*mvccpb.KeyValue `protobuf:"bytes,2,rep,name=kvs" json:"kvs,omitempty"`
+ // more indicates if there are more keys to return in the requested range.
+ More bool `protobuf:"varint,3,opt,name=more,proto3" json:"more,omitempty"`
+ // count is set to the number of keys within the range when requested.
+ Count int64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"`
+}
+
+func (m *RangeResponse) Reset() { *m = RangeResponse{} }
+func (m *RangeResponse) String() string { return proto.CompactTextString(m) }
+func (*RangeResponse) ProtoMessage() {}
+func (*RangeResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{2} }
+
+func (m *RangeResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *RangeResponse) GetKvs() []*mvccpb.KeyValue {
+ if m != nil {
+ return m.Kvs
+ }
+ return nil
+}
+
+func (m *RangeResponse) GetMore() bool {
+ if m != nil {
+ return m.More
+ }
+ return false
+}
+
+func (m *RangeResponse) GetCount() int64 {
+ if m != nil {
+ return m.Count
+ }
+ return 0
+}
+
+type PutRequest struct {
+ // key is the key, in bytes, to put into the key-value store.
+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // value is the value, in bytes, to associate with the key in the key-value store.
+ Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+ // lease is the lease ID to associate with the key in the key-value store. A lease
+ // value of 0 indicates no lease.
+ Lease int64 `protobuf:"varint,3,opt,name=lease,proto3" json:"lease,omitempty"`
+ // If prev_kv is set, etcd gets the previous key-value pair before changing it.
+ // The previous key-value pair will be returned in the put response.
+ PrevKv bool `protobuf:"varint,4,opt,name=prev_kv,json=prevKv,proto3" json:"prev_kv,omitempty"`
+ // If ignore_value is set, etcd updates the key using its current value.
+ // Returns an error if the key does not exist.
+ IgnoreValue bool `protobuf:"varint,5,opt,name=ignore_value,json=ignoreValue,proto3" json:"ignore_value,omitempty"`
+ // If ignore_lease is set, etcd updates the key using its current lease.
+ // Returns an error if the key does not exist.
+ IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,json=ignoreLease,proto3" json:"ignore_lease,omitempty"`
+}
+
+func (m *PutRequest) Reset() { *m = PutRequest{} }
+func (m *PutRequest) String() string { return proto.CompactTextString(m) }
+func (*PutRequest) ProtoMessage() {}
+func (*PutRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{3} }
+
+func (m *PutRequest) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+func (m *PutRequest) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (m *PutRequest) GetLease() int64 {
+ if m != nil {
+ return m.Lease
+ }
+ return 0
+}
+
+func (m *PutRequest) GetPrevKv() bool {
+ if m != nil {
+ return m.PrevKv
+ }
+ return false
+}
+
+func (m *PutRequest) GetIgnoreValue() bool {
+ if m != nil {
+ return m.IgnoreValue
+ }
+ return false
+}
+
+func (m *PutRequest) GetIgnoreLease() bool {
+ if m != nil {
+ return m.IgnoreLease
+ }
+ return false
+}
+
+type PutResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // if prev_kv is set in the request, the previous key-value pair will be returned.
+ PrevKv *mvccpb.KeyValue `protobuf:"bytes,2,opt,name=prev_kv,json=prevKv" json:"prev_kv,omitempty"`
+}
+
+func (m *PutResponse) Reset() { *m = PutResponse{} }
+func (m *PutResponse) String() string { return proto.CompactTextString(m) }
+func (*PutResponse) ProtoMessage() {}
+func (*PutResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{4} }
+
+func (m *PutResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *PutResponse) GetPrevKv() *mvccpb.KeyValue {
+ if m != nil {
+ return m.PrevKv
+ }
+ return nil
+}
+
+type DeleteRangeRequest struct {
+ // key is the first key to delete in the range.
+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // range_end is the key following the last key to delete for the range [key, range_end).
+ // If range_end is not given, the range is defined to contain only the key argument.
+ // If range_end is one bit larger than the given key, then the range is all the keys
+ // with the prefix (the given key).
+ // If range_end is '\0', the range is all keys greater than or equal to the key argument.
+ RangeEnd []byte `protobuf:"bytes,2,opt,name=range_end,json=rangeEnd,proto3" json:"range_end,omitempty"`
+ // If prev_kv is set, etcd gets the previous key-value pairs before deleting it.
+ // The previous key-value pairs will be returned in the delete response.
+ PrevKv bool `protobuf:"varint,3,opt,name=prev_kv,json=prevKv,proto3" json:"prev_kv,omitempty"`
+}
+
+func (m *DeleteRangeRequest) Reset() { *m = DeleteRangeRequest{} }
+func (m *DeleteRangeRequest) String() string { return proto.CompactTextString(m) }
+func (*DeleteRangeRequest) ProtoMessage() {}
+func (*DeleteRangeRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{5} }
+
+func (m *DeleteRangeRequest) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+func (m *DeleteRangeRequest) GetRangeEnd() []byte {
+ if m != nil {
+ return m.RangeEnd
+ }
+ return nil
+}
+
+func (m *DeleteRangeRequest) GetPrevKv() bool {
+ if m != nil {
+ return m.PrevKv
+ }
+ return false
+}
+
+type DeleteRangeResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // deleted is the number of keys deleted by the delete range request.
+ Deleted int64 `protobuf:"varint,2,opt,name=deleted,proto3" json:"deleted,omitempty"`
+ // if prev_kv is set in the request, the previous key-value pairs will be returned.
+ PrevKvs []*mvccpb.KeyValue `protobuf:"bytes,3,rep,name=prev_kvs,json=prevKvs" json:"prev_kvs,omitempty"`
+}
+
+func (m *DeleteRangeResponse) Reset() { *m = DeleteRangeResponse{} }
+func (m *DeleteRangeResponse) String() string { return proto.CompactTextString(m) }
+func (*DeleteRangeResponse) ProtoMessage() {}
+func (*DeleteRangeResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{6} }
+
+func (m *DeleteRangeResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *DeleteRangeResponse) GetDeleted() int64 {
+ if m != nil {
+ return m.Deleted
+ }
+ return 0
+}
+
+func (m *DeleteRangeResponse) GetPrevKvs() []*mvccpb.KeyValue {
+ if m != nil {
+ return m.PrevKvs
+ }
+ return nil
+}
+
+type RequestOp struct {
+ // request is a union of request types accepted by a transaction.
+ //
+ // Types that are valid to be assigned to Request:
+ // *RequestOp_RequestRange
+ // *RequestOp_RequestPut
+ // *RequestOp_RequestDeleteRange
+ // *RequestOp_RequestTxn
+ Request isRequestOp_Request `protobuf_oneof:"request"`
+}
+
+func (m *RequestOp) Reset() { *m = RequestOp{} }
+func (m *RequestOp) String() string { return proto.CompactTextString(m) }
+func (*RequestOp) ProtoMessage() {}
+func (*RequestOp) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{7} }
+
+type isRequestOp_Request interface {
+ isRequestOp_Request()
+ MarshalTo([]byte) (int, error)
+ Size() int
+}
+
+type RequestOp_RequestRange struct {
+ RequestRange *RangeRequest `protobuf:"bytes,1,opt,name=request_range,json=requestRange,oneof"`
+}
+type RequestOp_RequestPut struct {
+ RequestPut *PutRequest `protobuf:"bytes,2,opt,name=request_put,json=requestPut,oneof"`
+}
+type RequestOp_RequestDeleteRange struct {
+ RequestDeleteRange *DeleteRangeRequest `protobuf:"bytes,3,opt,name=request_delete_range,json=requestDeleteRange,oneof"`
+}
+type RequestOp_RequestTxn struct {
+ RequestTxn *TxnRequest `protobuf:"bytes,4,opt,name=request_txn,json=requestTxn,oneof"`
+}
+
+func (*RequestOp_RequestRange) isRequestOp_Request() {}
+func (*RequestOp_RequestPut) isRequestOp_Request() {}
+func (*RequestOp_RequestDeleteRange) isRequestOp_Request() {}
+func (*RequestOp_RequestTxn) isRequestOp_Request() {}
+
+func (m *RequestOp) GetRequest() isRequestOp_Request {
+ if m != nil {
+ return m.Request
+ }
+ return nil
+}
+
+func (m *RequestOp) GetRequestRange() *RangeRequest {
+ if x, ok := m.GetRequest().(*RequestOp_RequestRange); ok {
+ return x.RequestRange
+ }
+ return nil
+}
+
+func (m *RequestOp) GetRequestPut() *PutRequest {
+ if x, ok := m.GetRequest().(*RequestOp_RequestPut); ok {
+ return x.RequestPut
+ }
+ return nil
+}
+
+func (m *RequestOp) GetRequestDeleteRange() *DeleteRangeRequest {
+ if x, ok := m.GetRequest().(*RequestOp_RequestDeleteRange); ok {
+ return x.RequestDeleteRange
+ }
+ return nil
+}
+
+func (m *RequestOp) GetRequestTxn() *TxnRequest {
+ if x, ok := m.GetRequest().(*RequestOp_RequestTxn); ok {
+ return x.RequestTxn
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*RequestOp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _RequestOp_OneofMarshaler, _RequestOp_OneofUnmarshaler, _RequestOp_OneofSizer, []interface{}{
+ (*RequestOp_RequestRange)(nil),
+ (*RequestOp_RequestPut)(nil),
+ (*RequestOp_RequestDeleteRange)(nil),
+ (*RequestOp_RequestTxn)(nil),
+ }
+}
+
+func _RequestOp_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*RequestOp)
+ // request
+ switch x := m.Request.(type) {
+ case *RequestOp_RequestRange:
+ _ = b.EncodeVarint(1<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.RequestRange); err != nil {
+ return err
+ }
+ case *RequestOp_RequestPut:
+ _ = b.EncodeVarint(2<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.RequestPut); err != nil {
+ return err
+ }
+ case *RequestOp_RequestDeleteRange:
+ _ = b.EncodeVarint(3<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.RequestDeleteRange); err != nil {
+ return err
+ }
+ case *RequestOp_RequestTxn:
+ _ = b.EncodeVarint(4<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.RequestTxn); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("RequestOp.Request has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _RequestOp_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*RequestOp)
+ switch tag {
+ case 1: // request.request_range
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(RangeRequest)
+ err := b.DecodeMessage(msg)
+ m.Request = &RequestOp_RequestRange{msg}
+ return true, err
+ case 2: // request.request_put
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(PutRequest)
+ err := b.DecodeMessage(msg)
+ m.Request = &RequestOp_RequestPut{msg}
+ return true, err
+ case 3: // request.request_delete_range
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(DeleteRangeRequest)
+ err := b.DecodeMessage(msg)
+ m.Request = &RequestOp_RequestDeleteRange{msg}
+ return true, err
+ case 4: // request.request_txn
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(TxnRequest)
+ err := b.DecodeMessage(msg)
+ m.Request = &RequestOp_RequestTxn{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _RequestOp_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*RequestOp)
+ // request
+ switch x := m.Request.(type) {
+ case *RequestOp_RequestRange:
+ s := proto.Size(x.RequestRange)
+ n += proto.SizeVarint(1<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *RequestOp_RequestPut:
+ s := proto.Size(x.RequestPut)
+ n += proto.SizeVarint(2<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *RequestOp_RequestDeleteRange:
+ s := proto.Size(x.RequestDeleteRange)
+ n += proto.SizeVarint(3<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *RequestOp_RequestTxn:
+ s := proto.Size(x.RequestTxn)
+ n += proto.SizeVarint(4<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+type ResponseOp struct {
+ // response is a union of response types returned by a transaction.
+ //
+ // Types that are valid to be assigned to Response:
+ // *ResponseOp_ResponseRange
+ // *ResponseOp_ResponsePut
+ // *ResponseOp_ResponseDeleteRange
+ // *ResponseOp_ResponseTxn
+ Response isResponseOp_Response `protobuf_oneof:"response"`
+}
+
+func (m *ResponseOp) Reset() { *m = ResponseOp{} }
+func (m *ResponseOp) String() string { return proto.CompactTextString(m) }
+func (*ResponseOp) ProtoMessage() {}
+func (*ResponseOp) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{8} }
+
+type isResponseOp_Response interface {
+ isResponseOp_Response()
+ MarshalTo([]byte) (int, error)
+ Size() int
+}
+
+type ResponseOp_ResponseRange struct {
+ ResponseRange *RangeResponse `protobuf:"bytes,1,opt,name=response_range,json=responseRange,oneof"`
+}
+type ResponseOp_ResponsePut struct {
+ ResponsePut *PutResponse `protobuf:"bytes,2,opt,name=response_put,json=responsePut,oneof"`
+}
+type ResponseOp_ResponseDeleteRange struct {
+ ResponseDeleteRange *DeleteRangeResponse `protobuf:"bytes,3,opt,name=response_delete_range,json=responseDeleteRange,oneof"`
+}
+type ResponseOp_ResponseTxn struct {
+ ResponseTxn *TxnResponse `protobuf:"bytes,4,opt,name=response_txn,json=responseTxn,oneof"`
+}
+
+func (*ResponseOp_ResponseRange) isResponseOp_Response() {}
+func (*ResponseOp_ResponsePut) isResponseOp_Response() {}
+func (*ResponseOp_ResponseDeleteRange) isResponseOp_Response() {}
+func (*ResponseOp_ResponseTxn) isResponseOp_Response() {}
+
+func (m *ResponseOp) GetResponse() isResponseOp_Response {
+ if m != nil {
+ return m.Response
+ }
+ return nil
+}
+
+func (m *ResponseOp) GetResponseRange() *RangeResponse {
+ if x, ok := m.GetResponse().(*ResponseOp_ResponseRange); ok {
+ return x.ResponseRange
+ }
+ return nil
+}
+
+func (m *ResponseOp) GetResponsePut() *PutResponse {
+ if x, ok := m.GetResponse().(*ResponseOp_ResponsePut); ok {
+ return x.ResponsePut
+ }
+ return nil
+}
+
+func (m *ResponseOp) GetResponseDeleteRange() *DeleteRangeResponse {
+ if x, ok := m.GetResponse().(*ResponseOp_ResponseDeleteRange); ok {
+ return x.ResponseDeleteRange
+ }
+ return nil
+}
+
+func (m *ResponseOp) GetResponseTxn() *TxnResponse {
+ if x, ok := m.GetResponse().(*ResponseOp_ResponseTxn); ok {
+ return x.ResponseTxn
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*ResponseOp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _ResponseOp_OneofMarshaler, _ResponseOp_OneofUnmarshaler, _ResponseOp_OneofSizer, []interface{}{
+ (*ResponseOp_ResponseRange)(nil),
+ (*ResponseOp_ResponsePut)(nil),
+ (*ResponseOp_ResponseDeleteRange)(nil),
+ (*ResponseOp_ResponseTxn)(nil),
+ }
+}
+
+func _ResponseOp_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*ResponseOp)
+ // response
+ switch x := m.Response.(type) {
+ case *ResponseOp_ResponseRange:
+ _ = b.EncodeVarint(1<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ResponseRange); err != nil {
+ return err
+ }
+ case *ResponseOp_ResponsePut:
+ _ = b.EncodeVarint(2<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ResponsePut); err != nil {
+ return err
+ }
+ case *ResponseOp_ResponseDeleteRange:
+ _ = b.EncodeVarint(3<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ResponseDeleteRange); err != nil {
+ return err
+ }
+ case *ResponseOp_ResponseTxn:
+ _ = b.EncodeVarint(4<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ResponseTxn); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("ResponseOp.Response has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _ResponseOp_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*ResponseOp)
+ switch tag {
+ case 1: // response.response_range
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(RangeResponse)
+ err := b.DecodeMessage(msg)
+ m.Response = &ResponseOp_ResponseRange{msg}
+ return true, err
+ case 2: // response.response_put
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(PutResponse)
+ err := b.DecodeMessage(msg)
+ m.Response = &ResponseOp_ResponsePut{msg}
+ return true, err
+ case 3: // response.response_delete_range
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(DeleteRangeResponse)
+ err := b.DecodeMessage(msg)
+ m.Response = &ResponseOp_ResponseDeleteRange{msg}
+ return true, err
+ case 4: // response.response_txn
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(TxnResponse)
+ err := b.DecodeMessage(msg)
+ m.Response = &ResponseOp_ResponseTxn{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _ResponseOp_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*ResponseOp)
+ // response
+ switch x := m.Response.(type) {
+ case *ResponseOp_ResponseRange:
+ s := proto.Size(x.ResponseRange)
+ n += proto.SizeVarint(1<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *ResponseOp_ResponsePut:
+ s := proto.Size(x.ResponsePut)
+ n += proto.SizeVarint(2<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *ResponseOp_ResponseDeleteRange:
+ s := proto.Size(x.ResponseDeleteRange)
+ n += proto.SizeVarint(3<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *ResponseOp_ResponseTxn:
+ s := proto.Size(x.ResponseTxn)
+ n += proto.SizeVarint(4<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+type Compare struct {
+ // result is logical comparison operation for this comparison.
+ Result Compare_CompareResult `protobuf:"varint,1,opt,name=result,proto3,enum=etcdserverpb.Compare_CompareResult" json:"result,omitempty"`
+ // target is the key-value field to inspect for the comparison.
+ Target Compare_CompareTarget `protobuf:"varint,2,opt,name=target,proto3,enum=etcdserverpb.Compare_CompareTarget" json:"target,omitempty"`
+ // key is the subject key for the comparison operation.
+ Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"`
+ // Types that are valid to be assigned to TargetUnion:
+ // *Compare_Version
+ // *Compare_CreateRevision
+ // *Compare_ModRevision
+ // *Compare_Value
+ // *Compare_Lease
+ TargetUnion isCompare_TargetUnion `protobuf_oneof:"target_union"`
+ // range_end compares the given target to all keys in the range [key, range_end).
+ // See RangeRequest for more details on key ranges.
+ RangeEnd []byte `protobuf:"bytes,64,opt,name=range_end,json=rangeEnd,proto3" json:"range_end,omitempty"`
+}
+
+func (m *Compare) Reset() { *m = Compare{} }
+func (m *Compare) String() string { return proto.CompactTextString(m) }
+func (*Compare) ProtoMessage() {}
+func (*Compare) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{9} }
+
+type isCompare_TargetUnion interface {
+ isCompare_TargetUnion()
+ MarshalTo([]byte) (int, error)
+ Size() int
+}
+
+type Compare_Version struct {
+ Version int64 `protobuf:"varint,4,opt,name=version,proto3,oneof"`
+}
+type Compare_CreateRevision struct {
+ CreateRevision int64 `protobuf:"varint,5,opt,name=create_revision,json=createRevision,proto3,oneof"`
+}
+type Compare_ModRevision struct {
+ ModRevision int64 `protobuf:"varint,6,opt,name=mod_revision,json=modRevision,proto3,oneof"`
+}
+type Compare_Value struct {
+ Value []byte `protobuf:"bytes,7,opt,name=value,proto3,oneof"`
+}
+type Compare_Lease struct {
+ Lease int64 `protobuf:"varint,8,opt,name=lease,proto3,oneof"`
+}
+
+func (*Compare_Version) isCompare_TargetUnion() {}
+func (*Compare_CreateRevision) isCompare_TargetUnion() {}
+func (*Compare_ModRevision) isCompare_TargetUnion() {}
+func (*Compare_Value) isCompare_TargetUnion() {}
+func (*Compare_Lease) isCompare_TargetUnion() {}
+
+func (m *Compare) GetTargetUnion() isCompare_TargetUnion {
+ if m != nil {
+ return m.TargetUnion
+ }
+ return nil
+}
+
+func (m *Compare) GetResult() Compare_CompareResult {
+ if m != nil {
+ return m.Result
+ }
+ return Compare_EQUAL
+}
+
+func (m *Compare) GetTarget() Compare_CompareTarget {
+ if m != nil {
+ return m.Target
+ }
+ return Compare_VERSION
+}
+
+func (m *Compare) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+func (m *Compare) GetVersion() int64 {
+ if x, ok := m.GetTargetUnion().(*Compare_Version); ok {
+ return x.Version
+ }
+ return 0
+}
+
+func (m *Compare) GetCreateRevision() int64 {
+ if x, ok := m.GetTargetUnion().(*Compare_CreateRevision); ok {
+ return x.CreateRevision
+ }
+ return 0
+}
+
+func (m *Compare) GetModRevision() int64 {
+ if x, ok := m.GetTargetUnion().(*Compare_ModRevision); ok {
+ return x.ModRevision
+ }
+ return 0
+}
+
+func (m *Compare) GetValue() []byte {
+ if x, ok := m.GetTargetUnion().(*Compare_Value); ok {
+ return x.Value
+ }
+ return nil
+}
+
+func (m *Compare) GetLease() int64 {
+ if x, ok := m.GetTargetUnion().(*Compare_Lease); ok {
+ return x.Lease
+ }
+ return 0
+}
+
+func (m *Compare) GetRangeEnd() []byte {
+ if m != nil {
+ return m.RangeEnd
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*Compare) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _Compare_OneofMarshaler, _Compare_OneofUnmarshaler, _Compare_OneofSizer, []interface{}{
+ (*Compare_Version)(nil),
+ (*Compare_CreateRevision)(nil),
+ (*Compare_ModRevision)(nil),
+ (*Compare_Value)(nil),
+ (*Compare_Lease)(nil),
+ }
+}
+
+func _Compare_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*Compare)
+ // target_union
+ switch x := m.TargetUnion.(type) {
+ case *Compare_Version:
+ _ = b.EncodeVarint(4<<3 | proto.WireVarint)
+ _ = b.EncodeVarint(uint64(x.Version))
+ case *Compare_CreateRevision:
+ _ = b.EncodeVarint(5<<3 | proto.WireVarint)
+ _ = b.EncodeVarint(uint64(x.CreateRevision))
+ case *Compare_ModRevision:
+ _ = b.EncodeVarint(6<<3 | proto.WireVarint)
+ _ = b.EncodeVarint(uint64(x.ModRevision))
+ case *Compare_Value:
+ _ = b.EncodeVarint(7<<3 | proto.WireBytes)
+ _ = b.EncodeRawBytes(x.Value)
+ case *Compare_Lease:
+ _ = b.EncodeVarint(8<<3 | proto.WireVarint)
+ _ = b.EncodeVarint(uint64(x.Lease))
+ case nil:
+ default:
+ return fmt.Errorf("Compare.TargetUnion has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _Compare_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*Compare)
+ switch tag {
+ case 4: // target_union.version
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.TargetUnion = &Compare_Version{int64(x)}
+ return true, err
+ case 5: // target_union.create_revision
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.TargetUnion = &Compare_CreateRevision{int64(x)}
+ return true, err
+ case 6: // target_union.mod_revision
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.TargetUnion = &Compare_ModRevision{int64(x)}
+ return true, err
+ case 7: // target_union.value
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeRawBytes(true)
+ m.TargetUnion = &Compare_Value{x}
+ return true, err
+ case 8: // target_union.lease
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.TargetUnion = &Compare_Lease{int64(x)}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _Compare_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*Compare)
+ // target_union
+ switch x := m.TargetUnion.(type) {
+ case *Compare_Version:
+ n += proto.SizeVarint(4<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.Version))
+ case *Compare_CreateRevision:
+ n += proto.SizeVarint(5<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.CreateRevision))
+ case *Compare_ModRevision:
+ n += proto.SizeVarint(6<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.ModRevision))
+ case *Compare_Value:
+ n += proto.SizeVarint(7<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.Value)))
+ n += len(x.Value)
+ case *Compare_Lease:
+ n += proto.SizeVarint(8<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.Lease))
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+// From google paxosdb paper:
+// Our implementation hinges around a powerful primitive which we call MultiOp. All other database
+// operations except for iteration are implemented as a single call to MultiOp. A MultiOp is applied atomically
+// and consists of three components:
+// 1. A list of tests called guard. Each test in guard checks a single entry in the database. It may check
+// for the absence or presence of a value, or compare with a given value. Two different tests in the guard
+// may apply to the same or different entries in the database. All tests in the guard are applied and
+// MultiOp returns the results. If all tests are true, MultiOp executes t op (see item 2 below), otherwise
+// it executes f op (see item 3 below).
+// 2. A list of database operations called t op. Each operation in the list is either an insert, delete, or
+// lookup operation, and applies to a single database entry. Two different operations in the list may apply
+// to the same or different entries in the database. These operations are executed
+// if guard evaluates to
+// true.
+// 3. A list of database operations called f op. Like t op, but executed if guard evaluates to false.
+type TxnRequest struct {
+ // compare is a list of predicates representing a conjunction of terms.
+ // If the comparisons succeed, then the success requests will be processed in order,
+ // and the response will contain their respective responses in order.
+ // If the comparisons fail, then the failure requests will be processed in order,
+ // and the response will contain their respective responses in order.
+ Compare []*Compare `protobuf:"bytes,1,rep,name=compare" json:"compare,omitempty"`
+ // success is a list of requests which will be applied when compare evaluates to true.
+ Success []*RequestOp `protobuf:"bytes,2,rep,name=success" json:"success,omitempty"`
+ // failure is a list of requests which will be applied when compare evaluates to false.
+ Failure []*RequestOp `protobuf:"bytes,3,rep,name=failure" json:"failure,omitempty"`
+}
+
+func (m *TxnRequest) Reset() { *m = TxnRequest{} }
+func (m *TxnRequest) String() string { return proto.CompactTextString(m) }
+func (*TxnRequest) ProtoMessage() {}
+func (*TxnRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{10} }
+
+func (m *TxnRequest) GetCompare() []*Compare {
+ if m != nil {
+ return m.Compare
+ }
+ return nil
+}
+
+func (m *TxnRequest) GetSuccess() []*RequestOp {
+ if m != nil {
+ return m.Success
+ }
+ return nil
+}
+
+func (m *TxnRequest) GetFailure() []*RequestOp {
+ if m != nil {
+ return m.Failure
+ }
+ return nil
+}
+
+type TxnResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // succeeded is set to true if the compare evaluated to true or false otherwise.
+ Succeeded bool `protobuf:"varint,2,opt,name=succeeded,proto3" json:"succeeded,omitempty"`
+ // responses is a list of responses corresponding to the results from applying
+ // success if succeeded is true or failure if succeeded is false.
+ Responses []*ResponseOp `protobuf:"bytes,3,rep,name=responses" json:"responses,omitempty"`
+}
+
+func (m *TxnResponse) Reset() { *m = TxnResponse{} }
+func (m *TxnResponse) String() string { return proto.CompactTextString(m) }
+func (*TxnResponse) ProtoMessage() {}
+func (*TxnResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{11} }
+
+func (m *TxnResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *TxnResponse) GetSucceeded() bool {
+ if m != nil {
+ return m.Succeeded
+ }
+ return false
+}
+
+func (m *TxnResponse) GetResponses() []*ResponseOp {
+ if m != nil {
+ return m.Responses
+ }
+ return nil
+}
+
+// CompactionRequest compacts the key-value store up to a given revision. All superseded keys
+// with a revision less than the compaction revision will be removed.
+type CompactionRequest struct {
+ // revision is the key-value store revision for the compaction operation.
+ Revision int64 `protobuf:"varint,1,opt,name=revision,proto3" json:"revision,omitempty"`
+ // physical is set so the RPC will wait until the compaction is physically
+ // applied to the local database such that compacted entries are totally
+ // removed from the backend database.
+ Physical bool `protobuf:"varint,2,opt,name=physical,proto3" json:"physical,omitempty"`
+}
+
+func (m *CompactionRequest) Reset() { *m = CompactionRequest{} }
+func (m *CompactionRequest) String() string { return proto.CompactTextString(m) }
+func (*CompactionRequest) ProtoMessage() {}
+func (*CompactionRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{12} }
+
+func (m *CompactionRequest) GetRevision() int64 {
+ if m != nil {
+ return m.Revision
+ }
+ return 0
+}
+
+func (m *CompactionRequest) GetPhysical() bool {
+ if m != nil {
+ return m.Physical
+ }
+ return false
+}
+
+type CompactionResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *CompactionResponse) Reset() { *m = CompactionResponse{} }
+func (m *CompactionResponse) String() string { return proto.CompactTextString(m) }
+func (*CompactionResponse) ProtoMessage() {}
+func (*CompactionResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{13} }
+
+func (m *CompactionResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type HashRequest struct {
+}
+
+func (m *HashRequest) Reset() { *m = HashRequest{} }
+func (m *HashRequest) String() string { return proto.CompactTextString(m) }
+func (*HashRequest) ProtoMessage() {}
+func (*HashRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{14} }
+
+type HashKVRequest struct {
+ // revision is the key-value store revision for the hash operation.
+ Revision int64 `protobuf:"varint,1,opt,name=revision,proto3" json:"revision,omitempty"`
+}
+
+func (m *HashKVRequest) Reset() { *m = HashKVRequest{} }
+func (m *HashKVRequest) String() string { return proto.CompactTextString(m) }
+func (*HashKVRequest) ProtoMessage() {}
+func (*HashKVRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{15} }
+
+func (m *HashKVRequest) GetRevision() int64 {
+ if m != nil {
+ return m.Revision
+ }
+ return 0
+}
+
+type HashKVResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // hash is the hash value computed from the responding member's MVCC keys up to a given revision.
+ Hash uint32 `protobuf:"varint,2,opt,name=hash,proto3" json:"hash,omitempty"`
+ // compact_revision is the compacted revision of key-value store when hash begins.
+ CompactRevision int64 `protobuf:"varint,3,opt,name=compact_revision,json=compactRevision,proto3" json:"compact_revision,omitempty"`
+}
+
+func (m *HashKVResponse) Reset() { *m = HashKVResponse{} }
+func (m *HashKVResponse) String() string { return proto.CompactTextString(m) }
+func (*HashKVResponse) ProtoMessage() {}
+func (*HashKVResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{16} }
+
+func (m *HashKVResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *HashKVResponse) GetHash() uint32 {
+ if m != nil {
+ return m.Hash
+ }
+ return 0
+}
+
+func (m *HashKVResponse) GetCompactRevision() int64 {
+ if m != nil {
+ return m.CompactRevision
+ }
+ return 0
+}
+
+type HashResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // hash is the hash value computed from the responding member's KV's backend.
+ Hash uint32 `protobuf:"varint,2,opt,name=hash,proto3" json:"hash,omitempty"`
+}
+
+func (m *HashResponse) Reset() { *m = HashResponse{} }
+func (m *HashResponse) String() string { return proto.CompactTextString(m) }
+func (*HashResponse) ProtoMessage() {}
+func (*HashResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{17} }
+
+func (m *HashResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *HashResponse) GetHash() uint32 {
+ if m != nil {
+ return m.Hash
+ }
+ return 0
+}
+
+type SnapshotRequest struct {
+}
+
+func (m *SnapshotRequest) Reset() { *m = SnapshotRequest{} }
+func (m *SnapshotRequest) String() string { return proto.CompactTextString(m) }
+func (*SnapshotRequest) ProtoMessage() {}
+func (*SnapshotRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{18} }
+
+type SnapshotResponse struct {
+ // header has the current key-value store information. The first header in the snapshot
+ // stream indicates the point in time of the snapshot.
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // remaining_bytes is the number of blob bytes to be sent after this message
+ RemainingBytes uint64 `protobuf:"varint,2,opt,name=remaining_bytes,json=remainingBytes,proto3" json:"remaining_bytes,omitempty"`
+ // blob contains the next chunk of the snapshot in the snapshot stream.
+ Blob []byte `protobuf:"bytes,3,opt,name=blob,proto3" json:"blob,omitempty"`
+}
+
+func (m *SnapshotResponse) Reset() { *m = SnapshotResponse{} }
+func (m *SnapshotResponse) String() string { return proto.CompactTextString(m) }
+func (*SnapshotResponse) ProtoMessage() {}
+func (*SnapshotResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{19} }
+
+func (m *SnapshotResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *SnapshotResponse) GetRemainingBytes() uint64 {
+ if m != nil {
+ return m.RemainingBytes
+ }
+ return 0
+}
+
+func (m *SnapshotResponse) GetBlob() []byte {
+ if m != nil {
+ return m.Blob
+ }
+ return nil
+}
+
+type WatchRequest struct {
+ // request_union is a request to either create a new watcher or cancel an existing watcher.
+ //
+ // Types that are valid to be assigned to RequestUnion:
+ // *WatchRequest_CreateRequest
+ // *WatchRequest_CancelRequest
+ RequestUnion isWatchRequest_RequestUnion `protobuf_oneof:"request_union"`
+}
+
+func (m *WatchRequest) Reset() { *m = WatchRequest{} }
+func (m *WatchRequest) String() string { return proto.CompactTextString(m) }
+func (*WatchRequest) ProtoMessage() {}
+func (*WatchRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{20} }
+
+type isWatchRequest_RequestUnion interface {
+ isWatchRequest_RequestUnion()
+ MarshalTo([]byte) (int, error)
+ Size() int
+}
+
+type WatchRequest_CreateRequest struct {
+ CreateRequest *WatchCreateRequest `protobuf:"bytes,1,opt,name=create_request,json=createRequest,oneof"`
+}
+type WatchRequest_CancelRequest struct {
+ CancelRequest *WatchCancelRequest `protobuf:"bytes,2,opt,name=cancel_request,json=cancelRequest,oneof"`
+}
+
+func (*WatchRequest_CreateRequest) isWatchRequest_RequestUnion() {}
+func (*WatchRequest_CancelRequest) isWatchRequest_RequestUnion() {}
+
+func (m *WatchRequest) GetRequestUnion() isWatchRequest_RequestUnion {
+ if m != nil {
+ return m.RequestUnion
+ }
+ return nil
+}
+
+func (m *WatchRequest) GetCreateRequest() *WatchCreateRequest {
+ if x, ok := m.GetRequestUnion().(*WatchRequest_CreateRequest); ok {
+ return x.CreateRequest
+ }
+ return nil
+}
+
+func (m *WatchRequest) GetCancelRequest() *WatchCancelRequest {
+ if x, ok := m.GetRequestUnion().(*WatchRequest_CancelRequest); ok {
+ return x.CancelRequest
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*WatchRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _WatchRequest_OneofMarshaler, _WatchRequest_OneofUnmarshaler, _WatchRequest_OneofSizer, []interface{}{
+ (*WatchRequest_CreateRequest)(nil),
+ (*WatchRequest_CancelRequest)(nil),
+ }
+}
+
+func _WatchRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*WatchRequest)
+ // request_union
+ switch x := m.RequestUnion.(type) {
+ case *WatchRequest_CreateRequest:
+ _ = b.EncodeVarint(1<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.CreateRequest); err != nil {
+ return err
+ }
+ case *WatchRequest_CancelRequest:
+ _ = b.EncodeVarint(2<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.CancelRequest); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("WatchRequest.RequestUnion has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _WatchRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*WatchRequest)
+ switch tag {
+ case 1: // request_union.create_request
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(WatchCreateRequest)
+ err := b.DecodeMessage(msg)
+ m.RequestUnion = &WatchRequest_CreateRequest{msg}
+ return true, err
+ case 2: // request_union.cancel_request
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(WatchCancelRequest)
+ err := b.DecodeMessage(msg)
+ m.RequestUnion = &WatchRequest_CancelRequest{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _WatchRequest_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*WatchRequest)
+ // request_union
+ switch x := m.RequestUnion.(type) {
+ case *WatchRequest_CreateRequest:
+ s := proto.Size(x.CreateRequest)
+ n += proto.SizeVarint(1<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *WatchRequest_CancelRequest:
+ s := proto.Size(x.CancelRequest)
+ n += proto.SizeVarint(2<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+type WatchCreateRequest struct {
+ // key is the key to register for watching.
+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // range_end is the end of the range [key, range_end) to watch. If range_end is not given,
+ // only the key argument is watched. If range_end is equal to '\0', all keys greater than
+ // or equal to the key argument are watched.
+ // If the range_end is one bit larger than the given key,
+ // then all keys with the prefix (the given key) will be watched.
+ RangeEnd []byte `protobuf:"bytes,2,opt,name=range_end,json=rangeEnd,proto3" json:"range_end,omitempty"`
+ // start_revision is an optional revision to watch from (inclusive). No start_revision is "now".
+ StartRevision int64 `protobuf:"varint,3,opt,name=start_revision,json=startRevision,proto3" json:"start_revision,omitempty"`
+ // progress_notify is set so that the etcd server will periodically send a WatchResponse with
+ // no events to the new watcher if there are no recent events. It is useful when clients
+ // wish to recover a disconnected watcher starting from a recent known revision.
+ // The etcd server may decide how often it will send notifications based on current load.
+ ProgressNotify bool `protobuf:"varint,4,opt,name=progress_notify,json=progressNotify,proto3" json:"progress_notify,omitempty"`
+ // filters filter the events at server side before it sends back to the watcher.
+ Filters []WatchCreateRequest_FilterType `protobuf:"varint,5,rep,packed,name=filters,enum=etcdserverpb.WatchCreateRequest_FilterType" json:"filters,omitempty"`
+ // If prev_kv is set, created watcher gets the previous KV before the event happens.
+ // If the previous KV is already compacted, nothing will be returned.
+ PrevKv bool `protobuf:"varint,6,opt,name=prev_kv,json=prevKv,proto3" json:"prev_kv,omitempty"`
+}
+
+func (m *WatchCreateRequest) Reset() { *m = WatchCreateRequest{} }
+func (m *WatchCreateRequest) String() string { return proto.CompactTextString(m) }
+func (*WatchCreateRequest) ProtoMessage() {}
+func (*WatchCreateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{21} }
+
+func (m *WatchCreateRequest) GetKey() []byte {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+func (m *WatchCreateRequest) GetRangeEnd() []byte {
+ if m != nil {
+ return m.RangeEnd
+ }
+ return nil
+}
+
+func (m *WatchCreateRequest) GetStartRevision() int64 {
+ if m != nil {
+ return m.StartRevision
+ }
+ return 0
+}
+
+func (m *WatchCreateRequest) GetProgressNotify() bool {
+ if m != nil {
+ return m.ProgressNotify
+ }
+ return false
+}
+
+func (m *WatchCreateRequest) GetFilters() []WatchCreateRequest_FilterType {
+ if m != nil {
+ return m.Filters
+ }
+ return nil
+}
+
+func (m *WatchCreateRequest) GetPrevKv() bool {
+ if m != nil {
+ return m.PrevKv
+ }
+ return false
+}
+
+type WatchCancelRequest struct {
+ // watch_id is the watcher id to cancel so that no more events are transmitted.
+ WatchId int64 `protobuf:"varint,1,opt,name=watch_id,json=watchId,proto3" json:"watch_id,omitempty"`
+}
+
+func (m *WatchCancelRequest) Reset() { *m = WatchCancelRequest{} }
+func (m *WatchCancelRequest) String() string { return proto.CompactTextString(m) }
+func (*WatchCancelRequest) ProtoMessage() {}
+func (*WatchCancelRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{22} }
+
+func (m *WatchCancelRequest) GetWatchId() int64 {
+ if m != nil {
+ return m.WatchId
+ }
+ return 0
+}
+
+type WatchResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // watch_id is the ID of the watcher that corresponds to the response.
+ WatchId int64 `protobuf:"varint,2,opt,name=watch_id,json=watchId,proto3" json:"watch_id,omitempty"`
+ // created is set to true if the response is for a create watch request.
+ // The client should record the watch_id and expect to receive events for
+ // the created watcher from the same stream.
+ // All events sent to the created watcher will attach with the same watch_id.
+ Created bool `protobuf:"varint,3,opt,name=created,proto3" json:"created,omitempty"`
+ // canceled is set to true if the response is for a cancel watch request.
+ // No further events will be sent to the canceled watcher.
+ Canceled bool `protobuf:"varint,4,opt,name=canceled,proto3" json:"canceled,omitempty"`
+ // compact_revision is set to the minimum index if a watcher tries to watch
+ // at a compacted index.
+ //
+ // This happens when creating a watcher at a compacted revision or the watcher cannot
+ // catch up with the progress of the key-value store.
+ //
+ // The client should treat the watcher as canceled and should not try to create any
+ // watcher with the same start_revision again.
+ CompactRevision int64 `protobuf:"varint,5,opt,name=compact_revision,json=compactRevision,proto3" json:"compact_revision,omitempty"`
+ // cancel_reason indicates the reason for canceling the watcher.
+ CancelReason string `protobuf:"bytes,6,opt,name=cancel_reason,json=cancelReason,proto3" json:"cancel_reason,omitempty"`
+ Events []*mvccpb.Event `protobuf:"bytes,11,rep,name=events" json:"events,omitempty"`
+}
+
+func (m *WatchResponse) Reset() { *m = WatchResponse{} }
+func (m *WatchResponse) String() string { return proto.CompactTextString(m) }
+func (*WatchResponse) ProtoMessage() {}
+func (*WatchResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{23} }
+
+func (m *WatchResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *WatchResponse) GetWatchId() int64 {
+ if m != nil {
+ return m.WatchId
+ }
+ return 0
+}
+
+func (m *WatchResponse) GetCreated() bool {
+ if m != nil {
+ return m.Created
+ }
+ return false
+}
+
+func (m *WatchResponse) GetCanceled() bool {
+ if m != nil {
+ return m.Canceled
+ }
+ return false
+}
+
+func (m *WatchResponse) GetCompactRevision() int64 {
+ if m != nil {
+ return m.CompactRevision
+ }
+ return 0
+}
+
+func (m *WatchResponse) GetCancelReason() string {
+ if m != nil {
+ return m.CancelReason
+ }
+ return ""
+}
+
+func (m *WatchResponse) GetEvents() []*mvccpb.Event {
+ if m != nil {
+ return m.Events
+ }
+ return nil
+}
+
+type LeaseGrantRequest struct {
+ // TTL is the advisory time-to-live in seconds. Expired lease will return -1.
+ TTL int64 `protobuf:"varint,1,opt,name=TTL,proto3" json:"TTL,omitempty"`
+ // ID is the requested ID for the lease. If ID is set to 0, the lessor chooses an ID.
+ ID int64 `protobuf:"varint,2,opt,name=ID,proto3" json:"ID,omitempty"`
+}
+
+func (m *LeaseGrantRequest) Reset() { *m = LeaseGrantRequest{} }
+func (m *LeaseGrantRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaseGrantRequest) ProtoMessage() {}
+func (*LeaseGrantRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{24} }
+
+func (m *LeaseGrantRequest) GetTTL() int64 {
+ if m != nil {
+ return m.TTL
+ }
+ return 0
+}
+
+func (m *LeaseGrantRequest) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+type LeaseGrantResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // ID is the lease ID for the granted lease.
+ ID int64 `protobuf:"varint,2,opt,name=ID,proto3" json:"ID,omitempty"`
+ // TTL is the server chosen lease time-to-live in seconds.
+ TTL int64 `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
+ Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"`
+}
+
+func (m *LeaseGrantResponse) Reset() { *m = LeaseGrantResponse{} }
+func (m *LeaseGrantResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaseGrantResponse) ProtoMessage() {}
+func (*LeaseGrantResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{25} }
+
+func (m *LeaseGrantResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *LeaseGrantResponse) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+func (m *LeaseGrantResponse) GetTTL() int64 {
+ if m != nil {
+ return m.TTL
+ }
+ return 0
+}
+
+func (m *LeaseGrantResponse) GetError() string {
+ if m != nil {
+ return m.Error
+ }
+ return ""
+}
+
+type LeaseRevokeRequest struct {
+ // ID is the lease ID to revoke. When the ID is revoked, all associated keys will be deleted.
+ ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+}
+
+func (m *LeaseRevokeRequest) Reset() { *m = LeaseRevokeRequest{} }
+func (m *LeaseRevokeRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaseRevokeRequest) ProtoMessage() {}
+func (*LeaseRevokeRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{26} }
+
+func (m *LeaseRevokeRequest) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+type LeaseRevokeResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *LeaseRevokeResponse) Reset() { *m = LeaseRevokeResponse{} }
+func (m *LeaseRevokeResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaseRevokeResponse) ProtoMessage() {}
+func (*LeaseRevokeResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{27} }
+
+func (m *LeaseRevokeResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type LeaseKeepAliveRequest struct {
+ // ID is the lease ID for the lease to keep alive.
+ ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+}
+
+func (m *LeaseKeepAliveRequest) Reset() { *m = LeaseKeepAliveRequest{} }
+func (m *LeaseKeepAliveRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaseKeepAliveRequest) ProtoMessage() {}
+func (*LeaseKeepAliveRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{28} }
+
+func (m *LeaseKeepAliveRequest) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+type LeaseKeepAliveResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // ID is the lease ID from the keep alive request.
+ ID int64 `protobuf:"varint,2,opt,name=ID,proto3" json:"ID,omitempty"`
+ // TTL is the new time-to-live for the lease.
+ TTL int64 `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
+}
+
+func (m *LeaseKeepAliveResponse) Reset() { *m = LeaseKeepAliveResponse{} }
+func (m *LeaseKeepAliveResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaseKeepAliveResponse) ProtoMessage() {}
+func (*LeaseKeepAliveResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{29} }
+
+func (m *LeaseKeepAliveResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *LeaseKeepAliveResponse) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+func (m *LeaseKeepAliveResponse) GetTTL() int64 {
+ if m != nil {
+ return m.TTL
+ }
+ return 0
+}
+
+type LeaseTimeToLiveRequest struct {
+ // ID is the lease ID for the lease.
+ ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ // keys is true to query all the keys attached to this lease.
+ Keys bool `protobuf:"varint,2,opt,name=keys,proto3" json:"keys,omitempty"`
+}
+
+func (m *LeaseTimeToLiveRequest) Reset() { *m = LeaseTimeToLiveRequest{} }
+func (m *LeaseTimeToLiveRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaseTimeToLiveRequest) ProtoMessage() {}
+func (*LeaseTimeToLiveRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{30} }
+
+func (m *LeaseTimeToLiveRequest) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+func (m *LeaseTimeToLiveRequest) GetKeys() bool {
+ if m != nil {
+ return m.Keys
+ }
+ return false
+}
+
+type LeaseTimeToLiveResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // ID is the lease ID from the keep alive request.
+ ID int64 `protobuf:"varint,2,opt,name=ID,proto3" json:"ID,omitempty"`
+ // TTL is the remaining TTL in seconds for the lease; the lease will expire in under TTL+1 seconds.
+ TTL int64 `protobuf:"varint,3,opt,name=TTL,proto3" json:"TTL,omitempty"`
+ // GrantedTTL is the initial granted time in seconds upon lease creation/renewal.
+ GrantedTTL int64 `protobuf:"varint,4,opt,name=grantedTTL,proto3" json:"grantedTTL,omitempty"`
+ // Keys is the list of keys attached to this lease.
+ Keys [][]byte `protobuf:"bytes,5,rep,name=keys" json:"keys,omitempty"`
+}
+
+func (m *LeaseTimeToLiveResponse) Reset() { *m = LeaseTimeToLiveResponse{} }
+func (m *LeaseTimeToLiveResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaseTimeToLiveResponse) ProtoMessage() {}
+func (*LeaseTimeToLiveResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{31} }
+
+func (m *LeaseTimeToLiveResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *LeaseTimeToLiveResponse) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+func (m *LeaseTimeToLiveResponse) GetTTL() int64 {
+ if m != nil {
+ return m.TTL
+ }
+ return 0
+}
+
+func (m *LeaseTimeToLiveResponse) GetGrantedTTL() int64 {
+ if m != nil {
+ return m.GrantedTTL
+ }
+ return 0
+}
+
+func (m *LeaseTimeToLiveResponse) GetKeys() [][]byte {
+ if m != nil {
+ return m.Keys
+ }
+ return nil
+}
+
+type LeaseLeasesRequest struct {
+}
+
+func (m *LeaseLeasesRequest) Reset() { *m = LeaseLeasesRequest{} }
+func (m *LeaseLeasesRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaseLeasesRequest) ProtoMessage() {}
+func (*LeaseLeasesRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{32} }
+
+type LeaseStatus struct {
+ ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+}
+
+func (m *LeaseStatus) Reset() { *m = LeaseStatus{} }
+func (m *LeaseStatus) String() string { return proto.CompactTextString(m) }
+func (*LeaseStatus) ProtoMessage() {}
+func (*LeaseStatus) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{33} }
+
+func (m *LeaseStatus) GetID() int64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+type LeaseLeasesResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ Leases []*LeaseStatus `protobuf:"bytes,2,rep,name=leases" json:"leases,omitempty"`
+}
+
+func (m *LeaseLeasesResponse) Reset() { *m = LeaseLeasesResponse{} }
+func (m *LeaseLeasesResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaseLeasesResponse) ProtoMessage() {}
+func (*LeaseLeasesResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{34} }
+
+func (m *LeaseLeasesResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *LeaseLeasesResponse) GetLeases() []*LeaseStatus {
+ if m != nil {
+ return m.Leases
+ }
+ return nil
+}
+
+type Member struct {
+ // ID is the member ID for this member.
+ ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ // name is the human-readable name of the member. If the member is not started, the name will be an empty string.
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ // peerURLs is the list of URLs the member exposes to the cluster for communication.
+ PeerURLs []string `protobuf:"bytes,3,rep,name=peerURLs" json:"peerURLs,omitempty"`
+ // clientURLs is the list of URLs the member exposes to clients for communication. If the member is not started, clientURLs will be empty.
+ ClientURLs []string `protobuf:"bytes,4,rep,name=clientURLs" json:"clientURLs,omitempty"`
+}
+
+func (m *Member) Reset() { *m = Member{} }
+func (m *Member) String() string { return proto.CompactTextString(m) }
+func (*Member) ProtoMessage() {}
+func (*Member) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{35} }
+
+func (m *Member) GetID() uint64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+func (m *Member) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *Member) GetPeerURLs() []string {
+ if m != nil {
+ return m.PeerURLs
+ }
+ return nil
+}
+
+func (m *Member) GetClientURLs() []string {
+ if m != nil {
+ return m.ClientURLs
+ }
+ return nil
+}
+
+type MemberAddRequest struct {
+ // peerURLs is the list of URLs the added member will use to communicate with the cluster.
+ PeerURLs []string `protobuf:"bytes,1,rep,name=peerURLs" json:"peerURLs,omitempty"`
+}
+
+func (m *MemberAddRequest) Reset() { *m = MemberAddRequest{} }
+func (m *MemberAddRequest) String() string { return proto.CompactTextString(m) }
+func (*MemberAddRequest) ProtoMessage() {}
+func (*MemberAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{36} }
+
+func (m *MemberAddRequest) GetPeerURLs() []string {
+ if m != nil {
+ return m.PeerURLs
+ }
+ return nil
+}
+
+type MemberAddResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // member is the member information for the added member.
+ Member *Member `protobuf:"bytes,2,opt,name=member" json:"member,omitempty"`
+ // members is a list of all members after adding the new member.
+ Members []*Member `protobuf:"bytes,3,rep,name=members" json:"members,omitempty"`
+}
+
+func (m *MemberAddResponse) Reset() { *m = MemberAddResponse{} }
+func (m *MemberAddResponse) String() string { return proto.CompactTextString(m) }
+func (*MemberAddResponse) ProtoMessage() {}
+func (*MemberAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{37} }
+
+func (m *MemberAddResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *MemberAddResponse) GetMember() *Member {
+ if m != nil {
+ return m.Member
+ }
+ return nil
+}
+
+func (m *MemberAddResponse) GetMembers() []*Member {
+ if m != nil {
+ return m.Members
+ }
+ return nil
+}
+
+type MemberRemoveRequest struct {
+ // ID is the member ID of the member to remove.
+ ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+}
+
+func (m *MemberRemoveRequest) Reset() { *m = MemberRemoveRequest{} }
+func (m *MemberRemoveRequest) String() string { return proto.CompactTextString(m) }
+func (*MemberRemoveRequest) ProtoMessage() {}
+func (*MemberRemoveRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{38} }
+
+func (m *MemberRemoveRequest) GetID() uint64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+type MemberRemoveResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // members is a list of all members after removing the member.
+ Members []*Member `protobuf:"bytes,2,rep,name=members" json:"members,omitempty"`
+}
+
+func (m *MemberRemoveResponse) Reset() { *m = MemberRemoveResponse{} }
+func (m *MemberRemoveResponse) String() string { return proto.CompactTextString(m) }
+func (*MemberRemoveResponse) ProtoMessage() {}
+func (*MemberRemoveResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{39} }
+
+func (m *MemberRemoveResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *MemberRemoveResponse) GetMembers() []*Member {
+ if m != nil {
+ return m.Members
+ }
+ return nil
+}
+
+type MemberUpdateRequest struct {
+ // ID is the member ID of the member to update.
+ ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ // peerURLs is the new list of URLs the member will use to communicate with the cluster.
+ PeerURLs []string `protobuf:"bytes,2,rep,name=peerURLs" json:"peerURLs,omitempty"`
+}
+
+func (m *MemberUpdateRequest) Reset() { *m = MemberUpdateRequest{} }
+func (m *MemberUpdateRequest) String() string { return proto.CompactTextString(m) }
+func (*MemberUpdateRequest) ProtoMessage() {}
+func (*MemberUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{40} }
+
+func (m *MemberUpdateRequest) GetID() uint64 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+func (m *MemberUpdateRequest) GetPeerURLs() []string {
+ if m != nil {
+ return m.PeerURLs
+ }
+ return nil
+}
+
+type MemberUpdateResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // members is a list of all members after updating the member.
+ Members []*Member `protobuf:"bytes,2,rep,name=members" json:"members,omitempty"`
+}
+
+func (m *MemberUpdateResponse) Reset() { *m = MemberUpdateResponse{} }
+func (m *MemberUpdateResponse) String() string { return proto.CompactTextString(m) }
+func (*MemberUpdateResponse) ProtoMessage() {}
+func (*MemberUpdateResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{41} }
+
+func (m *MemberUpdateResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *MemberUpdateResponse) GetMembers() []*Member {
+ if m != nil {
+ return m.Members
+ }
+ return nil
+}
+
+type MemberListRequest struct {
+}
+
+func (m *MemberListRequest) Reset() { *m = MemberListRequest{} }
+func (m *MemberListRequest) String() string { return proto.CompactTextString(m) }
+func (*MemberListRequest) ProtoMessage() {}
+func (*MemberListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{42} }
+
+type MemberListResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // members is a list of all members associated with the cluster.
+ Members []*Member `protobuf:"bytes,2,rep,name=members" json:"members,omitempty"`
+}
+
+func (m *MemberListResponse) Reset() { *m = MemberListResponse{} }
+func (m *MemberListResponse) String() string { return proto.CompactTextString(m) }
+func (*MemberListResponse) ProtoMessage() {}
+func (*MemberListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{43} }
+
+func (m *MemberListResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *MemberListResponse) GetMembers() []*Member {
+ if m != nil {
+ return m.Members
+ }
+ return nil
+}
+
+type DefragmentRequest struct {
+}
+
+func (m *DefragmentRequest) Reset() { *m = DefragmentRequest{} }
+func (m *DefragmentRequest) String() string { return proto.CompactTextString(m) }
+func (*DefragmentRequest) ProtoMessage() {}
+func (*DefragmentRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{44} }
+
+type DefragmentResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *DefragmentResponse) Reset() { *m = DefragmentResponse{} }
+func (m *DefragmentResponse) String() string { return proto.CompactTextString(m) }
+func (*DefragmentResponse) ProtoMessage() {}
+func (*DefragmentResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{45} }
+
+func (m *DefragmentResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type MoveLeaderRequest struct {
+ // targetID is the node ID for the new leader.
+ TargetID uint64 `protobuf:"varint,1,opt,name=targetID,proto3" json:"targetID,omitempty"`
+}
+
+func (m *MoveLeaderRequest) Reset() { *m = MoveLeaderRequest{} }
+func (m *MoveLeaderRequest) String() string { return proto.CompactTextString(m) }
+func (*MoveLeaderRequest) ProtoMessage() {}
+func (*MoveLeaderRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{46} }
+
+func (m *MoveLeaderRequest) GetTargetID() uint64 {
+ if m != nil {
+ return m.TargetID
+ }
+ return 0
+}
+
+type MoveLeaderResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *MoveLeaderResponse) Reset() { *m = MoveLeaderResponse{} }
+func (m *MoveLeaderResponse) String() string { return proto.CompactTextString(m) }
+func (*MoveLeaderResponse) ProtoMessage() {}
+func (*MoveLeaderResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{47} }
+
+func (m *MoveLeaderResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AlarmRequest struct {
+ // action is the kind of alarm request to issue. The action
+ // may GET alarm statuses, ACTIVATE an alarm, or DEACTIVATE a
+ // raised alarm.
+ Action AlarmRequest_AlarmAction `protobuf:"varint,1,opt,name=action,proto3,enum=etcdserverpb.AlarmRequest_AlarmAction" json:"action,omitempty"`
+ // memberID is the ID of the member associated with the alarm. If memberID is 0, the
+ // alarm request covers all members.
+ MemberID uint64 `protobuf:"varint,2,opt,name=memberID,proto3" json:"memberID,omitempty"`
+ // alarm is the type of alarm to consider for this request.
+ Alarm AlarmType `protobuf:"varint,3,opt,name=alarm,proto3,enum=etcdserverpb.AlarmType" json:"alarm,omitempty"`
+}
+
+func (m *AlarmRequest) Reset() { *m = AlarmRequest{} }
+func (m *AlarmRequest) String() string { return proto.CompactTextString(m) }
+func (*AlarmRequest) ProtoMessage() {}
+func (*AlarmRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{48} }
+
+func (m *AlarmRequest) GetAction() AlarmRequest_AlarmAction {
+ if m != nil {
+ return m.Action
+ }
+ return AlarmRequest_GET
+}
+
+func (m *AlarmRequest) GetMemberID() uint64 {
+ if m != nil {
+ return m.MemberID
+ }
+ return 0
+}
+
+func (m *AlarmRequest) GetAlarm() AlarmType {
+ if m != nil {
+ return m.Alarm
+ }
+ return AlarmType_NONE
+}
+
+type AlarmMember struct {
+ // memberID is the ID of the member associated with the raised alarm.
+ MemberID uint64 `protobuf:"varint,1,opt,name=memberID,proto3" json:"memberID,omitempty"`
+ // alarm is the type of alarm which has been raised.
+ Alarm AlarmType `protobuf:"varint,2,opt,name=alarm,proto3,enum=etcdserverpb.AlarmType" json:"alarm,omitempty"`
+}
+
+func (m *AlarmMember) Reset() { *m = AlarmMember{} }
+func (m *AlarmMember) String() string { return proto.CompactTextString(m) }
+func (*AlarmMember) ProtoMessage() {}
+func (*AlarmMember) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{49} }
+
+func (m *AlarmMember) GetMemberID() uint64 {
+ if m != nil {
+ return m.MemberID
+ }
+ return 0
+}
+
+func (m *AlarmMember) GetAlarm() AlarmType {
+ if m != nil {
+ return m.Alarm
+ }
+ return AlarmType_NONE
+}
+
+type AlarmResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // alarms is a list of alarms associated with the alarm request.
+ Alarms []*AlarmMember `protobuf:"bytes,2,rep,name=alarms" json:"alarms,omitempty"`
+}
+
+func (m *AlarmResponse) Reset() { *m = AlarmResponse{} }
+func (m *AlarmResponse) String() string { return proto.CompactTextString(m) }
+func (*AlarmResponse) ProtoMessage() {}
+func (*AlarmResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{50} }
+
+func (m *AlarmResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *AlarmResponse) GetAlarms() []*AlarmMember {
+ if m != nil {
+ return m.Alarms
+ }
+ return nil
+}
+
+type StatusRequest struct {
+}
+
+func (m *StatusRequest) Reset() { *m = StatusRequest{} }
+func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
+func (*StatusRequest) ProtoMessage() {}
+func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{51} }
+
+type StatusResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // version is the cluster protocol version used by the responding member.
+ Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
+ // dbSize is the size of the backend database, in bytes, of the responding member.
+ DbSize int64 `protobuf:"varint,3,opt,name=dbSize,proto3" json:"dbSize,omitempty"`
+ // leader is the member ID which the responding member believes is the current leader.
+ Leader uint64 `protobuf:"varint,4,opt,name=leader,proto3" json:"leader,omitempty"`
+ // raftIndex is the current raft index of the responding member.
+ RaftIndex uint64 `protobuf:"varint,5,opt,name=raftIndex,proto3" json:"raftIndex,omitempty"`
+ // raftTerm is the current raft term of the responding member.
+ RaftTerm uint64 `protobuf:"varint,6,opt,name=raftTerm,proto3" json:"raftTerm,omitempty"`
+}
+
+func (m *StatusResponse) Reset() { *m = StatusResponse{} }
+func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
+func (*StatusResponse) ProtoMessage() {}
+func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{52} }
+
+func (m *StatusResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *StatusResponse) GetVersion() string {
+ if m != nil {
+ return m.Version
+ }
+ return ""
+}
+
+func (m *StatusResponse) GetDbSize() int64 {
+ if m != nil {
+ return m.DbSize
+ }
+ return 0
+}
+
+func (m *StatusResponse) GetLeader() uint64 {
+ if m != nil {
+ return m.Leader
+ }
+ return 0
+}
+
+func (m *StatusResponse) GetRaftIndex() uint64 {
+ if m != nil {
+ return m.RaftIndex
+ }
+ return 0
+}
+
+func (m *StatusResponse) GetRaftTerm() uint64 {
+ if m != nil {
+ return m.RaftTerm
+ }
+ return 0
+}
+
+type AuthEnableRequest struct {
+}
+
+func (m *AuthEnableRequest) Reset() { *m = AuthEnableRequest{} }
+func (m *AuthEnableRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthEnableRequest) ProtoMessage() {}
+func (*AuthEnableRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{53} }
+
+type AuthDisableRequest struct {
+}
+
+func (m *AuthDisableRequest) Reset() { *m = AuthDisableRequest{} }
+func (m *AuthDisableRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthDisableRequest) ProtoMessage() {}
+func (*AuthDisableRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{54} }
+
+type AuthenticateRequest struct {
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+}
+
+func (m *AuthenticateRequest) Reset() { *m = AuthenticateRequest{} }
+func (m *AuthenticateRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthenticateRequest) ProtoMessage() {}
+func (*AuthenticateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{55} }
+
+func (m *AuthenticateRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *AuthenticateRequest) GetPassword() string {
+ if m != nil {
+ return m.Password
+ }
+ return ""
+}
+
+type AuthUserAddRequest struct {
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+}
+
+func (m *AuthUserAddRequest) Reset() { *m = AuthUserAddRequest{} }
+func (m *AuthUserAddRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthUserAddRequest) ProtoMessage() {}
+func (*AuthUserAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{56} }
+
+func (m *AuthUserAddRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *AuthUserAddRequest) GetPassword() string {
+ if m != nil {
+ return m.Password
+ }
+ return ""
+}
+
+type AuthUserGetRequest struct {
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (m *AuthUserGetRequest) Reset() { *m = AuthUserGetRequest{} }
+func (m *AuthUserGetRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthUserGetRequest) ProtoMessage() {}
+func (*AuthUserGetRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{57} }
+
+func (m *AuthUserGetRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+type AuthUserDeleteRequest struct {
+ // name is the name of the user to delete.
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (m *AuthUserDeleteRequest) Reset() { *m = AuthUserDeleteRequest{} }
+func (m *AuthUserDeleteRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthUserDeleteRequest) ProtoMessage() {}
+func (*AuthUserDeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{58} }
+
+func (m *AuthUserDeleteRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+type AuthUserChangePasswordRequest struct {
+ // name is the name of the user whose password is being changed.
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // password is the new password for the user.
+ Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+}
+
+func (m *AuthUserChangePasswordRequest) Reset() { *m = AuthUserChangePasswordRequest{} }
+func (m *AuthUserChangePasswordRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthUserChangePasswordRequest) ProtoMessage() {}
+func (*AuthUserChangePasswordRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{59}
+}
+
+func (m *AuthUserChangePasswordRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *AuthUserChangePasswordRequest) GetPassword() string {
+ if m != nil {
+ return m.Password
+ }
+ return ""
+}
+
+type AuthUserGrantRoleRequest struct {
+ // user is the name of the user which should be granted a given role.
+ User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
+ // role is the name of the role to grant to the user.
+ Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"`
+}
+
+func (m *AuthUserGrantRoleRequest) Reset() { *m = AuthUserGrantRoleRequest{} }
+func (m *AuthUserGrantRoleRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthUserGrantRoleRequest) ProtoMessage() {}
+func (*AuthUserGrantRoleRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{60} }
+
+func (m *AuthUserGrantRoleRequest) GetUser() string {
+ if m != nil {
+ return m.User
+ }
+ return ""
+}
+
+func (m *AuthUserGrantRoleRequest) GetRole() string {
+ if m != nil {
+ return m.Role
+ }
+ return ""
+}
+
+type AuthUserRevokeRoleRequest struct {
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"`
+}
+
+func (m *AuthUserRevokeRoleRequest) Reset() { *m = AuthUserRevokeRoleRequest{} }
+func (m *AuthUserRevokeRoleRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthUserRevokeRoleRequest) ProtoMessage() {}
+func (*AuthUserRevokeRoleRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{61} }
+
+func (m *AuthUserRevokeRoleRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *AuthUserRevokeRoleRequest) GetRole() string {
+ if m != nil {
+ return m.Role
+ }
+ return ""
+}
+
+type AuthRoleAddRequest struct {
+ // name is the name of the role to add to the authentication system.
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (m *AuthRoleAddRequest) Reset() { *m = AuthRoleAddRequest{} }
+func (m *AuthRoleAddRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleAddRequest) ProtoMessage() {}
+func (*AuthRoleAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{62} }
+
+func (m *AuthRoleAddRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+type AuthRoleGetRequest struct {
+ Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"`
+}
+
+func (m *AuthRoleGetRequest) Reset() { *m = AuthRoleGetRequest{} }
+func (m *AuthRoleGetRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleGetRequest) ProtoMessage() {}
+func (*AuthRoleGetRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{63} }
+
+func (m *AuthRoleGetRequest) GetRole() string {
+ if m != nil {
+ return m.Role
+ }
+ return ""
+}
+
+type AuthUserListRequest struct {
+}
+
+func (m *AuthUserListRequest) Reset() { *m = AuthUserListRequest{} }
+func (m *AuthUserListRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthUserListRequest) ProtoMessage() {}
+func (*AuthUserListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{64} }
+
+type AuthRoleListRequest struct {
+}
+
+func (m *AuthRoleListRequest) Reset() { *m = AuthRoleListRequest{} }
+func (m *AuthRoleListRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleListRequest) ProtoMessage() {}
+func (*AuthRoleListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{65} }
+
+type AuthRoleDeleteRequest struct {
+ Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"`
+}
+
+func (m *AuthRoleDeleteRequest) Reset() { *m = AuthRoleDeleteRequest{} }
+func (m *AuthRoleDeleteRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleDeleteRequest) ProtoMessage() {}
+func (*AuthRoleDeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{66} }
+
+func (m *AuthRoleDeleteRequest) GetRole() string {
+ if m != nil {
+ return m.Role
+ }
+ return ""
+}
+
+type AuthRoleGrantPermissionRequest struct {
+ // name is the name of the role which will be granted the permission.
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ // perm is the permission to grant to the role.
+ Perm *authpb.Permission `protobuf:"bytes,2,opt,name=perm" json:"perm,omitempty"`
+}
+
+func (m *AuthRoleGrantPermissionRequest) Reset() { *m = AuthRoleGrantPermissionRequest{} }
+func (m *AuthRoleGrantPermissionRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleGrantPermissionRequest) ProtoMessage() {}
+func (*AuthRoleGrantPermissionRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{67}
+}
+
+func (m *AuthRoleGrantPermissionRequest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *AuthRoleGrantPermissionRequest) GetPerm() *authpb.Permission {
+ if m != nil {
+ return m.Perm
+ }
+ return nil
+}
+
+type AuthRoleRevokePermissionRequest struct {
+ Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"`
+ Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
+ RangeEnd string `protobuf:"bytes,3,opt,name=range_end,json=rangeEnd,proto3" json:"range_end,omitempty"`
+}
+
+func (m *AuthRoleRevokePermissionRequest) Reset() { *m = AuthRoleRevokePermissionRequest{} }
+func (m *AuthRoleRevokePermissionRequest) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleRevokePermissionRequest) ProtoMessage() {}
+func (*AuthRoleRevokePermissionRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{68}
+}
+
+func (m *AuthRoleRevokePermissionRequest) GetRole() string {
+ if m != nil {
+ return m.Role
+ }
+ return ""
+}
+
+func (m *AuthRoleRevokePermissionRequest) GetKey() string {
+ if m != nil {
+ return m.Key
+ }
+ return ""
+}
+
+func (m *AuthRoleRevokePermissionRequest) GetRangeEnd() string {
+ if m != nil {
+ return m.RangeEnd
+ }
+ return ""
+}
+
+type AuthEnableResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthEnableResponse) Reset() { *m = AuthEnableResponse{} }
+func (m *AuthEnableResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthEnableResponse) ProtoMessage() {}
+func (*AuthEnableResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{69} }
+
+func (m *AuthEnableResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthDisableResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthDisableResponse) Reset() { *m = AuthDisableResponse{} }
+func (m *AuthDisableResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthDisableResponse) ProtoMessage() {}
+func (*AuthDisableResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{70} }
+
+func (m *AuthDisableResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthenticateResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ // token is an authorized token that can be used in succeeding RPCs
+ Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
+}
+
+func (m *AuthenticateResponse) Reset() { *m = AuthenticateResponse{} }
+func (m *AuthenticateResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthenticateResponse) ProtoMessage() {}
+func (*AuthenticateResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{71} }
+
+func (m *AuthenticateResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *AuthenticateResponse) GetToken() string {
+ if m != nil {
+ return m.Token
+ }
+ return ""
+}
+
+type AuthUserAddResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthUserAddResponse) Reset() { *m = AuthUserAddResponse{} }
+func (m *AuthUserAddResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthUserAddResponse) ProtoMessage() {}
+func (*AuthUserAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{72} }
+
+func (m *AuthUserAddResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthUserGetResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ Roles []string `protobuf:"bytes,2,rep,name=roles" json:"roles,omitempty"`
+}
+
+func (m *AuthUserGetResponse) Reset() { *m = AuthUserGetResponse{} }
+func (m *AuthUserGetResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthUserGetResponse) ProtoMessage() {}
+func (*AuthUserGetResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{73} }
+
+func (m *AuthUserGetResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *AuthUserGetResponse) GetRoles() []string {
+ if m != nil {
+ return m.Roles
+ }
+ return nil
+}
+
+type AuthUserDeleteResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthUserDeleteResponse) Reset() { *m = AuthUserDeleteResponse{} }
+func (m *AuthUserDeleteResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthUserDeleteResponse) ProtoMessage() {}
+func (*AuthUserDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{74} }
+
+func (m *AuthUserDeleteResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthUserChangePasswordResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthUserChangePasswordResponse) Reset() { *m = AuthUserChangePasswordResponse{} }
+func (m *AuthUserChangePasswordResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthUserChangePasswordResponse) ProtoMessage() {}
+func (*AuthUserChangePasswordResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{75}
+}
+
+func (m *AuthUserChangePasswordResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthUserGrantRoleResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthUserGrantRoleResponse) Reset() { *m = AuthUserGrantRoleResponse{} }
+func (m *AuthUserGrantRoleResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthUserGrantRoleResponse) ProtoMessage() {}
+func (*AuthUserGrantRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{76} }
+
+func (m *AuthUserGrantRoleResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthUserRevokeRoleResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthUserRevokeRoleResponse) Reset() { *m = AuthUserRevokeRoleResponse{} }
+func (m *AuthUserRevokeRoleResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthUserRevokeRoleResponse) ProtoMessage() {}
+func (*AuthUserRevokeRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{77} }
+
+func (m *AuthUserRevokeRoleResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthRoleAddResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthRoleAddResponse) Reset() { *m = AuthRoleAddResponse{} }
+func (m *AuthRoleAddResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleAddResponse) ProtoMessage() {}
+func (*AuthRoleAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{78} }
+
+func (m *AuthRoleAddResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthRoleGetResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ Perm []*authpb.Permission `protobuf:"bytes,2,rep,name=perm" json:"perm,omitempty"`
+}
+
+func (m *AuthRoleGetResponse) Reset() { *m = AuthRoleGetResponse{} }
+func (m *AuthRoleGetResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleGetResponse) ProtoMessage() {}
+func (*AuthRoleGetResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{79} }
+
+func (m *AuthRoleGetResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *AuthRoleGetResponse) GetPerm() []*authpb.Permission {
+ if m != nil {
+ return m.Perm
+ }
+ return nil
+}
+
+type AuthRoleListResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ Roles []string `protobuf:"bytes,2,rep,name=roles" json:"roles,omitempty"`
+}
+
+func (m *AuthRoleListResponse) Reset() { *m = AuthRoleListResponse{} }
+func (m *AuthRoleListResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleListResponse) ProtoMessage() {}
+func (*AuthRoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{80} }
+
+func (m *AuthRoleListResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *AuthRoleListResponse) GetRoles() []string {
+ if m != nil {
+ return m.Roles
+ }
+ return nil
+}
+
+type AuthUserListResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+ Users []string `protobuf:"bytes,2,rep,name=users" json:"users,omitempty"`
+}
+
+func (m *AuthUserListResponse) Reset() { *m = AuthUserListResponse{} }
+func (m *AuthUserListResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthUserListResponse) ProtoMessage() {}
+func (*AuthUserListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{81} }
+
+func (m *AuthUserListResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func (m *AuthUserListResponse) GetUsers() []string {
+ if m != nil {
+ return m.Users
+ }
+ return nil
+}
+
+type AuthRoleDeleteResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthRoleDeleteResponse) Reset() { *m = AuthRoleDeleteResponse{} }
+func (m *AuthRoleDeleteResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleDeleteResponse) ProtoMessage() {}
+func (*AuthRoleDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{82} }
+
+func (m *AuthRoleDeleteResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthRoleGrantPermissionResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthRoleGrantPermissionResponse) Reset() { *m = AuthRoleGrantPermissionResponse{} }
+func (m *AuthRoleGrantPermissionResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleGrantPermissionResponse) ProtoMessage() {}
+func (*AuthRoleGrantPermissionResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{83}
+}
+
+func (m *AuthRoleGrantPermissionResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+type AuthRoleRevokePermissionResponse struct {
+ Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
+}
+
+func (m *AuthRoleRevokePermissionResponse) Reset() { *m = AuthRoleRevokePermissionResponse{} }
+func (m *AuthRoleRevokePermissionResponse) String() string { return proto.CompactTextString(m) }
+func (*AuthRoleRevokePermissionResponse) ProtoMessage() {}
+func (*AuthRoleRevokePermissionResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptorRpc, []int{84}
+}
+
+func (m *AuthRoleRevokePermissionResponse) GetHeader() *ResponseHeader {
+ if m != nil {
+ return m.Header
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*ResponseHeader)(nil), "etcdserverpb.ResponseHeader")
+ proto.RegisterType((*RangeRequest)(nil), "etcdserverpb.RangeRequest")
+ proto.RegisterType((*RangeResponse)(nil), "etcdserverpb.RangeResponse")
+ proto.RegisterType((*PutRequest)(nil), "etcdserverpb.PutRequest")
+ proto.RegisterType((*PutResponse)(nil), "etcdserverpb.PutResponse")
+ proto.RegisterType((*DeleteRangeRequest)(nil), "etcdserverpb.DeleteRangeRequest")
+ proto.RegisterType((*DeleteRangeResponse)(nil), "etcdserverpb.DeleteRangeResponse")
+ proto.RegisterType((*RequestOp)(nil), "etcdserverpb.RequestOp")
+ proto.RegisterType((*ResponseOp)(nil), "etcdserverpb.ResponseOp")
+ proto.RegisterType((*Compare)(nil), "etcdserverpb.Compare")
+ proto.RegisterType((*TxnRequest)(nil), "etcdserverpb.TxnRequest")
+ proto.RegisterType((*TxnResponse)(nil), "etcdserverpb.TxnResponse")
+ proto.RegisterType((*CompactionRequest)(nil), "etcdserverpb.CompactionRequest")
+ proto.RegisterType((*CompactionResponse)(nil), "etcdserverpb.CompactionResponse")
+ proto.RegisterType((*HashRequest)(nil), "etcdserverpb.HashRequest")
+ proto.RegisterType((*HashKVRequest)(nil), "etcdserverpb.HashKVRequest")
+ proto.RegisterType((*HashKVResponse)(nil), "etcdserverpb.HashKVResponse")
+ proto.RegisterType((*HashResponse)(nil), "etcdserverpb.HashResponse")
+ proto.RegisterType((*SnapshotRequest)(nil), "etcdserverpb.SnapshotRequest")
+ proto.RegisterType((*SnapshotResponse)(nil), "etcdserverpb.SnapshotResponse")
+ proto.RegisterType((*WatchRequest)(nil), "etcdserverpb.WatchRequest")
+ proto.RegisterType((*WatchCreateRequest)(nil), "etcdserverpb.WatchCreateRequest")
+ proto.RegisterType((*WatchCancelRequest)(nil), "etcdserverpb.WatchCancelRequest")
+ proto.RegisterType((*WatchResponse)(nil), "etcdserverpb.WatchResponse")
+ proto.RegisterType((*LeaseGrantRequest)(nil), "etcdserverpb.LeaseGrantRequest")
+ proto.RegisterType((*LeaseGrantResponse)(nil), "etcdserverpb.LeaseGrantResponse")
+ proto.RegisterType((*LeaseRevokeRequest)(nil), "etcdserverpb.LeaseRevokeRequest")
+ proto.RegisterType((*LeaseRevokeResponse)(nil), "etcdserverpb.LeaseRevokeResponse")
+ proto.RegisterType((*LeaseKeepAliveRequest)(nil), "etcdserverpb.LeaseKeepAliveRequest")
+ proto.RegisterType((*LeaseKeepAliveResponse)(nil), "etcdserverpb.LeaseKeepAliveResponse")
+ proto.RegisterType((*LeaseTimeToLiveRequest)(nil), "etcdserverpb.LeaseTimeToLiveRequest")
+ proto.RegisterType((*LeaseTimeToLiveResponse)(nil), "etcdserverpb.LeaseTimeToLiveResponse")
+ proto.RegisterType((*LeaseLeasesRequest)(nil), "etcdserverpb.LeaseLeasesRequest")
+ proto.RegisterType((*LeaseStatus)(nil), "etcdserverpb.LeaseStatus")
+ proto.RegisterType((*LeaseLeasesResponse)(nil), "etcdserverpb.LeaseLeasesResponse")
+ proto.RegisterType((*Member)(nil), "etcdserverpb.Member")
+ proto.RegisterType((*MemberAddRequest)(nil), "etcdserverpb.MemberAddRequest")
+ proto.RegisterType((*MemberAddResponse)(nil), "etcdserverpb.MemberAddResponse")
+ proto.RegisterType((*MemberRemoveRequest)(nil), "etcdserverpb.MemberRemoveRequest")
+ proto.RegisterType((*MemberRemoveResponse)(nil), "etcdserverpb.MemberRemoveResponse")
+ proto.RegisterType((*MemberUpdateRequest)(nil), "etcdserverpb.MemberUpdateRequest")
+ proto.RegisterType((*MemberUpdateResponse)(nil), "etcdserverpb.MemberUpdateResponse")
+ proto.RegisterType((*MemberListRequest)(nil), "etcdserverpb.MemberListRequest")
+ proto.RegisterType((*MemberListResponse)(nil), "etcdserverpb.MemberListResponse")
+ proto.RegisterType((*DefragmentRequest)(nil), "etcdserverpb.DefragmentRequest")
+ proto.RegisterType((*DefragmentResponse)(nil), "etcdserverpb.DefragmentResponse")
+ proto.RegisterType((*MoveLeaderRequest)(nil), "etcdserverpb.MoveLeaderRequest")
+ proto.RegisterType((*MoveLeaderResponse)(nil), "etcdserverpb.MoveLeaderResponse")
+ proto.RegisterType((*AlarmRequest)(nil), "etcdserverpb.AlarmRequest")
+ proto.RegisterType((*AlarmMember)(nil), "etcdserverpb.AlarmMember")
+ proto.RegisterType((*AlarmResponse)(nil), "etcdserverpb.AlarmResponse")
+ proto.RegisterType((*StatusRequest)(nil), "etcdserverpb.StatusRequest")
+ proto.RegisterType((*StatusResponse)(nil), "etcdserverpb.StatusResponse")
+ proto.RegisterType((*AuthEnableRequest)(nil), "etcdserverpb.AuthEnableRequest")
+ proto.RegisterType((*AuthDisableRequest)(nil), "etcdserverpb.AuthDisableRequest")
+ proto.RegisterType((*AuthenticateRequest)(nil), "etcdserverpb.AuthenticateRequest")
+ proto.RegisterType((*AuthUserAddRequest)(nil), "etcdserverpb.AuthUserAddRequest")
+ proto.RegisterType((*AuthUserGetRequest)(nil), "etcdserverpb.AuthUserGetRequest")
+ proto.RegisterType((*AuthUserDeleteRequest)(nil), "etcdserverpb.AuthUserDeleteRequest")
+ proto.RegisterType((*AuthUserChangePasswordRequest)(nil), "etcdserverpb.AuthUserChangePasswordRequest")
+ proto.RegisterType((*AuthUserGrantRoleRequest)(nil), "etcdserverpb.AuthUserGrantRoleRequest")
+ proto.RegisterType((*AuthUserRevokeRoleRequest)(nil), "etcdserverpb.AuthUserRevokeRoleRequest")
+ proto.RegisterType((*AuthRoleAddRequest)(nil), "etcdserverpb.AuthRoleAddRequest")
+ proto.RegisterType((*AuthRoleGetRequest)(nil), "etcdserverpb.AuthRoleGetRequest")
+ proto.RegisterType((*AuthUserListRequest)(nil), "etcdserverpb.AuthUserListRequest")
+ proto.RegisterType((*AuthRoleListRequest)(nil), "etcdserverpb.AuthRoleListRequest")
+ proto.RegisterType((*AuthRoleDeleteRequest)(nil), "etcdserverpb.AuthRoleDeleteRequest")
+ proto.RegisterType((*AuthRoleGrantPermissionRequest)(nil), "etcdserverpb.AuthRoleGrantPermissionRequest")
+ proto.RegisterType((*AuthRoleRevokePermissionRequest)(nil), "etcdserverpb.AuthRoleRevokePermissionRequest")
+ proto.RegisterType((*AuthEnableResponse)(nil), "etcdserverpb.AuthEnableResponse")
+ proto.RegisterType((*AuthDisableResponse)(nil), "etcdserverpb.AuthDisableResponse")
+ proto.RegisterType((*AuthenticateResponse)(nil), "etcdserverpb.AuthenticateResponse")
+ proto.RegisterType((*AuthUserAddResponse)(nil), "etcdserverpb.AuthUserAddResponse")
+ proto.RegisterType((*AuthUserGetResponse)(nil), "etcdserverpb.AuthUserGetResponse")
+ proto.RegisterType((*AuthUserDeleteResponse)(nil), "etcdserverpb.AuthUserDeleteResponse")
+ proto.RegisterType((*AuthUserChangePasswordResponse)(nil), "etcdserverpb.AuthUserChangePasswordResponse")
+ proto.RegisterType((*AuthUserGrantRoleResponse)(nil), "etcdserverpb.AuthUserGrantRoleResponse")
+ proto.RegisterType((*AuthUserRevokeRoleResponse)(nil), "etcdserverpb.AuthUserRevokeRoleResponse")
+ proto.RegisterType((*AuthRoleAddResponse)(nil), "etcdserverpb.AuthRoleAddResponse")
+ proto.RegisterType((*AuthRoleGetResponse)(nil), "etcdserverpb.AuthRoleGetResponse")
+ proto.RegisterType((*AuthRoleListResponse)(nil), "etcdserverpb.AuthRoleListResponse")
+ proto.RegisterType((*AuthUserListResponse)(nil), "etcdserverpb.AuthUserListResponse")
+ proto.RegisterType((*AuthRoleDeleteResponse)(nil), "etcdserverpb.AuthRoleDeleteResponse")
+ proto.RegisterType((*AuthRoleGrantPermissionResponse)(nil), "etcdserverpb.AuthRoleGrantPermissionResponse")
+ proto.RegisterType((*AuthRoleRevokePermissionResponse)(nil), "etcdserverpb.AuthRoleRevokePermissionResponse")
+ proto.RegisterEnum("etcdserverpb.AlarmType", AlarmType_name, AlarmType_value)
+ proto.RegisterEnum("etcdserverpb.RangeRequest_SortOrder", RangeRequest_SortOrder_name, RangeRequest_SortOrder_value)
+ proto.RegisterEnum("etcdserverpb.RangeRequest_SortTarget", RangeRequest_SortTarget_name, RangeRequest_SortTarget_value)
+ proto.RegisterEnum("etcdserverpb.Compare_CompareResult", Compare_CompareResult_name, Compare_CompareResult_value)
+ proto.RegisterEnum("etcdserverpb.Compare_CompareTarget", Compare_CompareTarget_name, Compare_CompareTarget_value)
+ proto.RegisterEnum("etcdserverpb.WatchCreateRequest_FilterType", WatchCreateRequest_FilterType_name, WatchCreateRequest_FilterType_value)
+ proto.RegisterEnum("etcdserverpb.AlarmRequest_AlarmAction", AlarmRequest_AlarmAction_name, AlarmRequest_AlarmAction_value)
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// Client API for KV service
+
+type KVClient interface {
+ // Range gets the keys in the range from the key-value store.
+ Range(ctx context.Context, in *RangeRequest, opts ...grpc.CallOption) (*RangeResponse, error)
+ // Put puts the given key into the key-value store.
+ // A put request increments the revision of the key-value store
+ // and generates one event in the event history.
+ Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error)
+ // DeleteRange deletes the given range from the key-value store.
+ // A delete request increments the revision of the key-value store
+ // and generates a delete event in the event history for every deleted key.
+ DeleteRange(ctx context.Context, in *DeleteRangeRequest, opts ...grpc.CallOption) (*DeleteRangeResponse, error)
+ // Txn processes multiple requests in a single transaction.
+ // A txn request increments the revision of the key-value store
+ // and generates events with the same revision for every completed request.
+ // It is not allowed to modify the same key several times within one txn.
+ Txn(ctx context.Context, in *TxnRequest, opts ...grpc.CallOption) (*TxnResponse, error)
+ // Compact compacts the event history in the etcd key-value store. The key-value
+ // store should be periodically compacted or the event history will continue to grow
+ // indefinitely.
+ Compact(ctx context.Context, in *CompactionRequest, opts ...grpc.CallOption) (*CompactionResponse, error)
+}
+
+type kVClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewKVClient(cc *grpc.ClientConn) KVClient {
+ return &kVClient{cc}
+}
+
+func (c *kVClient) Range(ctx context.Context, in *RangeRequest, opts ...grpc.CallOption) (*RangeResponse, error) {
+ out := new(RangeResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.KV/Range", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *kVClient) Put(ctx context.Context, in *PutRequest, opts ...grpc.CallOption) (*PutResponse, error) {
+ out := new(PutResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.KV/Put", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *kVClient) DeleteRange(ctx context.Context, in *DeleteRangeRequest, opts ...grpc.CallOption) (*DeleteRangeResponse, error) {
+ out := new(DeleteRangeResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.KV/DeleteRange", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *kVClient) Txn(ctx context.Context, in *TxnRequest, opts ...grpc.CallOption) (*TxnResponse, error) {
+ out := new(TxnResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.KV/Txn", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *kVClient) Compact(ctx context.Context, in *CompactionRequest, opts ...grpc.CallOption) (*CompactionResponse, error) {
+ out := new(CompactionResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.KV/Compact", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// Server API for KV service
+
+type KVServer interface {
+ // Range gets the keys in the range from the key-value store.
+ Range(context.Context, *RangeRequest) (*RangeResponse, error)
+ // Put puts the given key into the key-value store.
+ // A put request increments the revision of the key-value store
+ // and generates one event in the event history.
+ Put(context.Context, *PutRequest) (*PutResponse, error)
+ // DeleteRange deletes the given range from the key-value store.
+ // A delete request increments the revision of the key-value store
+ // and generates a delete event in the event history for every deleted key.
+ DeleteRange(context.Context, *DeleteRangeRequest) (*DeleteRangeResponse, error)
+ // Txn processes multiple requests in a single transaction.
+ // A txn request increments the revision of the key-value store
+ // and generates events with the same revision for every completed request.
+ // It is not allowed to modify the same key several times within one txn.
+ Txn(context.Context, *TxnRequest) (*TxnResponse, error)
+ // Compact compacts the event history in the etcd key-value store. The key-value
+ // store should be periodically compacted or the event history will continue to grow
+ // indefinitely.
+ Compact(context.Context, *CompactionRequest) (*CompactionResponse, error)
+}
+
+func RegisterKVServer(s *grpc.Server, srv KVServer) {
+ s.RegisterService(&_KV_serviceDesc, srv)
+}
+
+func _KV_Range_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(RangeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(KVServer).Range(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.KV/Range",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(KVServer).Range(ctx, req.(*RangeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _KV_Put_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(PutRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(KVServer).Put(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.KV/Put",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(KVServer).Put(ctx, req.(*PutRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _KV_DeleteRange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DeleteRangeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(KVServer).DeleteRange(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.KV/DeleteRange",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(KVServer).DeleteRange(ctx, req.(*DeleteRangeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _KV_Txn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(TxnRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(KVServer).Txn(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.KV/Txn",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(KVServer).Txn(ctx, req.(*TxnRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _KV_Compact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(CompactionRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(KVServer).Compact(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.KV/Compact",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(KVServer).Compact(ctx, req.(*CompactionRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _KV_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "etcdserverpb.KV",
+ HandlerType: (*KVServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Range",
+ Handler: _KV_Range_Handler,
+ },
+ {
+ MethodName: "Put",
+ Handler: _KV_Put_Handler,
+ },
+ {
+ MethodName: "DeleteRange",
+ Handler: _KV_DeleteRange_Handler,
+ },
+ {
+ MethodName: "Txn",
+ Handler: _KV_Txn_Handler,
+ },
+ {
+ MethodName: "Compact",
+ Handler: _KV_Compact_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "rpc.proto",
+}
+
+// Client API for Watch service
+
+type WatchClient interface {
+ // Watch watches for events happening or that have happened. Both input and output
+ // are streams; the input stream is for creating and canceling watchers and the output
+ // stream sends events. One watch RPC can watch on multiple key ranges, streaming events
+ // for several watches at once. The entire event history can be watched starting from the
+ // last compaction revision.
+ Watch(ctx context.Context, opts ...grpc.CallOption) (Watch_WatchClient, error)
+}
+
+type watchClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewWatchClient(cc *grpc.ClientConn) WatchClient {
+ return &watchClient{cc}
+}
+
+func (c *watchClient) Watch(ctx context.Context, opts ...grpc.CallOption) (Watch_WatchClient, error) {
+ stream, err := grpc.NewClientStream(ctx, &_Watch_serviceDesc.Streams[0], c.cc, "/etcdserverpb.Watch/Watch", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &watchWatchClient{stream}
+ return x, nil
+}
+
+type Watch_WatchClient interface {
+ Send(*WatchRequest) error
+ Recv() (*WatchResponse, error)
+ grpc.ClientStream
+}
+
+type watchWatchClient struct {
+ grpc.ClientStream
+}
+
+func (x *watchWatchClient) Send(m *WatchRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *watchWatchClient) Recv() (*WatchResponse, error) {
+ m := new(WatchResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+// Server API for Watch service
+
+type WatchServer interface {
+ // Watch watches for events happening or that have happened. Both input and output
+ // are streams; the input stream is for creating and canceling watchers and the output
+ // stream sends events. One watch RPC can watch on multiple key ranges, streaming events
+ // for several watches at once. The entire event history can be watched starting from the
+ // last compaction revision.
+ Watch(Watch_WatchServer) error
+}
+
+func RegisterWatchServer(s *grpc.Server, srv WatchServer) {
+ s.RegisterService(&_Watch_serviceDesc, srv)
+}
+
+func _Watch_Watch_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(WatchServer).Watch(&watchWatchServer{stream})
+}
+
+type Watch_WatchServer interface {
+ Send(*WatchResponse) error
+ Recv() (*WatchRequest, error)
+ grpc.ServerStream
+}
+
+type watchWatchServer struct {
+ grpc.ServerStream
+}
+
+func (x *watchWatchServer) Send(m *WatchResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *watchWatchServer) Recv() (*WatchRequest, error) {
+ m := new(WatchRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+var _Watch_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "etcdserverpb.Watch",
+ HandlerType: (*WatchServer)(nil),
+ Methods: []grpc.MethodDesc{},
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "Watch",
+ Handler: _Watch_Watch_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ },
+ Metadata: "rpc.proto",
+}
+
+// Client API for Lease service
+
+type LeaseClient interface {
+ // LeaseGrant creates a lease which expires if the server does not receive a keepAlive
+ // within a given time to live period. All keys attached to the lease will be expired and
+ // deleted if the lease expires. Each expired key generates a delete event in the event history.
+ LeaseGrant(ctx context.Context, in *LeaseGrantRequest, opts ...grpc.CallOption) (*LeaseGrantResponse, error)
+ // LeaseRevoke revokes a lease. All keys attached to the lease will expire and be deleted.
+ LeaseRevoke(ctx context.Context, in *LeaseRevokeRequest, opts ...grpc.CallOption) (*LeaseRevokeResponse, error)
+ // LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
+ // to the server and streaming keep alive responses from the server to the client.
+ LeaseKeepAlive(ctx context.Context, opts ...grpc.CallOption) (Lease_LeaseKeepAliveClient, error)
+ // LeaseTimeToLive retrieves lease information.
+ LeaseTimeToLive(ctx context.Context, in *LeaseTimeToLiveRequest, opts ...grpc.CallOption) (*LeaseTimeToLiveResponse, error)
+ // LeaseLeases lists all existing leases.
+ LeaseLeases(ctx context.Context, in *LeaseLeasesRequest, opts ...grpc.CallOption) (*LeaseLeasesResponse, error)
+}
+
+type leaseClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewLeaseClient(cc *grpc.ClientConn) LeaseClient {
+ return &leaseClient{cc}
+}
+
+func (c *leaseClient) LeaseGrant(ctx context.Context, in *LeaseGrantRequest, opts ...grpc.CallOption) (*LeaseGrantResponse, error) {
+ out := new(LeaseGrantResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Lease/LeaseGrant", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *leaseClient) LeaseRevoke(ctx context.Context, in *LeaseRevokeRequest, opts ...grpc.CallOption) (*LeaseRevokeResponse, error) {
+ out := new(LeaseRevokeResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Lease/LeaseRevoke", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *leaseClient) LeaseKeepAlive(ctx context.Context, opts ...grpc.CallOption) (Lease_LeaseKeepAliveClient, error) {
+ stream, err := grpc.NewClientStream(ctx, &_Lease_serviceDesc.Streams[0], c.cc, "/etcdserverpb.Lease/LeaseKeepAlive", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &leaseLeaseKeepAliveClient{stream}
+ return x, nil
+}
+
+type Lease_LeaseKeepAliveClient interface {
+ Send(*LeaseKeepAliveRequest) error
+ Recv() (*LeaseKeepAliveResponse, error)
+ grpc.ClientStream
+}
+
+type leaseLeaseKeepAliveClient struct {
+ grpc.ClientStream
+}
+
+func (x *leaseLeaseKeepAliveClient) Send(m *LeaseKeepAliveRequest) error {
+ return x.ClientStream.SendMsg(m)
+}
+
+func (x *leaseLeaseKeepAliveClient) Recv() (*LeaseKeepAliveResponse, error) {
+ m := new(LeaseKeepAliveResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *leaseClient) LeaseTimeToLive(ctx context.Context, in *LeaseTimeToLiveRequest, opts ...grpc.CallOption) (*LeaseTimeToLiveResponse, error) {
+ out := new(LeaseTimeToLiveResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Lease/LeaseTimeToLive", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *leaseClient) LeaseLeases(ctx context.Context, in *LeaseLeasesRequest, opts ...grpc.CallOption) (*LeaseLeasesResponse, error) {
+ out := new(LeaseLeasesResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Lease/LeaseLeases", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// Server API for Lease service
+
+type LeaseServer interface {
+ // LeaseGrant creates a lease which expires if the server does not receive a keepAlive
+ // within a given time to live period. All keys attached to the lease will be expired and
+ // deleted if the lease expires. Each expired key generates a delete event in the event history.
+ LeaseGrant(context.Context, *LeaseGrantRequest) (*LeaseGrantResponse, error)
+ // LeaseRevoke revokes a lease. All keys attached to the lease will expire and be deleted.
+ LeaseRevoke(context.Context, *LeaseRevokeRequest) (*LeaseRevokeResponse, error)
+ // LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client
+ // to the server and streaming keep alive responses from the server to the client.
+ LeaseKeepAlive(Lease_LeaseKeepAliveServer) error
+ // LeaseTimeToLive retrieves lease information.
+ LeaseTimeToLive(context.Context, *LeaseTimeToLiveRequest) (*LeaseTimeToLiveResponse, error)
+ // LeaseLeases lists all existing leases.
+ LeaseLeases(context.Context, *LeaseLeasesRequest) (*LeaseLeasesResponse, error)
+}
+
+func RegisterLeaseServer(s *grpc.Server, srv LeaseServer) {
+ s.RegisterService(&_Lease_serviceDesc, srv)
+}
+
+func _Lease_LeaseGrant_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LeaseGrantRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LeaseServer).LeaseGrant(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Lease/LeaseGrant",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LeaseServer).LeaseGrant(ctx, req.(*LeaseGrantRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Lease_LeaseRevoke_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LeaseRevokeRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LeaseServer).LeaseRevoke(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Lease/LeaseRevoke",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LeaseServer).LeaseRevoke(ctx, req.(*LeaseRevokeRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Lease_LeaseKeepAlive_Handler(srv interface{}, stream grpc.ServerStream) error {
+ return srv.(LeaseServer).LeaseKeepAlive(&leaseLeaseKeepAliveServer{stream})
+}
+
+type Lease_LeaseKeepAliveServer interface {
+ Send(*LeaseKeepAliveResponse) error
+ Recv() (*LeaseKeepAliveRequest, error)
+ grpc.ServerStream
+}
+
+type leaseLeaseKeepAliveServer struct {
+ grpc.ServerStream
+}
+
+func (x *leaseLeaseKeepAliveServer) Send(m *LeaseKeepAliveResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func (x *leaseLeaseKeepAliveServer) Recv() (*LeaseKeepAliveRequest, error) {
+ m := new(LeaseKeepAliveRequest)
+ if err := x.ServerStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func _Lease_LeaseTimeToLive_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LeaseTimeToLiveRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LeaseServer).LeaseTimeToLive(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Lease/LeaseTimeToLive",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LeaseServer).LeaseTimeToLive(ctx, req.(*LeaseTimeToLiveRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Lease_LeaseLeases_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(LeaseLeasesRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(LeaseServer).LeaseLeases(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Lease/LeaseLeases",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(LeaseServer).LeaseLeases(ctx, req.(*LeaseLeasesRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Lease_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "etcdserverpb.Lease",
+ HandlerType: (*LeaseServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "LeaseGrant",
+ Handler: _Lease_LeaseGrant_Handler,
+ },
+ {
+ MethodName: "LeaseRevoke",
+ Handler: _Lease_LeaseRevoke_Handler,
+ },
+ {
+ MethodName: "LeaseTimeToLive",
+ Handler: _Lease_LeaseTimeToLive_Handler,
+ },
+ {
+ MethodName: "LeaseLeases",
+ Handler: _Lease_LeaseLeases_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "LeaseKeepAlive",
+ Handler: _Lease_LeaseKeepAlive_Handler,
+ ServerStreams: true,
+ ClientStreams: true,
+ },
+ },
+ Metadata: "rpc.proto",
+}
+
+// Client API for Cluster service
+
+type ClusterClient interface {
+ // MemberAdd adds a member into the cluster.
+ MemberAdd(ctx context.Context, in *MemberAddRequest, opts ...grpc.CallOption) (*MemberAddResponse, error)
+ // MemberRemove removes an existing member from the cluster.
+ MemberRemove(ctx context.Context, in *MemberRemoveRequest, opts ...grpc.CallOption) (*MemberRemoveResponse, error)
+ // MemberUpdate updates the member configuration.
+ MemberUpdate(ctx context.Context, in *MemberUpdateRequest, opts ...grpc.CallOption) (*MemberUpdateResponse, error)
+ // MemberList lists all the members in the cluster.
+ MemberList(ctx context.Context, in *MemberListRequest, opts ...grpc.CallOption) (*MemberListResponse, error)
+}
+
+type clusterClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewClusterClient(cc *grpc.ClientConn) ClusterClient {
+ return &clusterClient{cc}
+}
+
+func (c *clusterClient) MemberAdd(ctx context.Context, in *MemberAddRequest, opts ...grpc.CallOption) (*MemberAddResponse, error) {
+ out := new(MemberAddResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Cluster/MemberAdd", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *clusterClient) MemberRemove(ctx context.Context, in *MemberRemoveRequest, opts ...grpc.CallOption) (*MemberRemoveResponse, error) {
+ out := new(MemberRemoveResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Cluster/MemberRemove", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *clusterClient) MemberUpdate(ctx context.Context, in *MemberUpdateRequest, opts ...grpc.CallOption) (*MemberUpdateResponse, error) {
+ out := new(MemberUpdateResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Cluster/MemberUpdate", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *clusterClient) MemberList(ctx context.Context, in *MemberListRequest, opts ...grpc.CallOption) (*MemberListResponse, error) {
+ out := new(MemberListResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Cluster/MemberList", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// Server API for Cluster service
+
+type ClusterServer interface {
+ // MemberAdd adds a member into the cluster.
+ MemberAdd(context.Context, *MemberAddRequest) (*MemberAddResponse, error)
+ // MemberRemove removes an existing member from the cluster.
+ MemberRemove(context.Context, *MemberRemoveRequest) (*MemberRemoveResponse, error)
+ // MemberUpdate updates the member configuration.
+ MemberUpdate(context.Context, *MemberUpdateRequest) (*MemberUpdateResponse, error)
+ // MemberList lists all the members in the cluster.
+ MemberList(context.Context, *MemberListRequest) (*MemberListResponse, error)
+}
+
+func RegisterClusterServer(s *grpc.Server, srv ClusterServer) {
+ s.RegisterService(&_Cluster_serviceDesc, srv)
+}
+
+func _Cluster_MemberAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MemberAddRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ClusterServer).MemberAdd(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Cluster/MemberAdd",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ClusterServer).MemberAdd(ctx, req.(*MemberAddRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Cluster_MemberRemove_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MemberRemoveRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ClusterServer).MemberRemove(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Cluster/MemberRemove",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ClusterServer).MemberRemove(ctx, req.(*MemberRemoveRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Cluster_MemberUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MemberUpdateRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ClusterServer).MemberUpdate(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Cluster/MemberUpdate",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ClusterServer).MemberUpdate(ctx, req.(*MemberUpdateRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Cluster_MemberList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MemberListRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ClusterServer).MemberList(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Cluster/MemberList",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ClusterServer).MemberList(ctx, req.(*MemberListRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Cluster_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "etcdserverpb.Cluster",
+ HandlerType: (*ClusterServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "MemberAdd",
+ Handler: _Cluster_MemberAdd_Handler,
+ },
+ {
+ MethodName: "MemberRemove",
+ Handler: _Cluster_MemberRemove_Handler,
+ },
+ {
+ MethodName: "MemberUpdate",
+ Handler: _Cluster_MemberUpdate_Handler,
+ },
+ {
+ MethodName: "MemberList",
+ Handler: _Cluster_MemberList_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "rpc.proto",
+}
+
+// Client API for Maintenance service
+
+type MaintenanceClient interface {
+ // Alarm activates, deactivates, and queries alarms regarding cluster health.
+ Alarm(ctx context.Context, in *AlarmRequest, opts ...grpc.CallOption) (*AlarmResponse, error)
+ // Status gets the status of the member.
+ Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
+ // Defragment defragments a member's backend database to recover storage space.
+ Defragment(ctx context.Context, in *DefragmentRequest, opts ...grpc.CallOption) (*DefragmentResponse, error)
+ // Hash computes the hash of the KV's backend.
+ // This is designed for testing; do not use this in production when there
+ // are ongoing transactions.
+ Hash(ctx context.Context, in *HashRequest, opts ...grpc.CallOption) (*HashResponse, error)
+ // HashKV computes the hash of all MVCC keys up to a given revision.
+ HashKV(ctx context.Context, in *HashKVRequest, opts ...grpc.CallOption) (*HashKVResponse, error)
+ // Snapshot sends a snapshot of the entire backend from a member over a stream to a client.
+ Snapshot(ctx context.Context, in *SnapshotRequest, opts ...grpc.CallOption) (Maintenance_SnapshotClient, error)
+ // MoveLeader requests current leader node to transfer its leadership to transferee.
+ MoveLeader(ctx context.Context, in *MoveLeaderRequest, opts ...grpc.CallOption) (*MoveLeaderResponse, error)
+}
+
+type maintenanceClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewMaintenanceClient(cc *grpc.ClientConn) MaintenanceClient {
+ return &maintenanceClient{cc}
+}
+
+func (c *maintenanceClient) Alarm(ctx context.Context, in *AlarmRequest, opts ...grpc.CallOption) (*AlarmResponse, error) {
+ out := new(AlarmResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Maintenance/Alarm", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *maintenanceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
+ out := new(StatusResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Maintenance/Status", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *maintenanceClient) Defragment(ctx context.Context, in *DefragmentRequest, opts ...grpc.CallOption) (*DefragmentResponse, error) {
+ out := new(DefragmentResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Maintenance/Defragment", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *maintenanceClient) Hash(ctx context.Context, in *HashRequest, opts ...grpc.CallOption) (*HashResponse, error) {
+ out := new(HashResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Maintenance/Hash", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *maintenanceClient) HashKV(ctx context.Context, in *HashKVRequest, opts ...grpc.CallOption) (*HashKVResponse, error) {
+ out := new(HashKVResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Maintenance/HashKV", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *maintenanceClient) Snapshot(ctx context.Context, in *SnapshotRequest, opts ...grpc.CallOption) (Maintenance_SnapshotClient, error) {
+ stream, err := grpc.NewClientStream(ctx, &_Maintenance_serviceDesc.Streams[0], c.cc, "/etcdserverpb.Maintenance/Snapshot", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &maintenanceSnapshotClient{stream}
+ if err := x.ClientStream.SendMsg(in); err != nil {
+ return nil, err
+ }
+ if err := x.ClientStream.CloseSend(); err != nil {
+ return nil, err
+ }
+ return x, nil
+}
+
+type Maintenance_SnapshotClient interface {
+ Recv() (*SnapshotResponse, error)
+ grpc.ClientStream
+}
+
+type maintenanceSnapshotClient struct {
+ grpc.ClientStream
+}
+
+func (x *maintenanceSnapshotClient) Recv() (*SnapshotResponse, error) {
+ m := new(SnapshotResponse)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (c *maintenanceClient) MoveLeader(ctx context.Context, in *MoveLeaderRequest, opts ...grpc.CallOption) (*MoveLeaderResponse, error) {
+ out := new(MoveLeaderResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Maintenance/MoveLeader", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// Server API for Maintenance service
+
+type MaintenanceServer interface {
+ // Alarm activates, deactivates, and queries alarms regarding cluster health.
+ Alarm(context.Context, *AlarmRequest) (*AlarmResponse, error)
+ // Status gets the status of the member.
+ Status(context.Context, *StatusRequest) (*StatusResponse, error)
+ // Defragment defragments a member's backend database to recover storage space.
+ Defragment(context.Context, *DefragmentRequest) (*DefragmentResponse, error)
+ // Hash computes the hash of the KV's backend.
+ // This is designed for testing; do not use this in production when there
+ // are ongoing transactions.
+ Hash(context.Context, *HashRequest) (*HashResponse, error)
+ // HashKV computes the hash of all MVCC keys up to a given revision.
+ HashKV(context.Context, *HashKVRequest) (*HashKVResponse, error)
+ // Snapshot sends a snapshot of the entire backend from a member over a stream to a client.
+ Snapshot(*SnapshotRequest, Maintenance_SnapshotServer) error
+ // MoveLeader requests current leader node to transfer its leadership to transferee.
+ MoveLeader(context.Context, *MoveLeaderRequest) (*MoveLeaderResponse, error)
+}
+
+func RegisterMaintenanceServer(s *grpc.Server, srv MaintenanceServer) {
+ s.RegisterService(&_Maintenance_serviceDesc, srv)
+}
+
+func _Maintenance_Alarm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AlarmRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MaintenanceServer).Alarm(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Maintenance/Alarm",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MaintenanceServer).Alarm(ctx, req.(*AlarmRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Maintenance_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(StatusRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MaintenanceServer).Status(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Maintenance/Status",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MaintenanceServer).Status(ctx, req.(*StatusRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Maintenance_Defragment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DefragmentRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MaintenanceServer).Defragment(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Maintenance/Defragment",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MaintenanceServer).Defragment(ctx, req.(*DefragmentRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Maintenance_Hash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HashRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MaintenanceServer).Hash(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Maintenance/Hash",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MaintenanceServer).Hash(ctx, req.(*HashRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Maintenance_HashKV_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HashKVRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MaintenanceServer).HashKV(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Maintenance/HashKV",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MaintenanceServer).HashKV(ctx, req.(*HashKVRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Maintenance_Snapshot_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(SnapshotRequest)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(MaintenanceServer).Snapshot(m, &maintenanceSnapshotServer{stream})
+}
+
+type Maintenance_SnapshotServer interface {
+ Send(*SnapshotResponse) error
+ grpc.ServerStream
+}
+
+type maintenanceSnapshotServer struct {
+ grpc.ServerStream
+}
+
+func (x *maintenanceSnapshotServer) Send(m *SnapshotResponse) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+func _Maintenance_MoveLeader_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(MoveLeaderRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(MaintenanceServer).MoveLeader(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Maintenance/MoveLeader",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(MaintenanceServer).MoveLeader(ctx, req.(*MoveLeaderRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Maintenance_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "etcdserverpb.Maintenance",
+ HandlerType: (*MaintenanceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "Alarm",
+ Handler: _Maintenance_Alarm_Handler,
+ },
+ {
+ MethodName: "Status",
+ Handler: _Maintenance_Status_Handler,
+ },
+ {
+ MethodName: "Defragment",
+ Handler: _Maintenance_Defragment_Handler,
+ },
+ {
+ MethodName: "Hash",
+ Handler: _Maintenance_Hash_Handler,
+ },
+ {
+ MethodName: "HashKV",
+ Handler: _Maintenance_HashKV_Handler,
+ },
+ {
+ MethodName: "MoveLeader",
+ Handler: _Maintenance_MoveLeader_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "Snapshot",
+ Handler: _Maintenance_Snapshot_Handler,
+ ServerStreams: true,
+ },
+ },
+ Metadata: "rpc.proto",
+}
+
+// Client API for Auth service
+
+type AuthClient interface {
+ // AuthEnable enables authentication.
+ AuthEnable(ctx context.Context, in *AuthEnableRequest, opts ...grpc.CallOption) (*AuthEnableResponse, error)
+ // AuthDisable disables authentication.
+ AuthDisable(ctx context.Context, in *AuthDisableRequest, opts ...grpc.CallOption) (*AuthDisableResponse, error)
+ // Authenticate processes an authenticate request.
+ Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error)
+ // UserAdd adds a new user.
+ UserAdd(ctx context.Context, in *AuthUserAddRequest, opts ...grpc.CallOption) (*AuthUserAddResponse, error)
+ // UserGet gets detailed user information.
+ UserGet(ctx context.Context, in *AuthUserGetRequest, opts ...grpc.CallOption) (*AuthUserGetResponse, error)
+ // UserList gets a list of all users.
+ UserList(ctx context.Context, in *AuthUserListRequest, opts ...grpc.CallOption) (*AuthUserListResponse, error)
+ // UserDelete deletes a specified user.
+ UserDelete(ctx context.Context, in *AuthUserDeleteRequest, opts ...grpc.CallOption) (*AuthUserDeleteResponse, error)
+ // UserChangePassword changes the password of a specified user.
+ UserChangePassword(ctx context.Context, in *AuthUserChangePasswordRequest, opts ...grpc.CallOption) (*AuthUserChangePasswordResponse, error)
+ // UserGrant grants a role to a specified user.
+ UserGrantRole(ctx context.Context, in *AuthUserGrantRoleRequest, opts ...grpc.CallOption) (*AuthUserGrantRoleResponse, error)
+ // UserRevokeRole revokes a role of specified user.
+ UserRevokeRole(ctx context.Context, in *AuthUserRevokeRoleRequest, opts ...grpc.CallOption) (*AuthUserRevokeRoleResponse, error)
+ // RoleAdd adds a new role.
+ RoleAdd(ctx context.Context, in *AuthRoleAddRequest, opts ...grpc.CallOption) (*AuthRoleAddResponse, error)
+ // RoleGet gets detailed role information.
+ RoleGet(ctx context.Context, in *AuthRoleGetRequest, opts ...grpc.CallOption) (*AuthRoleGetResponse, error)
+ // RoleList gets lists of all roles.
+ RoleList(ctx context.Context, in *AuthRoleListRequest, opts ...grpc.CallOption) (*AuthRoleListResponse, error)
+ // RoleDelete deletes a specified role.
+ RoleDelete(ctx context.Context, in *AuthRoleDeleteRequest, opts ...grpc.CallOption) (*AuthRoleDeleteResponse, error)
+ // RoleGrantPermission grants a permission of a specified key or range to a specified role.
+ RoleGrantPermission(ctx context.Context, in *AuthRoleGrantPermissionRequest, opts ...grpc.CallOption) (*AuthRoleGrantPermissionResponse, error)
+ // RoleRevokePermission revokes a key or range permission of a specified role.
+ RoleRevokePermission(ctx context.Context, in *AuthRoleRevokePermissionRequest, opts ...grpc.CallOption) (*AuthRoleRevokePermissionResponse, error)
+}
+
+type authClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewAuthClient(cc *grpc.ClientConn) AuthClient {
+ return &authClient{cc}
+}
+
+func (c *authClient) AuthEnable(ctx context.Context, in *AuthEnableRequest, opts ...grpc.CallOption) (*AuthEnableResponse, error) {
+ out := new(AuthEnableResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/AuthEnable", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) AuthDisable(ctx context.Context, in *AuthDisableRequest, opts ...grpc.CallOption) (*AuthDisableResponse, error) {
+ out := new(AuthDisableResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/AuthDisable", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error) {
+ out := new(AuthenticateResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/Authenticate", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) UserAdd(ctx context.Context, in *AuthUserAddRequest, opts ...grpc.CallOption) (*AuthUserAddResponse, error) {
+ out := new(AuthUserAddResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/UserAdd", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) UserGet(ctx context.Context, in *AuthUserGetRequest, opts ...grpc.CallOption) (*AuthUserGetResponse, error) {
+ out := new(AuthUserGetResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/UserGet", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) UserList(ctx context.Context, in *AuthUserListRequest, opts ...grpc.CallOption) (*AuthUserListResponse, error) {
+ out := new(AuthUserListResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/UserList", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) UserDelete(ctx context.Context, in *AuthUserDeleteRequest, opts ...grpc.CallOption) (*AuthUserDeleteResponse, error) {
+ out := new(AuthUserDeleteResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/UserDelete", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) UserChangePassword(ctx context.Context, in *AuthUserChangePasswordRequest, opts ...grpc.CallOption) (*AuthUserChangePasswordResponse, error) {
+ out := new(AuthUserChangePasswordResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/UserChangePassword", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) UserGrantRole(ctx context.Context, in *AuthUserGrantRoleRequest, opts ...grpc.CallOption) (*AuthUserGrantRoleResponse, error) {
+ out := new(AuthUserGrantRoleResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/UserGrantRole", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) UserRevokeRole(ctx context.Context, in *AuthUserRevokeRoleRequest, opts ...grpc.CallOption) (*AuthUserRevokeRoleResponse, error) {
+ out := new(AuthUserRevokeRoleResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/UserRevokeRole", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) RoleAdd(ctx context.Context, in *AuthRoleAddRequest, opts ...grpc.CallOption) (*AuthRoleAddResponse, error) {
+ out := new(AuthRoleAddResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/RoleAdd", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) RoleGet(ctx context.Context, in *AuthRoleGetRequest, opts ...grpc.CallOption) (*AuthRoleGetResponse, error) {
+ out := new(AuthRoleGetResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/RoleGet", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) RoleList(ctx context.Context, in *AuthRoleListRequest, opts ...grpc.CallOption) (*AuthRoleListResponse, error) {
+ out := new(AuthRoleListResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/RoleList", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) RoleDelete(ctx context.Context, in *AuthRoleDeleteRequest, opts ...grpc.CallOption) (*AuthRoleDeleteResponse, error) {
+ out := new(AuthRoleDeleteResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/RoleDelete", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) RoleGrantPermission(ctx context.Context, in *AuthRoleGrantPermissionRequest, opts ...grpc.CallOption) (*AuthRoleGrantPermissionResponse, error) {
+ out := new(AuthRoleGrantPermissionResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/RoleGrantPermission", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *authClient) RoleRevokePermission(ctx context.Context, in *AuthRoleRevokePermissionRequest, opts ...grpc.CallOption) (*AuthRoleRevokePermissionResponse, error) {
+ out := new(AuthRoleRevokePermissionResponse)
+ err := grpc.Invoke(ctx, "/etcdserverpb.Auth/RoleRevokePermission", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// Server API for Auth service
+
+type AuthServer interface {
+ // AuthEnable enables authentication.
+ AuthEnable(context.Context, *AuthEnableRequest) (*AuthEnableResponse, error)
+ // AuthDisable disables authentication.
+ AuthDisable(context.Context, *AuthDisableRequest) (*AuthDisableResponse, error)
+ // Authenticate processes an authenticate request.
+ Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error)
+ // UserAdd adds a new user.
+ UserAdd(context.Context, *AuthUserAddRequest) (*AuthUserAddResponse, error)
+ // UserGet gets detailed user information.
+ UserGet(context.Context, *AuthUserGetRequest) (*AuthUserGetResponse, error)
+ // UserList gets a list of all users.
+ UserList(context.Context, *AuthUserListRequest) (*AuthUserListResponse, error)
+ // UserDelete deletes a specified user.
+ UserDelete(context.Context, *AuthUserDeleteRequest) (*AuthUserDeleteResponse, error)
+ // UserChangePassword changes the password of a specified user.
+ UserChangePassword(context.Context, *AuthUserChangePasswordRequest) (*AuthUserChangePasswordResponse, error)
+ // UserGrant grants a role to a specified user.
+ UserGrantRole(context.Context, *AuthUserGrantRoleRequest) (*AuthUserGrantRoleResponse, error)
+ // UserRevokeRole revokes a role of specified user.
+ UserRevokeRole(context.Context, *AuthUserRevokeRoleRequest) (*AuthUserRevokeRoleResponse, error)
+ // RoleAdd adds a new role.
+ RoleAdd(context.Context, *AuthRoleAddRequest) (*AuthRoleAddResponse, error)
+ // RoleGet gets detailed role information.
+ RoleGet(context.Context, *AuthRoleGetRequest) (*AuthRoleGetResponse, error)
+ // RoleList gets lists of all roles.
+ RoleList(context.Context, *AuthRoleListRequest) (*AuthRoleListResponse, error)
+ // RoleDelete deletes a specified role.
+ RoleDelete(context.Context, *AuthRoleDeleteRequest) (*AuthRoleDeleteResponse, error)
+ // RoleGrantPermission grants a permission of a specified key or range to a specified role.
+ RoleGrantPermission(context.Context, *AuthRoleGrantPermissionRequest) (*AuthRoleGrantPermissionResponse, error)
+ // RoleRevokePermission revokes a key or range permission of a specified role.
+ RoleRevokePermission(context.Context, *AuthRoleRevokePermissionRequest) (*AuthRoleRevokePermissionResponse, error)
+}
+
+func RegisterAuthServer(s *grpc.Server, srv AuthServer) {
+ s.RegisterService(&_Auth_serviceDesc, srv)
+}
+
+func _Auth_AuthEnable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthEnableRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).AuthEnable(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/AuthEnable",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).AuthEnable(ctx, req.(*AuthEnableRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_AuthDisable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthDisableRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).AuthDisable(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/AuthDisable",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).AuthDisable(ctx, req.(*AuthDisableRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthenticateRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).Authenticate(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/Authenticate",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).Authenticate(ctx, req.(*AuthenticateRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_UserAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthUserAddRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).UserAdd(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/UserAdd",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).UserAdd(ctx, req.(*AuthUserAddRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_UserGet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthUserGetRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).UserGet(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/UserGet",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).UserGet(ctx, req.(*AuthUserGetRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_UserList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthUserListRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).UserList(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/UserList",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).UserList(ctx, req.(*AuthUserListRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_UserDelete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthUserDeleteRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).UserDelete(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/UserDelete",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).UserDelete(ctx, req.(*AuthUserDeleteRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_UserChangePassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthUserChangePasswordRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).UserChangePassword(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/UserChangePassword",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).UserChangePassword(ctx, req.(*AuthUserChangePasswordRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_UserGrantRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthUserGrantRoleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).UserGrantRole(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/UserGrantRole",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).UserGrantRole(ctx, req.(*AuthUserGrantRoleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_UserRevokeRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthUserRevokeRoleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).UserRevokeRole(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/UserRevokeRole",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).UserRevokeRole(ctx, req.(*AuthUserRevokeRoleRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_RoleAdd_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthRoleAddRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).RoleAdd(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/RoleAdd",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).RoleAdd(ctx, req.(*AuthRoleAddRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_RoleGet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthRoleGetRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).RoleGet(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/RoleGet",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).RoleGet(ctx, req.(*AuthRoleGetRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_RoleList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthRoleListRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).RoleList(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/RoleList",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).RoleList(ctx, req.(*AuthRoleListRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_RoleDelete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthRoleDeleteRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).RoleDelete(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/RoleDelete",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).RoleDelete(ctx, req.(*AuthRoleDeleteRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_RoleGrantPermission_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthRoleGrantPermissionRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).RoleGrantPermission(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/RoleGrantPermission",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).RoleGrantPermission(ctx, req.(*AuthRoleGrantPermissionRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_RoleRevokePermission_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AuthRoleRevokePermissionRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AuthServer).RoleRevokePermission(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/etcdserverpb.Auth/RoleRevokePermission",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AuthServer).RoleRevokePermission(ctx, req.(*AuthRoleRevokePermissionRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Auth_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "etcdserverpb.Auth",
+ HandlerType: (*AuthServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "AuthEnable",
+ Handler: _Auth_AuthEnable_Handler,
+ },
+ {
+ MethodName: "AuthDisable",
+ Handler: _Auth_AuthDisable_Handler,
+ },
+ {
+ MethodName: "Authenticate",
+ Handler: _Auth_Authenticate_Handler,
+ },
+ {
+ MethodName: "UserAdd",
+ Handler: _Auth_UserAdd_Handler,
+ },
+ {
+ MethodName: "UserGet",
+ Handler: _Auth_UserGet_Handler,
+ },
+ {
+ MethodName: "UserList",
+ Handler: _Auth_UserList_Handler,
+ },
+ {
+ MethodName: "UserDelete",
+ Handler: _Auth_UserDelete_Handler,
+ },
+ {
+ MethodName: "UserChangePassword",
+ Handler: _Auth_UserChangePassword_Handler,
+ },
+ {
+ MethodName: "UserGrantRole",
+ Handler: _Auth_UserGrantRole_Handler,
+ },
+ {
+ MethodName: "UserRevokeRole",
+ Handler: _Auth_UserRevokeRole_Handler,
+ },
+ {
+ MethodName: "RoleAdd",
+ Handler: _Auth_RoleAdd_Handler,
+ },
+ {
+ MethodName: "RoleGet",
+ Handler: _Auth_RoleGet_Handler,
+ },
+ {
+ MethodName: "RoleList",
+ Handler: _Auth_RoleList_Handler,
+ },
+ {
+ MethodName: "RoleDelete",
+ Handler: _Auth_RoleDelete_Handler,
+ },
+ {
+ MethodName: "RoleGrantPermission",
+ Handler: _Auth_RoleGrantPermission_Handler,
+ },
+ {
+ MethodName: "RoleRevokePermission",
+ Handler: _Auth_RoleRevokePermission_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "rpc.proto",
+}
+
+func (m *ResponseHeader) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ResponseHeader) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ClusterId != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ClusterId))
+ }
+ if m.MemberId != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.MemberId))
+ }
+ if m.Revision != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Revision))
+ }
+ if m.RaftTerm != 0 {
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RaftTerm))
+ }
+ return i, nil
+}
+
+func (m *RangeRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *RangeRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Key) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if len(m.RangeEnd) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.RangeEnd)))
+ i += copy(dAtA[i:], m.RangeEnd)
+ }
+ if m.Limit != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Limit))
+ }
+ if m.Revision != 0 {
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Revision))
+ }
+ if m.SortOrder != 0 {
+ dAtA[i] = 0x28
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.SortOrder))
+ }
+ if m.SortTarget != 0 {
+ dAtA[i] = 0x30
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.SortTarget))
+ }
+ if m.Serializable {
+ dAtA[i] = 0x38
+ i++
+ if m.Serializable {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.KeysOnly {
+ dAtA[i] = 0x40
+ i++
+ if m.KeysOnly {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.CountOnly {
+ dAtA[i] = 0x48
+ i++
+ if m.CountOnly {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.MinModRevision != 0 {
+ dAtA[i] = 0x50
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.MinModRevision))
+ }
+ if m.MaxModRevision != 0 {
+ dAtA[i] = 0x58
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.MaxModRevision))
+ }
+ if m.MinCreateRevision != 0 {
+ dAtA[i] = 0x60
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.MinCreateRevision))
+ }
+ if m.MaxCreateRevision != 0 {
+ dAtA[i] = 0x68
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.MaxCreateRevision))
+ }
+ return i, nil
+}
+
+func (m *RangeResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *RangeResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n1, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ }
+ if len(m.Kvs) > 0 {
+ for _, msg := range m.Kvs {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ if m.More {
+ dAtA[i] = 0x18
+ i++
+ if m.More {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.Count != 0 {
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Count))
+ }
+ return i, nil
+}
+
+func (m *PutRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *PutRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Key) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if len(m.Value) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Value)))
+ i += copy(dAtA[i:], m.Value)
+ }
+ if m.Lease != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Lease))
+ }
+ if m.PrevKv {
+ dAtA[i] = 0x20
+ i++
+ if m.PrevKv {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.IgnoreValue {
+ dAtA[i] = 0x28
+ i++
+ if m.IgnoreValue {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.IgnoreLease {
+ dAtA[i] = 0x30
+ i++
+ if m.IgnoreLease {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ return i, nil
+}
+
+func (m *PutResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *PutResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n2, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n2
+ }
+ if m.PrevKv != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.PrevKv.Size()))
+ n3, err := m.PrevKv.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n3
+ }
+ return i, nil
+}
+
+func (m *DeleteRangeRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *DeleteRangeRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Key) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if len(m.RangeEnd) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.RangeEnd)))
+ i += copy(dAtA[i:], m.RangeEnd)
+ }
+ if m.PrevKv {
+ dAtA[i] = 0x18
+ i++
+ if m.PrevKv {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ return i, nil
+}
+
+func (m *DeleteRangeResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *DeleteRangeResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n4, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n4
+ }
+ if m.Deleted != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Deleted))
+ }
+ if len(m.PrevKvs) > 0 {
+ for _, msg := range m.PrevKvs {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *RequestOp) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *RequestOp) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Request != nil {
+ nn5, err := m.Request.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += nn5
+ }
+ return i, nil
+}
+
+func (m *RequestOp_RequestRange) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.RequestRange != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RequestRange.Size()))
+ n6, err := m.RequestRange.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n6
+ }
+ return i, nil
+}
+func (m *RequestOp_RequestPut) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.RequestPut != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RequestPut.Size()))
+ n7, err := m.RequestPut.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n7
+ }
+ return i, nil
+}
+func (m *RequestOp_RequestDeleteRange) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.RequestDeleteRange != nil {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RequestDeleteRange.Size()))
+ n8, err := m.RequestDeleteRange.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n8
+ }
+ return i, nil
+}
+func (m *RequestOp_RequestTxn) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.RequestTxn != nil {
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RequestTxn.Size()))
+ n9, err := m.RequestTxn.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n9
+ }
+ return i, nil
+}
+func (m *ResponseOp) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ResponseOp) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Response != nil {
+ nn10, err := m.Response.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += nn10
+ }
+ return i, nil
+}
+
+func (m *ResponseOp_ResponseRange) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.ResponseRange != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ResponseRange.Size()))
+ n11, err := m.ResponseRange.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n11
+ }
+ return i, nil
+}
+func (m *ResponseOp_ResponsePut) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.ResponsePut != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ResponsePut.Size()))
+ n12, err := m.ResponsePut.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n12
+ }
+ return i, nil
+}
+func (m *ResponseOp_ResponseDeleteRange) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.ResponseDeleteRange != nil {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ResponseDeleteRange.Size()))
+ n13, err := m.ResponseDeleteRange.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n13
+ }
+ return i, nil
+}
+func (m *ResponseOp_ResponseTxn) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.ResponseTxn != nil {
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ResponseTxn.Size()))
+ n14, err := m.ResponseTxn.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n14
+ }
+ return i, nil
+}
+func (m *Compare) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Compare) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Result != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Result))
+ }
+ if m.Target != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Target))
+ }
+ if len(m.Key) > 0 {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if m.TargetUnion != nil {
+ nn15, err := m.TargetUnion.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += nn15
+ }
+ if len(m.RangeEnd) > 0 {
+ dAtA[i] = 0x82
+ i++
+ dAtA[i] = 0x4
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.RangeEnd)))
+ i += copy(dAtA[i:], m.RangeEnd)
+ }
+ return i, nil
+}
+
+func (m *Compare_Version) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Version))
+ return i, nil
+}
+func (m *Compare_CreateRevision) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x28
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.CreateRevision))
+ return i, nil
+}
+func (m *Compare_ModRevision) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x30
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ModRevision))
+ return i, nil
+}
+func (m *Compare_Value) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.Value != nil {
+ dAtA[i] = 0x3a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Value)))
+ i += copy(dAtA[i:], m.Value)
+ }
+ return i, nil
+}
+func (m *Compare_Lease) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ dAtA[i] = 0x40
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Lease))
+ return i, nil
+}
+func (m *TxnRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *TxnRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Compare) > 0 {
+ for _, msg := range m.Compare {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ if len(m.Success) > 0 {
+ for _, msg := range m.Success {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ if len(m.Failure) > 0 {
+ for _, msg := range m.Failure {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *TxnResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *TxnResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n16, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n16
+ }
+ if m.Succeeded {
+ dAtA[i] = 0x10
+ i++
+ if m.Succeeded {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if len(m.Responses) > 0 {
+ for _, msg := range m.Responses {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *CompactionRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *CompactionRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Revision != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Revision))
+ }
+ if m.Physical {
+ dAtA[i] = 0x10
+ i++
+ if m.Physical {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ return i, nil
+}
+
+func (m *CompactionResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *CompactionResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n17, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n17
+ }
+ return i, nil
+}
+
+func (m *HashRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *HashRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *HashKVRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *HashKVRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Revision != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Revision))
+ }
+ return i, nil
+}
+
+func (m *HashKVResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *HashKVResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n18, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n18
+ }
+ if m.Hash != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Hash))
+ }
+ if m.CompactRevision != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.CompactRevision))
+ }
+ return i, nil
+}
+
+func (m *HashResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *HashResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n19, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n19
+ }
+ if m.Hash != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Hash))
+ }
+ return i, nil
+}
+
+func (m *SnapshotRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *SnapshotRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *SnapshotResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *SnapshotResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n20, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n20
+ }
+ if m.RemainingBytes != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RemainingBytes))
+ }
+ if len(m.Blob) > 0 {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Blob)))
+ i += copy(dAtA[i:], m.Blob)
+ }
+ return i, nil
+}
+
+func (m *WatchRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *WatchRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.RequestUnion != nil {
+ nn21, err := m.RequestUnion.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += nn21
+ }
+ return i, nil
+}
+
+func (m *WatchRequest_CreateRequest) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.CreateRequest != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.CreateRequest.Size()))
+ n22, err := m.CreateRequest.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n22
+ }
+ return i, nil
+}
+func (m *WatchRequest_CancelRequest) MarshalTo(dAtA []byte) (int, error) {
+ i := 0
+ if m.CancelRequest != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.CancelRequest.Size()))
+ n23, err := m.CancelRequest.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n23
+ }
+ return i, nil
+}
+func (m *WatchCreateRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *WatchCreateRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Key) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if len(m.RangeEnd) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.RangeEnd)))
+ i += copy(dAtA[i:], m.RangeEnd)
+ }
+ if m.StartRevision != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.StartRevision))
+ }
+ if m.ProgressNotify {
+ dAtA[i] = 0x20
+ i++
+ if m.ProgressNotify {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if len(m.Filters) > 0 {
+ dAtA25 := make([]byte, len(m.Filters)*10)
+ var j24 int
+ for _, num := range m.Filters {
+ for num >= 1<<7 {
+ dAtA25[j24] = uint8(uint64(num)&0x7f | 0x80)
+ num >>= 7
+ j24++
+ }
+ dAtA25[j24] = uint8(num)
+ j24++
+ }
+ dAtA[i] = 0x2a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(j24))
+ i += copy(dAtA[i:], dAtA25[:j24])
+ }
+ if m.PrevKv {
+ dAtA[i] = 0x30
+ i++
+ if m.PrevKv {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ return i, nil
+}
+
+func (m *WatchCancelRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *WatchCancelRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.WatchId != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.WatchId))
+ }
+ return i, nil
+}
+
+func (m *WatchResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *WatchResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n26, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n26
+ }
+ if m.WatchId != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.WatchId))
+ }
+ if m.Created {
+ dAtA[i] = 0x18
+ i++
+ if m.Created {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.Canceled {
+ dAtA[i] = 0x20
+ i++
+ if m.Canceled {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ if m.CompactRevision != 0 {
+ dAtA[i] = 0x28
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.CompactRevision))
+ }
+ if len(m.CancelReason) > 0 {
+ dAtA[i] = 0x32
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.CancelReason)))
+ i += copy(dAtA[i:], m.CancelReason)
+ }
+ if len(m.Events) > 0 {
+ for _, msg := range m.Events {
+ dAtA[i] = 0x5a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *LeaseGrantRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseGrantRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.TTL != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.TTL))
+ }
+ if m.ID != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ return i, nil
+}
+
+func (m *LeaseGrantResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseGrantResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n27, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n27
+ }
+ if m.ID != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.TTL))
+ }
+ if len(m.Error) > 0 {
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Error)))
+ i += copy(dAtA[i:], m.Error)
+ }
+ return i, nil
+}
+
+func (m *LeaseRevokeRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseRevokeRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ return i, nil
+}
+
+func (m *LeaseRevokeResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseRevokeResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n28, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n28
+ }
+ return i, nil
+}
+
+func (m *LeaseKeepAliveRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseKeepAliveRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ return i, nil
+}
+
+func (m *LeaseKeepAliveResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseKeepAliveResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n29, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n29
+ }
+ if m.ID != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.TTL))
+ }
+ return i, nil
+}
+
+func (m *LeaseTimeToLiveRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseTimeToLiveRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ if m.Keys {
+ dAtA[i] = 0x10
+ i++
+ if m.Keys {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ }
+ return i, nil
+}
+
+func (m *LeaseTimeToLiveResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseTimeToLiveResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n30, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n30
+ }
+ if m.ID != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.TTL))
+ }
+ if m.GrantedTTL != 0 {
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.GrantedTTL))
+ }
+ if len(m.Keys) > 0 {
+ for _, b := range m.Keys {
+ dAtA[i] = 0x2a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(b)))
+ i += copy(dAtA[i:], b)
+ }
+ }
+ return i, nil
+}
+
+func (m *LeaseLeasesRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseLeasesRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *LeaseStatus) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseStatus) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ return i, nil
+}
+
+func (m *LeaseLeasesResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseLeasesResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n31, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n31
+ }
+ if len(m.Leases) > 0 {
+ for _, msg := range m.Leases {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *Member) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Member) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ if len(m.Name) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.PeerURLs) > 0 {
+ for _, s := range m.PeerURLs {
+ dAtA[i] = 0x1a
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ if len(m.ClientURLs) > 0 {
+ for _, s := range m.ClientURLs {
+ dAtA[i] = 0x22
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func (m *MemberAddRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberAddRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.PeerURLs) > 0 {
+ for _, s := range m.PeerURLs {
+ dAtA[i] = 0xa
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func (m *MemberAddResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberAddResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n32, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n32
+ }
+ if m.Member != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Member.Size()))
+ n33, err := m.Member.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n33
+ }
+ if len(m.Members) > 0 {
+ for _, msg := range m.Members {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *MemberRemoveRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberRemoveRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ return i, nil
+}
+
+func (m *MemberRemoveResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberRemoveResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n34, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n34
+ }
+ if len(m.Members) > 0 {
+ for _, msg := range m.Members {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *MemberUpdateRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberUpdateRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.ID))
+ }
+ if len(m.PeerURLs) > 0 {
+ for _, s := range m.PeerURLs {
+ dAtA[i] = 0x12
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func (m *MemberUpdateResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberUpdateResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n35, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n35
+ }
+ if len(m.Members) > 0 {
+ for _, msg := range m.Members {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *MemberListRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberListRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *MemberListResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MemberListResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n36, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n36
+ }
+ if len(m.Members) > 0 {
+ for _, msg := range m.Members {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *DefragmentRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *DefragmentRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *DefragmentResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *DefragmentResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n37, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n37
+ }
+ return i, nil
+}
+
+func (m *MoveLeaderRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MoveLeaderRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.TargetID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.TargetID))
+ }
+ return i, nil
+}
+
+func (m *MoveLeaderResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *MoveLeaderResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n38, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n38
+ }
+ return i, nil
+}
+
+func (m *AlarmRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AlarmRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Action != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Action))
+ }
+ if m.MemberID != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.MemberID))
+ }
+ if m.Alarm != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Alarm))
+ }
+ return i, nil
+}
+
+func (m *AlarmMember) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AlarmMember) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.MemberID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.MemberID))
+ }
+ if m.Alarm != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Alarm))
+ }
+ return i, nil
+}
+
+func (m *AlarmResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AlarmResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n39, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n39
+ }
+ if len(m.Alarms) > 0 {
+ for _, msg := range m.Alarms {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *StatusRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *StatusRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *StatusResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n40, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n40
+ }
+ if len(m.Version) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Version)))
+ i += copy(dAtA[i:], m.Version)
+ }
+ if m.DbSize != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.DbSize))
+ }
+ if m.Leader != 0 {
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Leader))
+ }
+ if m.RaftIndex != 0 {
+ dAtA[i] = 0x28
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RaftIndex))
+ }
+ if m.RaftTerm != 0 {
+ dAtA[i] = 0x30
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.RaftTerm))
+ }
+ return i, nil
+}
+
+func (m *AuthEnableRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthEnableRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *AuthDisableRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthDisableRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *AuthenticateRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthenticateRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.Password) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Password)))
+ i += copy(dAtA[i:], m.Password)
+ }
+ return i, nil
+}
+
+func (m *AuthUserAddRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserAddRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.Password) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Password)))
+ i += copy(dAtA[i:], m.Password)
+ }
+ return i, nil
+}
+
+func (m *AuthUserGetRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserGetRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ return i, nil
+}
+
+func (m *AuthUserDeleteRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserDeleteRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ return i, nil
+}
+
+func (m *AuthUserChangePasswordRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserChangePasswordRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.Password) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Password)))
+ i += copy(dAtA[i:], m.Password)
+ }
+ return i, nil
+}
+
+func (m *AuthUserGrantRoleRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserGrantRoleRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.User) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.User)))
+ i += copy(dAtA[i:], m.User)
+ }
+ if len(m.Role) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Role)))
+ i += copy(dAtA[i:], m.Role)
+ }
+ return i, nil
+}
+
+func (m *AuthUserRevokeRoleRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserRevokeRoleRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if len(m.Role) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Role)))
+ i += copy(dAtA[i:], m.Role)
+ }
+ return i, nil
+}
+
+func (m *AuthRoleAddRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleAddRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ return i, nil
+}
+
+func (m *AuthRoleGetRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleGetRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Role) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Role)))
+ i += copy(dAtA[i:], m.Role)
+ }
+ return i, nil
+}
+
+func (m *AuthUserListRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserListRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *AuthRoleListRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleListRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ return i, nil
+}
+
+func (m *AuthRoleDeleteRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleDeleteRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Role) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Role)))
+ i += copy(dAtA[i:], m.Role)
+ }
+ return i, nil
+}
+
+func (m *AuthRoleGrantPermissionRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleGrantPermissionRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Name) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Name)))
+ i += copy(dAtA[i:], m.Name)
+ }
+ if m.Perm != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Perm.Size()))
+ n41, err := m.Perm.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n41
+ }
+ return i, nil
+}
+
+func (m *AuthRoleRevokePermissionRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleRevokePermissionRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Role) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Role)))
+ i += copy(dAtA[i:], m.Role)
+ }
+ if len(m.Key) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if len(m.RangeEnd) > 0 {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.RangeEnd)))
+ i += copy(dAtA[i:], m.RangeEnd)
+ }
+ return i, nil
+}
+
+func (m *AuthEnableResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthEnableResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n42, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n42
+ }
+ return i, nil
+}
+
+func (m *AuthDisableResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthDisableResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n43, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n43
+ }
+ return i, nil
+}
+
+func (m *AuthenticateResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthenticateResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n44, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n44
+ }
+ if len(m.Token) > 0 {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(len(m.Token)))
+ i += copy(dAtA[i:], m.Token)
+ }
+ return i, nil
+}
+
+func (m *AuthUserAddResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserAddResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n45, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n45
+ }
+ return i, nil
+}
+
+func (m *AuthUserGetResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserGetResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n46, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n46
+ }
+ if len(m.Roles) > 0 {
+ for _, s := range m.Roles {
+ dAtA[i] = 0x12
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func (m *AuthUserDeleteResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserDeleteResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n47, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n47
+ }
+ return i, nil
+}
+
+func (m *AuthUserChangePasswordResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserChangePasswordResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n48, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n48
+ }
+ return i, nil
+}
+
+func (m *AuthUserGrantRoleResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserGrantRoleResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n49, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n49
+ }
+ return i, nil
+}
+
+func (m *AuthUserRevokeRoleResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserRevokeRoleResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n50, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n50
+ }
+ return i, nil
+}
+
+func (m *AuthRoleAddResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleAddResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n51, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n51
+ }
+ return i, nil
+}
+
+func (m *AuthRoleGetResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleGetResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n52, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n52
+ }
+ if len(m.Perm) > 0 {
+ for _, msg := range m.Perm {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ return i, nil
+}
+
+func (m *AuthRoleListResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleListResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n53, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n53
+ }
+ if len(m.Roles) > 0 {
+ for _, s := range m.Roles {
+ dAtA[i] = 0x12
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func (m *AuthUserListResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthUserListResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n54, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n54
+ }
+ if len(m.Users) > 0 {
+ for _, s := range m.Users {
+ dAtA[i] = 0x12
+ i++
+ l = len(s)
+ for l >= 1<<7 {
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
+ l >>= 7
+ i++
+ }
+ dAtA[i] = uint8(l)
+ i++
+ i += copy(dAtA[i:], s)
+ }
+ }
+ return i, nil
+}
+
+func (m *AuthRoleDeleteResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleDeleteResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n55, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n55
+ }
+ return i, nil
+}
+
+func (m *AuthRoleGrantPermissionResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleGrantPermissionResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n56, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n56
+ }
+ return i, nil
+}
+
+func (m *AuthRoleRevokePermissionResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *AuthRoleRevokePermissionResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Header != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size()))
+ n57, err := m.Header.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n57
+ }
+ return i, nil
+}
+
+func encodeVarintRpc(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *ResponseHeader) Size() (n int) {
+ var l int
+ _ = l
+ if m.ClusterId != 0 {
+ n += 1 + sovRpc(uint64(m.ClusterId))
+ }
+ if m.MemberId != 0 {
+ n += 1 + sovRpc(uint64(m.MemberId))
+ }
+ if m.Revision != 0 {
+ n += 1 + sovRpc(uint64(m.Revision))
+ }
+ if m.RaftTerm != 0 {
+ n += 1 + sovRpc(uint64(m.RaftTerm))
+ }
+ return n
+}
+
+func (m *RangeRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.RangeEnd)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Limit != 0 {
+ n += 1 + sovRpc(uint64(m.Limit))
+ }
+ if m.Revision != 0 {
+ n += 1 + sovRpc(uint64(m.Revision))
+ }
+ if m.SortOrder != 0 {
+ n += 1 + sovRpc(uint64(m.SortOrder))
+ }
+ if m.SortTarget != 0 {
+ n += 1 + sovRpc(uint64(m.SortTarget))
+ }
+ if m.Serializable {
+ n += 2
+ }
+ if m.KeysOnly {
+ n += 2
+ }
+ if m.CountOnly {
+ n += 2
+ }
+ if m.MinModRevision != 0 {
+ n += 1 + sovRpc(uint64(m.MinModRevision))
+ }
+ if m.MaxModRevision != 0 {
+ n += 1 + sovRpc(uint64(m.MaxModRevision))
+ }
+ if m.MinCreateRevision != 0 {
+ n += 1 + sovRpc(uint64(m.MinCreateRevision))
+ }
+ if m.MaxCreateRevision != 0 {
+ n += 1 + sovRpc(uint64(m.MaxCreateRevision))
+ }
+ return n
+}
+
+func (m *RangeResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Kvs) > 0 {
+ for _, e := range m.Kvs {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ if m.More {
+ n += 2
+ }
+ if m.Count != 0 {
+ n += 1 + sovRpc(uint64(m.Count))
+ }
+ return n
+}
+
+func (m *PutRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Lease != 0 {
+ n += 1 + sovRpc(uint64(m.Lease))
+ }
+ if m.PrevKv {
+ n += 2
+ }
+ if m.IgnoreValue {
+ n += 2
+ }
+ if m.IgnoreLease {
+ n += 2
+ }
+ return n
+}
+
+func (m *PutResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.PrevKv != nil {
+ l = m.PrevKv.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *DeleteRangeRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.RangeEnd)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.PrevKv {
+ n += 2
+ }
+ return n
+}
+
+func (m *DeleteRangeResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Deleted != 0 {
+ n += 1 + sovRpc(uint64(m.Deleted))
+ }
+ if len(m.PrevKvs) > 0 {
+ for _, e := range m.PrevKvs {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *RequestOp) Size() (n int) {
+ var l int
+ _ = l
+ if m.Request != nil {
+ n += m.Request.Size()
+ }
+ return n
+}
+
+func (m *RequestOp_RequestRange) Size() (n int) {
+ var l int
+ _ = l
+ if m.RequestRange != nil {
+ l = m.RequestRange.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *RequestOp_RequestPut) Size() (n int) {
+ var l int
+ _ = l
+ if m.RequestPut != nil {
+ l = m.RequestPut.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *RequestOp_RequestDeleteRange) Size() (n int) {
+ var l int
+ _ = l
+ if m.RequestDeleteRange != nil {
+ l = m.RequestDeleteRange.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *RequestOp_RequestTxn) Size() (n int) {
+ var l int
+ _ = l
+ if m.RequestTxn != nil {
+ l = m.RequestTxn.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *ResponseOp) Size() (n int) {
+ var l int
+ _ = l
+ if m.Response != nil {
+ n += m.Response.Size()
+ }
+ return n
+}
+
+func (m *ResponseOp_ResponseRange) Size() (n int) {
+ var l int
+ _ = l
+ if m.ResponseRange != nil {
+ l = m.ResponseRange.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *ResponseOp_ResponsePut) Size() (n int) {
+ var l int
+ _ = l
+ if m.ResponsePut != nil {
+ l = m.ResponsePut.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *ResponseOp_ResponseDeleteRange) Size() (n int) {
+ var l int
+ _ = l
+ if m.ResponseDeleteRange != nil {
+ l = m.ResponseDeleteRange.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *ResponseOp_ResponseTxn) Size() (n int) {
+ var l int
+ _ = l
+ if m.ResponseTxn != nil {
+ l = m.ResponseTxn.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *Compare) Size() (n int) {
+ var l int
+ _ = l
+ if m.Result != 0 {
+ n += 1 + sovRpc(uint64(m.Result))
+ }
+ if m.Target != 0 {
+ n += 1 + sovRpc(uint64(m.Target))
+ }
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.TargetUnion != nil {
+ n += m.TargetUnion.Size()
+ }
+ l = len(m.RangeEnd)
+ if l > 0 {
+ n += 2 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *Compare_Version) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRpc(uint64(m.Version))
+ return n
+}
+func (m *Compare_CreateRevision) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRpc(uint64(m.CreateRevision))
+ return n
+}
+func (m *Compare_ModRevision) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRpc(uint64(m.ModRevision))
+ return n
+}
+func (m *Compare_Value) Size() (n int) {
+ var l int
+ _ = l
+ if m.Value != nil {
+ l = len(m.Value)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *Compare_Lease) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRpc(uint64(m.Lease))
+ return n
+}
+func (m *TxnRequest) Size() (n int) {
+ var l int
+ _ = l
+ if len(m.Compare) > 0 {
+ for _, e := range m.Compare {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ if len(m.Success) > 0 {
+ for _, e := range m.Success {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ if len(m.Failure) > 0 {
+ for _, e := range m.Failure {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *TxnResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Succeeded {
+ n += 2
+ }
+ if len(m.Responses) > 0 {
+ for _, e := range m.Responses {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *CompactionRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.Revision != 0 {
+ n += 1 + sovRpc(uint64(m.Revision))
+ }
+ if m.Physical {
+ n += 2
+ }
+ return n
+}
+
+func (m *CompactionResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *HashRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *HashKVRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.Revision != 0 {
+ n += 1 + sovRpc(uint64(m.Revision))
+ }
+ return n
+}
+
+func (m *HashKVResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Hash != 0 {
+ n += 1 + sovRpc(uint64(m.Hash))
+ }
+ if m.CompactRevision != 0 {
+ n += 1 + sovRpc(uint64(m.CompactRevision))
+ }
+ return n
+}
+
+func (m *HashResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Hash != 0 {
+ n += 1 + sovRpc(uint64(m.Hash))
+ }
+ return n
+}
+
+func (m *SnapshotRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *SnapshotResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.RemainingBytes != 0 {
+ n += 1 + sovRpc(uint64(m.RemainingBytes))
+ }
+ l = len(m.Blob)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *WatchRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.RequestUnion != nil {
+ n += m.RequestUnion.Size()
+ }
+ return n
+}
+
+func (m *WatchRequest_CreateRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.CreateRequest != nil {
+ l = m.CreateRequest.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *WatchRequest_CancelRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.CancelRequest != nil {
+ l = m.CancelRequest.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+func (m *WatchCreateRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.RangeEnd)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.StartRevision != 0 {
+ n += 1 + sovRpc(uint64(m.StartRevision))
+ }
+ if m.ProgressNotify {
+ n += 2
+ }
+ if len(m.Filters) > 0 {
+ l = 0
+ for _, e := range m.Filters {
+ l += sovRpc(uint64(e))
+ }
+ n += 1 + sovRpc(uint64(l)) + l
+ }
+ if m.PrevKv {
+ n += 2
+ }
+ return n
+}
+
+func (m *WatchCancelRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.WatchId != 0 {
+ n += 1 + sovRpc(uint64(m.WatchId))
+ }
+ return n
+}
+
+func (m *WatchResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.WatchId != 0 {
+ n += 1 + sovRpc(uint64(m.WatchId))
+ }
+ if m.Created {
+ n += 2
+ }
+ if m.Canceled {
+ n += 2
+ }
+ if m.CompactRevision != 0 {
+ n += 1 + sovRpc(uint64(m.CompactRevision))
+ }
+ l = len(m.CancelReason)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Events) > 0 {
+ for _, e := range m.Events {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *LeaseGrantRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.TTL != 0 {
+ n += 1 + sovRpc(uint64(m.TTL))
+ }
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ return n
+}
+
+func (m *LeaseGrantResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ n += 1 + sovRpc(uint64(m.TTL))
+ }
+ l = len(m.Error)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *LeaseRevokeRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ return n
+}
+
+func (m *LeaseRevokeResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *LeaseKeepAliveRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ return n
+}
+
+func (m *LeaseKeepAliveResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ n += 1 + sovRpc(uint64(m.TTL))
+ }
+ return n
+}
+
+func (m *LeaseTimeToLiveRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ if m.Keys {
+ n += 2
+ }
+ return n
+}
+
+func (m *LeaseTimeToLiveResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ n += 1 + sovRpc(uint64(m.TTL))
+ }
+ if m.GrantedTTL != 0 {
+ n += 1 + sovRpc(uint64(m.GrantedTTL))
+ }
+ if len(m.Keys) > 0 {
+ for _, b := range m.Keys {
+ l = len(b)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *LeaseLeasesRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *LeaseStatus) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ return n
+}
+
+func (m *LeaseLeasesResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Leases) > 0 {
+ for _, e := range m.Leases {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *Member) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.PeerURLs) > 0 {
+ for _, s := range m.PeerURLs {
+ l = len(s)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ if len(m.ClientURLs) > 0 {
+ for _, s := range m.ClientURLs {
+ l = len(s)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *MemberAddRequest) Size() (n int) {
+ var l int
+ _ = l
+ if len(m.PeerURLs) > 0 {
+ for _, s := range m.PeerURLs {
+ l = len(s)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *MemberAddResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Member != nil {
+ l = m.Member.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Members) > 0 {
+ for _, e := range m.Members {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *MemberRemoveRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ return n
+}
+
+func (m *MemberRemoveResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Members) > 0 {
+ for _, e := range m.Members {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *MemberUpdateRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovRpc(uint64(m.ID))
+ }
+ if len(m.PeerURLs) > 0 {
+ for _, s := range m.PeerURLs {
+ l = len(s)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *MemberUpdateResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Members) > 0 {
+ for _, e := range m.Members {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *MemberListRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *MemberListResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Members) > 0 {
+ for _, e := range m.Members {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *DefragmentRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *DefragmentResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *MoveLeaderRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.TargetID != 0 {
+ n += 1 + sovRpc(uint64(m.TargetID))
+ }
+ return n
+}
+
+func (m *MoveLeaderResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AlarmRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.Action != 0 {
+ n += 1 + sovRpc(uint64(m.Action))
+ }
+ if m.MemberID != 0 {
+ n += 1 + sovRpc(uint64(m.MemberID))
+ }
+ if m.Alarm != 0 {
+ n += 1 + sovRpc(uint64(m.Alarm))
+ }
+ return n
+}
+
+func (m *AlarmMember) Size() (n int) {
+ var l int
+ _ = l
+ if m.MemberID != 0 {
+ n += 1 + sovRpc(uint64(m.MemberID))
+ }
+ if m.Alarm != 0 {
+ n += 1 + sovRpc(uint64(m.Alarm))
+ }
+ return n
+}
+
+func (m *AlarmResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Alarms) > 0 {
+ for _, e := range m.Alarms {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *StatusRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *StatusResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Version)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.DbSize != 0 {
+ n += 1 + sovRpc(uint64(m.DbSize))
+ }
+ if m.Leader != 0 {
+ n += 1 + sovRpc(uint64(m.Leader))
+ }
+ if m.RaftIndex != 0 {
+ n += 1 + sovRpc(uint64(m.RaftIndex))
+ }
+ if m.RaftTerm != 0 {
+ n += 1 + sovRpc(uint64(m.RaftTerm))
+ }
+ return n
+}
+
+func (m *AuthEnableRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *AuthDisableRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *AuthenticateRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Password)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserAddRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Password)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserGetRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserDeleteRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserChangePasswordRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Password)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserGrantRoleRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.User)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Role)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserRevokeRoleRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Role)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleAddRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleGetRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Role)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserListRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *AuthRoleListRequest) Size() (n int) {
+ var l int
+ _ = l
+ return n
+}
+
+func (m *AuthRoleDeleteRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Role)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleGrantPermissionRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Name)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if m.Perm != nil {
+ l = m.Perm.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleRevokePermissionRequest) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Role)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.RangeEnd)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthEnableResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthDisableResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthenticateResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ l = len(m.Token)
+ if l > 0 {
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserAddResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserGetResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Roles) > 0 {
+ for _, s := range m.Roles {
+ l = len(s)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *AuthUserDeleteResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserChangePasswordResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserGrantRoleResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthUserRevokeRoleResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleAddResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleGetResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Perm) > 0 {
+ for _, e := range m.Perm {
+ l = e.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *AuthRoleListResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Roles) > 0 {
+ for _, s := range m.Roles {
+ l = len(s)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *AuthUserListResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ if len(m.Users) > 0 {
+ for _, s := range m.Users {
+ l = len(s)
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ }
+ return n
+}
+
+func (m *AuthRoleDeleteResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleGrantPermissionResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func (m *AuthRoleRevokePermissionResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.Header != nil {
+ l = m.Header.Size()
+ n += 1 + l + sovRpc(uint64(l))
+ }
+ return n
+}
+
+func sovRpc(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozRpc(x uint64) (n int) {
+ return sovRpc(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *ResponseHeader) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ResponseHeader: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ResponseHeader: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ClusterId", wireType)
+ }
+ m.ClusterId = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ClusterId |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MemberId", wireType)
+ }
+ m.MemberId = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.MemberId |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType)
+ }
+ m.Revision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Revision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RaftTerm", wireType)
+ }
+ m.RaftTerm = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.RaftTerm |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *RangeRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: RangeRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: RangeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RangeEnd", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.RangeEnd = append(m.RangeEnd[:0], dAtA[iNdEx:postIndex]...)
+ if m.RangeEnd == nil {
+ m.RangeEnd = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType)
+ }
+ m.Limit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Limit |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType)
+ }
+ m.Revision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Revision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field SortOrder", wireType)
+ }
+ m.SortOrder = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.SortOrder |= (RangeRequest_SortOrder(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field SortTarget", wireType)
+ }
+ m.SortTarget = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.SortTarget |= (RangeRequest_SortTarget(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 7:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Serializable", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Serializable = bool(v != 0)
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field KeysOnly", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.KeysOnly = bool(v != 0)
+ case 9:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CountOnly", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.CountOnly = bool(v != 0)
+ case 10:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MinModRevision", wireType)
+ }
+ m.MinModRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.MinModRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 11:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MaxModRevision", wireType)
+ }
+ m.MaxModRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.MaxModRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 12:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MinCreateRevision", wireType)
+ }
+ m.MinCreateRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.MinCreateRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 13:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MaxCreateRevision", wireType)
+ }
+ m.MaxCreateRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.MaxCreateRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *RangeResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: RangeResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: RangeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Kvs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Kvs = append(m.Kvs, &mvccpb.KeyValue{})
+ if err := m.Kvs[len(m.Kvs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field More", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.More = bool(v != 0)
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Count", wireType)
+ }
+ m.Count = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Count |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *PutRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: PutRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: PutRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
+ if m.Value == nil {
+ m.Value = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Lease", wireType)
+ }
+ m.Lease = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Lease |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevKv", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.PrevKv = bool(v != 0)
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field IgnoreValue", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.IgnoreValue = bool(v != 0)
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field IgnoreLease", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.IgnoreLease = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *PutResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: PutResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: PutResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevKv", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.PrevKv == nil {
+ m.PrevKv = &mvccpb.KeyValue{}
+ }
+ if err := m.PrevKv.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *DeleteRangeRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: DeleteRangeRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: DeleteRangeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RangeEnd", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.RangeEnd = append(m.RangeEnd[:0], dAtA[iNdEx:postIndex]...)
+ if m.RangeEnd == nil {
+ m.RangeEnd = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevKv", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.PrevKv = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *DeleteRangeResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: DeleteRangeResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: DeleteRangeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Deleted", wireType)
+ }
+ m.Deleted = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Deleted |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevKvs", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.PrevKvs = append(m.PrevKvs, &mvccpb.KeyValue{})
+ if err := m.PrevKvs[len(m.PrevKvs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *RequestOp) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: RequestOp: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: RequestOp: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RequestRange", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &RangeRequest{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Request = &RequestOp_RequestRange{v}
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RequestPut", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &PutRequest{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Request = &RequestOp_RequestPut{v}
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RequestDeleteRange", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &DeleteRangeRequest{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Request = &RequestOp_RequestDeleteRange{v}
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RequestTxn", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &TxnRequest{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Request = &RequestOp_RequestTxn{v}
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ResponseOp) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ResponseOp: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ResponseOp: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ResponseRange", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &RangeResponse{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Response = &ResponseOp_ResponseRange{v}
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ResponsePut", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &PutResponse{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Response = &ResponseOp_ResponsePut{v}
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ResponseDeleteRange", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &DeleteRangeResponse{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Response = &ResponseOp_ResponseDeleteRange{v}
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ResponseTxn", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &TxnResponse{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.Response = &ResponseOp_ResponseTxn{v}
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Compare) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Compare: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Compare: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType)
+ }
+ m.Result = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Result |= (Compare_CompareResult(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Target", wireType)
+ }
+ m.Target = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Target |= (Compare_CompareTarget(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
+ }
+ var v int64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.TargetUnion = &Compare_Version{v}
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CreateRevision", wireType)
+ }
+ var v int64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.TargetUnion = &Compare_CreateRevision{v}
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ModRevision", wireType)
+ }
+ var v int64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.TargetUnion = &Compare_ModRevision{v}
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := make([]byte, postIndex-iNdEx)
+ copy(v, dAtA[iNdEx:postIndex])
+ m.TargetUnion = &Compare_Value{v}
+ iNdEx = postIndex
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Lease", wireType)
+ }
+ var v int64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.TargetUnion = &Compare_Lease{v}
+ case 64:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RangeEnd", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.RangeEnd = append(m.RangeEnd[:0], dAtA[iNdEx:postIndex]...)
+ if m.RangeEnd == nil {
+ m.RangeEnd = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *TxnRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TxnRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TxnRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Compare", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Compare = append(m.Compare, &Compare{})
+ if err := m.Compare[len(m.Compare)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Success", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Success = append(m.Success, &RequestOp{})
+ if err := m.Success[len(m.Success)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Failure", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Failure = append(m.Failure, &RequestOp{})
+ if err := m.Failure[len(m.Failure)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *TxnResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: TxnResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: TxnResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Succeeded", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Succeeded = bool(v != 0)
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Responses", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Responses = append(m.Responses, &ResponseOp{})
+ if err := m.Responses[len(m.Responses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *CompactionRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: CompactionRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: CompactionRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType)
+ }
+ m.Revision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Revision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Physical", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Physical = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *CompactionResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: CompactionResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: CompactionResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *HashRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: HashRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: HashRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *HashKVRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: HashKVRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: HashKVRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType)
+ }
+ m.Revision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Revision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *HashKVResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: HashKVResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: HashKVResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ m.Hash = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Hash |= (uint32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CompactRevision", wireType)
+ }
+ m.CompactRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.CompactRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *HashResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: HashResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: HashResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
+ }
+ m.Hash = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Hash |= (uint32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *SnapshotRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: SnapshotRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: SnapshotRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *SnapshotResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: SnapshotResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: SnapshotResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RemainingBytes", wireType)
+ }
+ m.RemainingBytes = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.RemainingBytes |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Blob", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Blob = append(m.Blob[:0], dAtA[iNdEx:postIndex]...)
+ if m.Blob == nil {
+ m.Blob = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *WatchRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: WatchRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: WatchRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CreateRequest", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &WatchCreateRequest{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.RequestUnion = &WatchRequest_CreateRequest{v}
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CancelRequest", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ v := &WatchCancelRequest{}
+ if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ m.RequestUnion = &WatchRequest_CancelRequest{v}
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *WatchCreateRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: WatchCreateRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: WatchCreateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RangeEnd", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.RangeEnd = append(m.RangeEnd[:0], dAtA[iNdEx:postIndex]...)
+ if m.RangeEnd == nil {
+ m.RangeEnd = []byte{}
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field StartRevision", wireType)
+ }
+ m.StartRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.StartRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ProgressNotify", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.ProgressNotify = bool(v != 0)
+ case 5:
+ if wireType == 0 {
+ var v WatchCreateRequest_FilterType
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (WatchCreateRequest_FilterType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Filters = append(m.Filters, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ for iNdEx < postIndex {
+ var v WatchCreateRequest_FilterType
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (WatchCreateRequest_FilterType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Filters = append(m.Filters, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field Filters", wireType)
+ }
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevKv", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.PrevKv = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *WatchCancelRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: WatchCancelRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: WatchCancelRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field WatchId", wireType)
+ }
+ m.WatchId = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.WatchId |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *WatchResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: WatchResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: WatchResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field WatchId", wireType)
+ }
+ m.WatchId = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.WatchId |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Created", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Created = bool(v != 0)
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Canceled", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Canceled = bool(v != 0)
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CompactRevision", wireType)
+ }
+ m.CompactRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.CompactRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CancelReason", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.CancelReason = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 11:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Events = append(m.Events, &mvccpb.Event{})
+ if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseGrantRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseGrantRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseGrantRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+ }
+ m.TTL = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TTL |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseGrantResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseGrantResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseGrantResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+ }
+ m.TTL = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TTL |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Error = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseRevokeRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseRevokeRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseRevokeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseRevokeResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseRevokeResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseRevokeResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseKeepAliveRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseKeepAliveRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseKeepAliveRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseKeepAliveResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseKeepAliveResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseKeepAliveResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+ }
+ m.TTL = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TTL |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseTimeToLiveRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseTimeToLiveRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseTimeToLiveRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Keys", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Keys = bool(v != 0)
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseTimeToLiveResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseTimeToLiveResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseTimeToLiveResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+ }
+ m.TTL = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TTL |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field GrantedTTL", wireType)
+ }
+ m.GrantedTTL = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.GrantedTTL |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Keys", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Keys = append(m.Keys, make([]byte, postIndex-iNdEx))
+ copy(m.Keys[len(m.Keys)-1], dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseLeasesRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseLeasesRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseLeasesRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseStatus) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseStatus: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseStatus: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseLeasesResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseLeasesResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseLeasesResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Leases", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Leases = append(m.Leases, &LeaseStatus{})
+ if err := m.Leases[len(m.Leases)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Member) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Member: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Member: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PeerURLs", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.PeerURLs = append(m.PeerURLs, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ClientURLs", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.ClientURLs = append(m.ClientURLs, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberAddRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberAddRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberAddRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PeerURLs", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.PeerURLs = append(m.PeerURLs, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberAddResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberAddResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberAddResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Member", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Member == nil {
+ m.Member = &Member{}
+ }
+ if err := m.Member.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Members = append(m.Members, &Member{})
+ if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberRemoveRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberRemoveRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberRemoveRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberRemoveResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberRemoveResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberRemoveResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Members = append(m.Members, &Member{})
+ if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberUpdateRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberUpdateRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberUpdateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PeerURLs", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.PeerURLs = append(m.PeerURLs, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberUpdateResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberUpdateResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberUpdateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Members = append(m.Members, &Member{})
+ if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberListRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberListRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberListRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MemberListResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MemberListResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MemberListResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Members = append(m.Members, &Member{})
+ if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *DefragmentRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: DefragmentRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: DefragmentRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *DefragmentResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: DefragmentResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: DefragmentResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MoveLeaderRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MoveLeaderRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MoveLeaderRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TargetID", wireType)
+ }
+ m.TargetID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TargetID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *MoveLeaderResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: MoveLeaderResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: MoveLeaderResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AlarmRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AlarmRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AlarmRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Action", wireType)
+ }
+ m.Action = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Action |= (AlarmRequest_AlarmAction(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MemberID", wireType)
+ }
+ m.MemberID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.MemberID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Alarm", wireType)
+ }
+ m.Alarm = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Alarm |= (AlarmType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AlarmMember) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AlarmMember: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AlarmMember: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field MemberID", wireType)
+ }
+ m.MemberID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.MemberID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Alarm", wireType)
+ }
+ m.Alarm = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Alarm |= (AlarmType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AlarmResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AlarmResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AlarmResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Alarms", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Alarms = append(m.Alarms, &AlarmMember{})
+ if err := m.Alarms[len(m.Alarms)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *StatusRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: StatusRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: StatusRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *StatusResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: StatusResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: StatusResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Version = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field DbSize", wireType)
+ }
+ m.DbSize = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.DbSize |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Leader", wireType)
+ }
+ m.Leader = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Leader |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RaftIndex", wireType)
+ }
+ m.RaftIndex = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.RaftIndex |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RaftTerm", wireType)
+ }
+ m.RaftTerm = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.RaftTerm |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthEnableRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthEnableRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthEnableRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthDisableRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthDisableRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthDisableRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthenticateRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthenticateRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthenticateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Password = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserAddRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserAddRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserAddRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Password = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserGetRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserGetRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserGetRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserDeleteRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserDeleteRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserDeleteRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserChangePasswordRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserChangePasswordRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserChangePasswordRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Password = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserGrantRoleRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserGrantRoleRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserGrantRoleRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field User", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.User = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Role = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserRevokeRoleRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserRevokeRoleRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserRevokeRoleRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Role = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleAddRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleAddRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleAddRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleGetRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleGetRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleGetRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Role = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserListRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserListRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserListRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleListRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleListRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleListRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleDeleteRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleDeleteRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleDeleteRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Role = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleGrantPermissionRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleGrantPermissionRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleGrantPermissionRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Name = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Perm", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Perm == nil {
+ m.Perm = &authpb.Permission{}
+ }
+ if err := m.Perm.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleRevokePermissionRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleRevokePermissionRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleRevokePermissionRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Role", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Role = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RangeEnd", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.RangeEnd = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthEnableResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthEnableResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthEnableResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthDisableResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthDisableResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthDisableResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthenticateResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthenticateResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthenticateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Token = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserAddResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserAddResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserAddResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserGetResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserGetResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserGetResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Roles = append(m.Roles, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserDeleteResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserDeleteResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserDeleteResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserChangePasswordResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserChangePasswordResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserChangePasswordResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserGrantRoleResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserGrantRoleResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserGrantRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserRevokeRoleResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserRevokeRoleResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserRevokeRoleResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleAddResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleAddResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleAddResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleGetResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleGetResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleGetResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Perm", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Perm = append(m.Perm, &authpb.Permission{})
+ if err := m.Perm[len(m.Perm)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleListResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleListResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleListResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Roles = append(m.Roles, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthUserListResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthUserListResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthUserListResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Users", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Users = append(m.Users, string(dAtA[iNdEx:postIndex]))
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleDeleteResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleDeleteResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleDeleteResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleGrantPermissionResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleGrantPermissionResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleGrantPermissionResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *AuthRoleRevokePermissionResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: AuthRoleRevokePermissionResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: AuthRoleRevokePermissionResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRpc
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Header == nil {
+ m.Header = &ResponseHeader{}
+ }
+ if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRpc(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRpc
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipRpc(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthRpc
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRpc
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipRpc(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthRpc = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowRpc = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) }
+
+var fileDescriptorRpc = []byte{
+ // 3669 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x5b, 0x6f, 0x23, 0xc7,
+ 0x72, 0xd6, 0x90, 0x22, 0x29, 0x16, 0x2f, 0xe2, 0xb6, 0xb4, 0xbb, 0x14, 0x77, 0x57, 0xab, 0xed,
+ 0xbd, 0x69, 0x2f, 0x16, 0x6d, 0xd9, 0xc9, 0xc3, 0x26, 0x30, 0xac, 0x95, 0xe8, 0x95, 0x2c, 0xad,
+ 0x24, 0x8f, 0xa8, 0xb5, 0x03, 0x38, 0x11, 0x46, 0x64, 0x4b, 0x62, 0x44, 0xce, 0x30, 0x33, 0x43,
+ 0xae, 0xb4, 0x31, 0x12, 0xc0, 0x71, 0x82, 0xbc, 0xe4, 0x25, 0x06, 0x82, 0xc4, 0xaf, 0x41, 0x60,
+ 0xf8, 0x07, 0x04, 0xf9, 0x0b, 0x41, 0x5e, 0x12, 0x20, 0x7f, 0xe0, 0xc0, 0xe7, 0xbc, 0x9c, 0x5f,
+ 0x70, 0x2e, 0x4f, 0x07, 0x7d, 0x9b, 0xe9, 0xb9, 0x51, 0xb2, 0x69, 0xfb, 0x45, 0x3b, 0x5d, 0x5d,
+ 0x5d, 0x55, 0x5d, 0xdd, 0x55, 0xd5, 0xfd, 0x35, 0x17, 0xf2, 0x76, 0xbf, 0xb5, 0xd4, 0xb7, 0x2d,
+ 0xd7, 0x42, 0x45, 0xe2, 0xb6, 0xda, 0x0e, 0xb1, 0x87, 0xc4, 0xee, 0x1f, 0xd6, 0x66, 0x8f, 0xad,
+ 0x63, 0x8b, 0x75, 0xd4, 0xe9, 0x17, 0xe7, 0xa9, 0xcd, 0x51, 0x9e, 0x7a, 0x6f, 0xd8, 0x6a, 0xb1,
+ 0x3f, 0xfd, 0xc3, 0xfa, 0xe9, 0x50, 0x74, 0xdd, 0x60, 0x5d, 0xc6, 0xc0, 0x3d, 0x61, 0x7f, 0xfa,
+ 0x87, 0xec, 0x1f, 0xd1, 0x79, 0xf3, 0xd8, 0xb2, 0x8e, 0xbb, 0xa4, 0x6e, 0xf4, 0x3b, 0x75, 0xc3,
+ 0x34, 0x2d, 0xd7, 0x70, 0x3b, 0x96, 0xe9, 0xf0, 0x5e, 0xfc, 0xf7, 0x1a, 0x94, 0x75, 0xe2, 0xf4,
+ 0x2d, 0xd3, 0x21, 0xeb, 0xc4, 0x68, 0x13, 0x1b, 0xdd, 0x02, 0x68, 0x75, 0x07, 0x8e, 0x4b, 0xec,
+ 0x83, 0x4e, 0xbb, 0xaa, 0x2d, 0x68, 0x8b, 0x93, 0x7a, 0x5e, 0x50, 0x36, 0xda, 0xe8, 0x06, 0xe4,
+ 0x7b, 0xa4, 0x77, 0xc8, 0x7b, 0x53, 0xac, 0x77, 0x8a, 0x13, 0x36, 0xda, 0xa8, 0x06, 0x53, 0x36,
+ 0x19, 0x76, 0x9c, 0x8e, 0x65, 0x56, 0xd3, 0x0b, 0xda, 0x62, 0x5a, 0xf7, 0xda, 0x74, 0xa0, 0x6d,
+ 0x1c, 0xb9, 0x07, 0x2e, 0xb1, 0x7b, 0xd5, 0x49, 0x3e, 0x90, 0x12, 0x9a, 0xc4, 0xee, 0xe1, 0x2f,
+ 0x33, 0x50, 0xd4, 0x0d, 0xf3, 0x98, 0xe8, 0xe4, 0xaf, 0x06, 0xc4, 0x71, 0x51, 0x05, 0xd2, 0xa7,
+ 0xe4, 0x9c, 0xa9, 0x2f, 0xea, 0xf4, 0x93, 0x8f, 0x37, 0x8f, 0xc9, 0x01, 0x31, 0xb9, 0xe2, 0x22,
+ 0x1d, 0x6f, 0x1e, 0x93, 0x86, 0xd9, 0x46, 0xb3, 0x90, 0xe9, 0x76, 0x7a, 0x1d, 0x57, 0x68, 0xe5,
+ 0x8d, 0x80, 0x39, 0x93, 0x21, 0x73, 0x56, 0x01, 0x1c, 0xcb, 0x76, 0x0f, 0x2c, 0xbb, 0x4d, 0xec,
+ 0x6a, 0x66, 0x41, 0x5b, 0x2c, 0x2f, 0xdf, 0x5b, 0x52, 0x17, 0x62, 0x49, 0x35, 0x68, 0x69, 0xcf,
+ 0xb2, 0xdd, 0x1d, 0xca, 0xab, 0xe7, 0x1d, 0xf9, 0x89, 0x3e, 0x84, 0x02, 0x13, 0xe2, 0x1a, 0xf6,
+ 0x31, 0x71, 0xab, 0x59, 0x26, 0xe5, 0xfe, 0x05, 0x52, 0x9a, 0x8c, 0x59, 0x67, 0xea, 0xf9, 0x37,
+ 0xc2, 0x50, 0x74, 0x88, 0xdd, 0x31, 0xba, 0x9d, 0x37, 0xc6, 0x61, 0x97, 0x54, 0x73, 0x0b, 0xda,
+ 0xe2, 0x94, 0x1e, 0xa0, 0xd1, 0xf9, 0x9f, 0x92, 0x73, 0xe7, 0xc0, 0x32, 0xbb, 0xe7, 0xd5, 0x29,
+ 0xc6, 0x30, 0x45, 0x09, 0x3b, 0x66, 0xf7, 0x9c, 0x2d, 0x9a, 0x35, 0x30, 0x5d, 0xde, 0x9b, 0x67,
+ 0xbd, 0x79, 0x46, 0x61, 0xdd, 0x8b, 0x50, 0xe9, 0x75, 0xcc, 0x83, 0x9e, 0xd5, 0x3e, 0xf0, 0x1c,
+ 0x02, 0xcc, 0x21, 0xe5, 0x5e, 0xc7, 0x7c, 0x69, 0xb5, 0x75, 0xe9, 0x16, 0xca, 0x69, 0x9c, 0x05,
+ 0x39, 0x0b, 0x82, 0xd3, 0x38, 0x53, 0x39, 0x97, 0x60, 0x86, 0xca, 0x6c, 0xd9, 0xc4, 0x70, 0x89,
+ 0xcf, 0x5c, 0x64, 0xcc, 0x57, 0x7a, 0x1d, 0x73, 0x95, 0xf5, 0x04, 0xf8, 0x8d, 0xb3, 0x08, 0x7f,
+ 0x49, 0xf0, 0x1b, 0x67, 0x41, 0x7e, 0xbc, 0x04, 0x79, 0xcf, 0xe7, 0x68, 0x0a, 0x26, 0xb7, 0x77,
+ 0xb6, 0x1b, 0x95, 0x09, 0x04, 0x90, 0x5d, 0xd9, 0x5b, 0x6d, 0x6c, 0xaf, 0x55, 0x34, 0x54, 0x80,
+ 0xdc, 0x5a, 0x83, 0x37, 0x52, 0xf8, 0x39, 0x80, 0xef, 0x5d, 0x94, 0x83, 0xf4, 0x66, 0xe3, 0xcf,
+ 0x2a, 0x13, 0x94, 0xe7, 0x55, 0x43, 0xdf, 0xdb, 0xd8, 0xd9, 0xae, 0x68, 0x74, 0xf0, 0xaa, 0xde,
+ 0x58, 0x69, 0x36, 0x2a, 0x29, 0xca, 0xf1, 0x72, 0x67, 0xad, 0x92, 0x46, 0x79, 0xc8, 0xbc, 0x5a,
+ 0xd9, 0xda, 0x6f, 0x54, 0x26, 0xf1, 0x57, 0x1a, 0x94, 0xc4, 0x7a, 0xf1, 0x98, 0x40, 0xef, 0x41,
+ 0xf6, 0x84, 0xc5, 0x05, 0xdb, 0x8a, 0x85, 0xe5, 0x9b, 0xa1, 0xc5, 0x0d, 0xc4, 0x8e, 0x2e, 0x78,
+ 0x11, 0x86, 0xf4, 0xe9, 0xd0, 0xa9, 0xa6, 0x16, 0xd2, 0x8b, 0x85, 0xe5, 0xca, 0x12, 0x0f, 0xd8,
+ 0xa5, 0x4d, 0x72, 0xfe, 0xca, 0xe8, 0x0e, 0x88, 0x4e, 0x3b, 0x11, 0x82, 0xc9, 0x9e, 0x65, 0x13,
+ 0xb6, 0x63, 0xa7, 0x74, 0xf6, 0x4d, 0xb7, 0x31, 0x5b, 0x34, 0xb1, 0x5b, 0x79, 0x03, 0x7f, 0xab,
+ 0x01, 0xec, 0x0e, 0xdc, 0xe4, 0xd0, 0x98, 0x85, 0xcc, 0x90, 0x0a, 0x16, 0x61, 0xc1, 0x1b, 0x2c,
+ 0x26, 0x88, 0xe1, 0x10, 0x2f, 0x26, 0x68, 0x03, 0x5d, 0x87, 0x5c, 0xdf, 0x26, 0xc3, 0x83, 0xd3,
+ 0x21, 0x53, 0x32, 0xa5, 0x67, 0x69, 0x73, 0x73, 0x88, 0xee, 0x40, 0xb1, 0x73, 0x6c, 0x5a, 0x36,
+ 0x39, 0xe0, 0xb2, 0x32, 0xac, 0xb7, 0xc0, 0x69, 0xcc, 0x6e, 0x85, 0x85, 0x0b, 0xce, 0xaa, 0x2c,
+ 0x5b, 0x94, 0x84, 0x4d, 0x28, 0x30, 0x53, 0xc7, 0x72, 0xdf, 0x23, 0xdf, 0xc6, 0x14, 0x1b, 0x16,
+ 0x75, 0xa1, 0xb0, 0x1a, 0x7f, 0x06, 0x68, 0x8d, 0x74, 0x89, 0x4b, 0xc6, 0xc9, 0x1e, 0x8a, 0x4f,
+ 0xd2, 0xaa, 0x4f, 0xf0, 0x3f, 0x6b, 0x30, 0x13, 0x10, 0x3f, 0xd6, 0xb4, 0xaa, 0x90, 0x6b, 0x33,
+ 0x61, 0xdc, 0x82, 0xb4, 0x2e, 0x9b, 0xe8, 0x09, 0x4c, 0x09, 0x03, 0x9c, 0x6a, 0x3a, 0x61, 0xd3,
+ 0xe4, 0xb8, 0x4d, 0x0e, 0xfe, 0x36, 0x05, 0x79, 0x31, 0xd1, 0x9d, 0x3e, 0x5a, 0x81, 0x92, 0xcd,
+ 0x1b, 0x07, 0x6c, 0x3e, 0xc2, 0xa2, 0x5a, 0x72, 0x12, 0x5a, 0x9f, 0xd0, 0x8b, 0x62, 0x08, 0x23,
+ 0xa3, 0x3f, 0x81, 0x82, 0x14, 0xd1, 0x1f, 0xb8, 0xc2, 0xe5, 0xd5, 0xa0, 0x00, 0x7f, 0xff, 0xad,
+ 0x4f, 0xe8, 0x20, 0xd8, 0x77, 0x07, 0x2e, 0x6a, 0xc2, 0xac, 0x1c, 0xcc, 0x67, 0x23, 0xcc, 0x48,
+ 0x33, 0x29, 0x0b, 0x41, 0x29, 0xd1, 0xa5, 0x5a, 0x9f, 0xd0, 0x91, 0x18, 0xaf, 0x74, 0xaa, 0x26,
+ 0xb9, 0x67, 0x3c, 0x79, 0x47, 0x4c, 0x6a, 0x9e, 0x99, 0x51, 0x93, 0x9a, 0x67, 0xe6, 0xf3, 0x3c,
+ 0xe4, 0x44, 0x0b, 0xff, 0x57, 0x0a, 0x40, 0xae, 0xc6, 0x4e, 0x1f, 0xad, 0x41, 0xd9, 0x16, 0xad,
+ 0x80, 0xb7, 0x6e, 0xc4, 0x7a, 0x4b, 0x2c, 0xe2, 0x84, 0x5e, 0x92, 0x83, 0xb8, 0x71, 0xef, 0x43,
+ 0xd1, 0x93, 0xe2, 0x3b, 0x6c, 0x2e, 0xc6, 0x61, 0x9e, 0x84, 0x82, 0x1c, 0x40, 0x5d, 0xf6, 0x09,
+ 0x5c, 0xf5, 0xc6, 0xc7, 0xf8, 0xec, 0xce, 0x08, 0x9f, 0x79, 0x02, 0x67, 0xa4, 0x04, 0xd5, 0x6b,
+ 0xaa, 0x61, 0xbe, 0xdb, 0xe6, 0x62, 0xdc, 0x16, 0x35, 0x8c, 0x3a, 0x0e, 0x68, 0xbd, 0xe4, 0x4d,
+ 0xfc, 0xeb, 0x34, 0xe4, 0x56, 0xad, 0x5e, 0xdf, 0xb0, 0xe9, 0x6a, 0x64, 0x6d, 0xe2, 0x0c, 0xba,
+ 0x2e, 0x73, 0x57, 0x79, 0xf9, 0x6e, 0x50, 0xa2, 0x60, 0x93, 0xff, 0xea, 0x8c, 0x55, 0x17, 0x43,
+ 0xe8, 0x60, 0x51, 0x1e, 0x53, 0x97, 0x18, 0x2c, 0x8a, 0xa3, 0x18, 0x22, 0x03, 0x39, 0xed, 0x07,
+ 0x72, 0x0d, 0x72, 0x43, 0x62, 0xfb, 0x25, 0x7d, 0x7d, 0x42, 0x97, 0x04, 0xf4, 0x08, 0xa6, 0xc3,
+ 0xe5, 0x25, 0x23, 0x78, 0xca, 0xad, 0x60, 0x35, 0xba, 0x0b, 0xc5, 0x40, 0x8d, 0xcb, 0x0a, 0xbe,
+ 0x42, 0x4f, 0x29, 0x71, 0xd7, 0x64, 0x5e, 0xa5, 0xf5, 0xb8, 0xb8, 0x3e, 0x21, 0x33, 0xeb, 0x35,
+ 0x99, 0x59, 0xa7, 0xc4, 0x28, 0x91, 0x5b, 0x03, 0x49, 0xe6, 0x83, 0x60, 0x92, 0xc1, 0x1f, 0x40,
+ 0x29, 0xe0, 0x20, 0x5a, 0x77, 0x1a, 0x1f, 0xef, 0xaf, 0x6c, 0xf1, 0x22, 0xf5, 0x82, 0xd5, 0x25,
+ 0xbd, 0xa2, 0xd1, 0x5a, 0xb7, 0xd5, 0xd8, 0xdb, 0xab, 0xa4, 0x50, 0x09, 0xf2, 0xdb, 0x3b, 0xcd,
+ 0x03, 0xce, 0x95, 0xc6, 0x2f, 0x3c, 0x09, 0xa2, 0xc8, 0x29, 0xb5, 0x6d, 0x42, 0xa9, 0x6d, 0x9a,
+ 0xac, 0x6d, 0x29, 0xbf, 0xb6, 0xb1, 0x32, 0xb7, 0xd5, 0x58, 0xd9, 0x6b, 0x54, 0x26, 0x9f, 0x97,
+ 0xa1, 0xc8, 0xfd, 0x7b, 0x30, 0x30, 0x69, 0xa9, 0xfd, 0x77, 0x0d, 0xc0, 0x8f, 0x26, 0x54, 0x87,
+ 0x5c, 0x8b, 0xeb, 0xa9, 0x6a, 0x2c, 0x19, 0x5d, 0x8d, 0x5d, 0x32, 0x5d, 0x72, 0xa1, 0x77, 0x20,
+ 0xe7, 0x0c, 0x5a, 0x2d, 0xe2, 0xc8, 0x92, 0x77, 0x3d, 0x9c, 0x0f, 0x45, 0xb6, 0xd2, 0x25, 0x1f,
+ 0x1d, 0x72, 0x64, 0x74, 0xba, 0x03, 0x56, 0x00, 0x47, 0x0f, 0x11, 0x7c, 0xf8, 0xdf, 0x34, 0x28,
+ 0x28, 0x9b, 0xf7, 0x07, 0x26, 0xe1, 0x9b, 0x90, 0x67, 0x36, 0x90, 0xb6, 0x48, 0xc3, 0x53, 0xba,
+ 0x4f, 0x40, 0x7f, 0x0c, 0x79, 0x19, 0x01, 0x32, 0x13, 0x57, 0xe3, 0xc5, 0xee, 0xf4, 0x75, 0x9f,
+ 0x15, 0x6f, 0xc2, 0x15, 0xe6, 0x95, 0x16, 0x3d, 0x5c, 0x4b, 0x3f, 0xaa, 0xc7, 0x4f, 0x2d, 0x74,
+ 0xfc, 0xac, 0xc1, 0x54, 0xff, 0xe4, 0xdc, 0xe9, 0xb4, 0x8c, 0xae, 0xb0, 0xc2, 0x6b, 0xe3, 0x8f,
+ 0x00, 0xa9, 0xc2, 0xc6, 0x99, 0x2e, 0x2e, 0x41, 0x61, 0xdd, 0x70, 0x4e, 0x84, 0x49, 0xf8, 0x09,
+ 0x94, 0x68, 0x73, 0xf3, 0xd5, 0x25, 0x6c, 0x64, 0x97, 0x03, 0xc9, 0x3d, 0x96, 0xcf, 0x11, 0x4c,
+ 0x9e, 0x18, 0xce, 0x09, 0x9b, 0x68, 0x49, 0x67, 0xdf, 0xe8, 0x11, 0x54, 0x5a, 0x7c, 0x92, 0x07,
+ 0xa1, 0x2b, 0xc3, 0xb4, 0xa0, 0x7b, 0x27, 0xc1, 0x4f, 0xa1, 0xc8, 0xe7, 0xf0, 0x63, 0x1b, 0x81,
+ 0xaf, 0xc0, 0xf4, 0x9e, 0x69, 0xf4, 0x9d, 0x13, 0x4b, 0x56, 0x37, 0x3a, 0xe9, 0x8a, 0x4f, 0x1b,
+ 0x4b, 0xe3, 0x43, 0x98, 0xb6, 0x49, 0xcf, 0xe8, 0x98, 0x1d, 0xf3, 0xf8, 0xe0, 0xf0, 0xdc, 0x25,
+ 0x8e, 0xb8, 0x30, 0x95, 0x3d, 0xf2, 0x73, 0x4a, 0xa5, 0xa6, 0x1d, 0x76, 0xad, 0x43, 0x91, 0xe6,
+ 0xd8, 0x37, 0xfe, 0x4f, 0x0d, 0x8a, 0x9f, 0x18, 0x6e, 0x4b, 0x2e, 0x1d, 0xda, 0x80, 0xb2, 0x97,
+ 0xdc, 0x18, 0x45, 0xd8, 0x12, 0x2a, 0xb1, 0x6c, 0x8c, 0x3c, 0x4a, 0xcb, 0xea, 0x58, 0x6a, 0xa9,
+ 0x04, 0x26, 0xca, 0x30, 0x5b, 0xa4, 0xeb, 0x89, 0x4a, 0x25, 0x8b, 0x62, 0x8c, 0xaa, 0x28, 0x95,
+ 0xf0, 0x7c, 0xda, 0x3f, 0x7e, 0xf0, 0x5c, 0xf2, 0x75, 0x0a, 0x50, 0xd4, 0x86, 0xef, 0x7b, 0x22,
+ 0xbb, 0x0f, 0x65, 0xc7, 0x35, 0xec, 0xc8, 0xde, 0x28, 0x31, 0xaa, 0x97, 0xa0, 0x1f, 0xc2, 0x74,
+ 0xdf, 0xb6, 0x8e, 0x6d, 0xe2, 0x38, 0x07, 0xa6, 0xe5, 0x76, 0x8e, 0xce, 0xc5, 0xa1, 0xb6, 0x2c,
+ 0xc9, 0xdb, 0x8c, 0x8a, 0x1a, 0x90, 0x3b, 0xea, 0x74, 0x5d, 0x62, 0x3b, 0xd5, 0xcc, 0x42, 0x7a,
+ 0xb1, 0xbc, 0xfc, 0xe4, 0x22, 0xaf, 0x2d, 0x7d, 0xc8, 0xf8, 0x9b, 0xe7, 0x7d, 0xa2, 0xcb, 0xb1,
+ 0xea, 0x41, 0x31, 0x1b, 0x38, 0x28, 0xde, 0x07, 0xf0, 0xf9, 0x69, 0xaa, 0xdd, 0xde, 0xd9, 0xdd,
+ 0x6f, 0x56, 0x26, 0x50, 0x11, 0xa6, 0xb6, 0x77, 0xd6, 0x1a, 0x5b, 0x0d, 0x9a, 0x97, 0x71, 0x5d,
+ 0xfa, 0x46, 0xf5, 0x21, 0x9a, 0x83, 0xa9, 0xd7, 0x94, 0x2a, 0xef, 0xdb, 0x69, 0x3d, 0xc7, 0xda,
+ 0x1b, 0x6d, 0xfc, 0x4f, 0x29, 0x28, 0x89, 0x5d, 0x30, 0xd6, 0x56, 0x54, 0x55, 0xa4, 0x02, 0x2a,
+ 0xe8, 0xa9, 0x94, 0xef, 0x8e, 0xb6, 0x38, 0xfc, 0xca, 0x26, 0xcd, 0x0d, 0x7c, 0xb1, 0x49, 0x5b,
+ 0xb8, 0xd5, 0x6b, 0xc7, 0x86, 0x6f, 0x26, 0x36, 0x7c, 0xd1, 0x5d, 0x28, 0x79, 0xbb, 0xcd, 0x70,
+ 0x44, 0xad, 0xcd, 0xeb, 0x45, 0xb9, 0x91, 0x28, 0x0d, 0xdd, 0x87, 0x2c, 0x19, 0x12, 0xd3, 0x75,
+ 0xaa, 0x05, 0x96, 0x75, 0x4b, 0xf2, 0xfc, 0xdb, 0xa0, 0x54, 0x5d, 0x74, 0xe2, 0x3f, 0x82, 0x2b,
+ 0xec, 0x9e, 0xf1, 0xc2, 0x36, 0x4c, 0xf5, 0x42, 0xd4, 0x6c, 0x6e, 0x09, 0xd7, 0xd1, 0x4f, 0x54,
+ 0x86, 0xd4, 0xc6, 0x9a, 0x98, 0x68, 0x6a, 0x63, 0x0d, 0x7f, 0xa1, 0x01, 0x52, 0xc7, 0x8d, 0xe5,
+ 0xcb, 0x90, 0x70, 0xa9, 0x3e, 0xed, 0xab, 0x9f, 0x85, 0x0c, 0xb1, 0x6d, 0xcb, 0x66, 0x5e, 0xcb,
+ 0xeb, 0xbc, 0x81, 0xef, 0x09, 0x1b, 0x74, 0x32, 0xb4, 0x4e, 0xbd, 0xc0, 0xe0, 0xd2, 0x34, 0xcf,
+ 0xd4, 0x4d, 0x98, 0x09, 0x70, 0x8d, 0x95, 0xfd, 0x1f, 0xc2, 0x55, 0x26, 0x6c, 0x93, 0x90, 0xfe,
+ 0x4a, 0xb7, 0x33, 0x4c, 0xd4, 0xda, 0x87, 0x6b, 0x61, 0xc6, 0x9f, 0xd6, 0x47, 0xf8, 0x4f, 0x85,
+ 0xc6, 0x66, 0xa7, 0x47, 0x9a, 0xd6, 0x56, 0xb2, 0x6d, 0x34, 0x3b, 0x9e, 0x92, 0x73, 0x47, 0x94,
+ 0x49, 0xf6, 0x8d, 0xff, 0x43, 0x83, 0xeb, 0x91, 0xe1, 0x3f, 0xf1, 0xaa, 0xce, 0x03, 0x1c, 0xd3,
+ 0xed, 0x43, 0xda, 0xb4, 0x83, 0xdf, 0xd0, 0x15, 0x8a, 0x67, 0x27, 0x4d, 0x30, 0x45, 0x61, 0xe7,
+ 0xac, 0x58, 0x73, 0xf6, 0xc7, 0x91, 0x35, 0xe6, 0x16, 0x14, 0x18, 0x61, 0xcf, 0x35, 0xdc, 0x81,
+ 0x13, 0x59, 0x8c, 0xbf, 0x11, 0x5b, 0x40, 0x0e, 0x1a, 0x6b, 0x5e, 0xef, 0x40, 0x96, 0x1d, 0x4e,
+ 0xe5, 0xd1, 0x2c, 0x74, 0x1b, 0x50, 0xec, 0xd0, 0x05, 0x23, 0x3e, 0x81, 0xec, 0x4b, 0x86, 0xe8,
+ 0x29, 0x96, 0x4d, 0xca, 0xa5, 0x30, 0x8d, 0x1e, 0xc7, 0x19, 0xf2, 0x3a, 0xfb, 0x66, 0x27, 0x19,
+ 0x42, 0xec, 0x7d, 0x7d, 0x8b, 0x9f, 0x98, 0xf2, 0xba, 0xd7, 0xa6, 0x2e, 0x6b, 0x75, 0x3b, 0xc4,
+ 0x74, 0x59, 0xef, 0x24, 0xeb, 0x55, 0x28, 0x78, 0x09, 0x2a, 0x5c, 0xd3, 0x4a, 0xbb, 0xad, 0x9c,
+ 0x48, 0x3c, 0x79, 0x5a, 0x50, 0x1e, 0xfe, 0x46, 0x83, 0x2b, 0xca, 0x80, 0xb1, 0x1c, 0xf3, 0x14,
+ 0xb2, 0x1c, 0xb7, 0x14, 0xc5, 0x6f, 0x36, 0x38, 0x8a, 0xab, 0xd1, 0x05, 0x0f, 0x5a, 0x82, 0x1c,
+ 0xff, 0x92, 0xc7, 0xc2, 0x78, 0x76, 0xc9, 0x84, 0xef, 0xc3, 0x8c, 0x20, 0x91, 0x9e, 0x15, 0xb7,
+ 0xb7, 0x99, 0x43, 0xf1, 0xe7, 0x30, 0x1b, 0x64, 0x1b, 0x6b, 0x4a, 0x8a, 0x91, 0xa9, 0xcb, 0x18,
+ 0xb9, 0x22, 0x8d, 0xdc, 0xef, 0xb7, 0x95, 0x5a, 0x1d, 0x5e, 0x75, 0x75, 0x45, 0x52, 0xa1, 0x15,
+ 0xf1, 0x26, 0x20, 0x45, 0xfc, 0xac, 0x13, 0x98, 0x91, 0xdb, 0x61, 0xab, 0xe3, 0x78, 0x27, 0xb8,
+ 0x37, 0x80, 0x54, 0xe2, 0xcf, 0x6d, 0xd0, 0x1a, 0x39, 0xb2, 0x8d, 0xe3, 0x1e, 0xf1, 0xea, 0x13,
+ 0x3d, 0xcf, 0xab, 0xc4, 0xb1, 0x32, 0x7a, 0x1d, 0xae, 0xbc, 0xb4, 0x86, 0x34, 0x35, 0x50, 0xaa,
+ 0x1f, 0x32, 0xfc, 0x3e, 0xe7, 0x2d, 0x9b, 0xd7, 0xa6, 0xca, 0xd5, 0x01, 0x63, 0x29, 0xff, 0x5f,
+ 0x0d, 0x8a, 0x2b, 0x5d, 0xc3, 0xee, 0x49, 0xc5, 0xef, 0x43, 0x96, 0xdf, 0x52, 0x04, 0x30, 0xf0,
+ 0x20, 0x28, 0x46, 0xe5, 0xe5, 0x8d, 0x15, 0x7e, 0xa7, 0x11, 0xa3, 0xa8, 0xe1, 0xe2, 0xed, 0x60,
+ 0x2d, 0xf4, 0x96, 0xb0, 0x86, 0xde, 0x82, 0x8c, 0x41, 0x87, 0xb0, 0x14, 0x5c, 0x0e, 0xdf, 0x0f,
+ 0x99, 0x34, 0x76, 0x38, 0xe3, 0x5c, 0xf8, 0x3d, 0x28, 0x28, 0x1a, 0xe8, 0x0d, 0xf8, 0x45, 0x43,
+ 0x1c, 0xc0, 0x56, 0x56, 0x9b, 0x1b, 0xaf, 0xf8, 0xc5, 0xb8, 0x0c, 0xb0, 0xd6, 0xf0, 0xda, 0x29,
+ 0xfc, 0xa9, 0x18, 0x25, 0xf2, 0x9d, 0x6a, 0x8f, 0x96, 0x64, 0x4f, 0xea, 0x52, 0xf6, 0x9c, 0x41,
+ 0x49, 0x4c, 0x7f, 0xdc, 0xf4, 0xcd, 0xe4, 0x25, 0xa4, 0x6f, 0xc5, 0x78, 0x5d, 0x30, 0xe2, 0x69,
+ 0x28, 0x89, 0x84, 0x2e, 0xf6, 0xdf, 0xff, 0x68, 0x50, 0x96, 0x94, 0x71, 0x01, 0x4c, 0x89, 0xbd,
+ 0xf0, 0x0a, 0xe0, 0x21, 0x2f, 0xd7, 0x20, 0xdb, 0x3e, 0xdc, 0xeb, 0xbc, 0x91, 0x60, 0xb3, 0x68,
+ 0x51, 0x7a, 0x97, 0xeb, 0xe1, 0x2f, 0x3e, 0xa2, 0x45, 0x6f, 0xe1, 0xb6, 0x71, 0xe4, 0x6e, 0x98,
+ 0x6d, 0x72, 0xc6, 0xce, 0x8d, 0x93, 0xba, 0x4f, 0x60, 0x97, 0x52, 0xf1, 0x32, 0xc4, 0x0e, 0x8b,
+ 0xea, 0x4b, 0xd1, 0x0c, 0x5c, 0x59, 0x19, 0xb8, 0x27, 0x0d, 0xd3, 0x38, 0xec, 0xca, 0x8c, 0x45,
+ 0xcb, 0x2c, 0x25, 0xae, 0x75, 0x1c, 0x95, 0xda, 0x80, 0x19, 0x4a, 0x25, 0xa6, 0xdb, 0x69, 0x29,
+ 0xe9, 0x4d, 0x16, 0x31, 0x2d, 0x54, 0xc4, 0x0c, 0xc7, 0x79, 0x6d, 0xd9, 0x6d, 0x31, 0x35, 0xaf,
+ 0x8d, 0xd7, 0xb8, 0xf0, 0x7d, 0x27, 0x50, 0xa6, 0xbe, 0xaf, 0x94, 0x45, 0x5f, 0xca, 0x0b, 0xe2,
+ 0x8e, 0x90, 0x82, 0x9f, 0xc0, 0x55, 0xc9, 0x29, 0xc0, 0xbd, 0x11, 0xcc, 0x3b, 0x70, 0x4b, 0x32,
+ 0xaf, 0x9e, 0xd0, 0xdb, 0xd3, 0xae, 0x50, 0xf8, 0x43, 0xed, 0x7c, 0x0e, 0x55, 0xcf, 0x4e, 0x76,
+ 0x58, 0xb6, 0xba, 0xaa, 0x01, 0x03, 0x47, 0xec, 0x99, 0xbc, 0xce, 0xbe, 0x29, 0xcd, 0xb6, 0xba,
+ 0xde, 0x91, 0x80, 0x7e, 0xe3, 0x55, 0x98, 0x93, 0x32, 0xc4, 0x31, 0x36, 0x28, 0x24, 0x62, 0x50,
+ 0x9c, 0x10, 0xe1, 0x30, 0x3a, 0x74, 0xb4, 0xdb, 0x55, 0xce, 0xa0, 0x6b, 0x99, 0x4c, 0x4d, 0x91,
+ 0x79, 0x95, 0xef, 0x08, 0x6a, 0x98, 0x5a, 0x31, 0x04, 0x99, 0x0a, 0x50, 0xc9, 0x62, 0x21, 0x28,
+ 0x39, 0xb2, 0x10, 0x11, 0xd1, 0x9f, 0xc1, 0xbc, 0x67, 0x04, 0xf5, 0xdb, 0x2e, 0xb1, 0x7b, 0x1d,
+ 0xc7, 0x51, 0xe0, 0xa0, 0xb8, 0x89, 0x3f, 0x80, 0xc9, 0x3e, 0x11, 0x39, 0xa5, 0xb0, 0x8c, 0x96,
+ 0xf8, 0xfb, 0xed, 0x92, 0x32, 0x98, 0xf5, 0xe3, 0x36, 0xdc, 0x96, 0xd2, 0xb9, 0x47, 0x63, 0xc5,
+ 0x87, 0x8d, 0x92, 0xb7, 0x6e, 0xee, 0xd6, 0xe8, 0xad, 0x3b, 0xcd, 0xd7, 0xde, 0x83, 0x28, 0x3f,
+ 0xe2, 0x8e, 0x94, 0xb1, 0x35, 0x56, 0xad, 0xd8, 0xe4, 0x3e, 0xf5, 0x42, 0x72, 0x2c, 0x61, 0x87,
+ 0x30, 0x1b, 0x8c, 0xe4, 0xb1, 0xd2, 0xd8, 0x2c, 0x64, 0x5c, 0xeb, 0x94, 0xc8, 0x24, 0xc6, 0x1b,
+ 0xd2, 0x60, 0x2f, 0xcc, 0xc7, 0x32, 0xd8, 0xf0, 0x85, 0xb1, 0x2d, 0x39, 0xae, 0xbd, 0x74, 0x35,
+ 0xe5, 0xe1, 0x8b, 0x37, 0xf0, 0x36, 0x5c, 0x0b, 0xa7, 0x89, 0xb1, 0x4c, 0x7e, 0xc5, 0x37, 0x70,
+ 0x5c, 0x26, 0x19, 0x4b, 0xee, 0xc7, 0x7e, 0x32, 0x50, 0x12, 0xca, 0x58, 0x22, 0x75, 0xa8, 0xc5,
+ 0xe5, 0x97, 0x1f, 0x63, 0xbf, 0x7a, 0xe9, 0x66, 0x2c, 0x61, 0x8e, 0x2f, 0x6c, 0xfc, 0xe5, 0xf7,
+ 0x73, 0x44, 0x7a, 0x64, 0x8e, 0x10, 0x41, 0xe2, 0x67, 0xb1, 0x9f, 0x60, 0xd3, 0x09, 0x1d, 0x7e,
+ 0x02, 0x1d, 0x57, 0x07, 0xad, 0x21, 0x9e, 0x0e, 0xd6, 0x90, 0x1b, 0x5b, 0x4d, 0xbb, 0x63, 0x2d,
+ 0xc6, 0x27, 0x7e, 0xee, 0x8c, 0x64, 0xe6, 0xb1, 0x04, 0x7f, 0x0a, 0x0b, 0xc9, 0x49, 0x79, 0x1c,
+ 0xc9, 0x8f, 0xeb, 0x90, 0xf7, 0x0e, 0x94, 0xca, 0x6f, 0x1f, 0x0a, 0x90, 0xdb, 0xde, 0xd9, 0xdb,
+ 0x5d, 0x59, 0x6d, 0xf0, 0x1f, 0x3f, 0xac, 0xee, 0xe8, 0xfa, 0xfe, 0x6e, 0xb3, 0x92, 0x5a, 0xfe,
+ 0x6d, 0x1a, 0x52, 0x9b, 0xaf, 0xd0, 0x9f, 0x43, 0x86, 0xbf, 0x04, 0x8e, 0x78, 0xfe, 0xad, 0x8d,
+ 0x7a, 0xec, 0xc4, 0x37, 0xbe, 0xf8, 0xff, 0x5f, 0x7d, 0x95, 0xba, 0x8a, 0x2b, 0xf5, 0xe1, 0xbb,
+ 0x87, 0xc4, 0x35, 0xea, 0xa7, 0xc3, 0x3a, 0xab, 0x0f, 0xcf, 0xb4, 0xc7, 0x68, 0x1f, 0xd2, 0xbb,
+ 0x03, 0x17, 0x25, 0x3e, 0x0d, 0xd7, 0x92, 0xdf, 0x40, 0xf1, 0x1c, 0x13, 0x3c, 0x83, 0xcb, 0x8a,
+ 0xe0, 0xfe, 0xc0, 0xa5, 0x62, 0x07, 0x50, 0x50, 0x5f, 0x31, 0x2f, 0x7c, 0x33, 0xae, 0x5d, 0xfc,
+ 0x42, 0x8a, 0xef, 0x30, 0x75, 0x37, 0xf0, 0x35, 0x45, 0x1d, 0x7f, 0x6b, 0x55, 0x67, 0xd3, 0x3c,
+ 0x33, 0x51, 0xe2, 0xab, 0x72, 0x2d, 0xf9, 0xe1, 0x34, 0x76, 0x36, 0xee, 0x99, 0x49, 0xc5, 0x9a,
+ 0xe2, 0xdd, 0xb4, 0xe5, 0xa2, 0xdb, 0x31, 0xef, 0x66, 0xea, 0x0b, 0x51, 0x6d, 0x21, 0x99, 0x41,
+ 0x28, 0x5a, 0x60, 0x8a, 0x6a, 0xf8, 0xaa, 0xa2, 0xa8, 0xe5, 0xb1, 0x3d, 0xd3, 0x1e, 0x2f, 0x1f,
+ 0x43, 0x86, 0x21, 0xc4, 0xe8, 0x2f, 0xe4, 0x47, 0x2d, 0x06, 0xdb, 0x4e, 0x58, 0xfc, 0x00, 0xb6,
+ 0x8c, 0xab, 0x4c, 0x19, 0xc2, 0x25, 0xa9, 0x8c, 0x61, 0xc4, 0xcf, 0xb4, 0xc7, 0x8b, 0xda, 0xdb,
+ 0xda, 0xf2, 0x6f, 0x26, 0x21, 0xc3, 0xe0, 0x22, 0x64, 0x01, 0xf8, 0x68, 0x6a, 0x78, 0x96, 0x11,
+ 0x7c, 0x36, 0x3c, 0xcb, 0x28, 0x10, 0x8b, 0xe7, 0x99, 0xe2, 0x2a, 0x9e, 0x91, 0x8a, 0x19, 0x12,
+ 0x55, 0x67, 0xe0, 0x1a, 0xf5, 0xe9, 0x50, 0x00, 0x66, 0x3c, 0xcc, 0x50, 0x9c, 0xc0, 0x00, 0xaa,
+ 0x1a, 0xde, 0x21, 0x31, 0x88, 0x2a, 0xc6, 0x4c, 0xe7, 0x4d, 0x7c, 0x5d, 0xf1, 0x2c, 0x57, 0x6b,
+ 0x33, 0x46, 0xaa, 0xf7, 0xef, 0x34, 0x28, 0x07, 0x71, 0x51, 0x74, 0x37, 0x46, 0x72, 0x18, 0x5e,
+ 0xad, 0xdd, 0x1b, 0xcd, 0x94, 0x64, 0x01, 0x57, 0x7f, 0x4a, 0x48, 0xdf, 0xa0, 0x8c, 0xc2, 0xf1,
+ 0xe8, 0x1f, 0x34, 0x98, 0x0e, 0x81, 0x9d, 0x28, 0x4e, 0x43, 0x04, 0x4a, 0xad, 0xdd, 0xbf, 0x80,
+ 0x4b, 0x18, 0xf2, 0x80, 0x19, 0xb2, 0x80, 0x6f, 0x44, 0x5c, 0xe1, 0x76, 0x7a, 0xc4, 0xb5, 0x84,
+ 0x31, 0xde, 0x32, 0x70, 0x60, 0x32, 0x76, 0x19, 0x02, 0x40, 0x67, 0xec, 0x32, 0x04, 0x51, 0xcd,
+ 0x11, 0xcb, 0xc0, 0xd1, 0x48, 0xba, 0xc5, 0x7f, 0x97, 0x86, 0xdc, 0x2a, 0xff, 0x05, 0x22, 0x72,
+ 0x20, 0xef, 0x21, 0x80, 0x68, 0x3e, 0x0e, 0x8d, 0xf1, 0x6f, 0x0b, 0xb5, 0xdb, 0x89, 0xfd, 0x42,
+ 0xfb, 0x7d, 0xa6, 0xfd, 0x36, 0xae, 0x49, 0xed, 0xe2, 0x87, 0x8e, 0x75, 0x7e, 0xed, 0xaf, 0x1b,
+ 0xed, 0x36, 0x9d, 0xf8, 0xdf, 0x42, 0x51, 0x85, 0xe9, 0xd0, 0x9d, 0x58, 0x14, 0x48, 0x45, 0xfa,
+ 0x6a, 0x78, 0x14, 0x8b, 0xd0, 0xbe, 0xc8, 0xb4, 0x63, 0x7c, 0x2b, 0x41, 0xbb, 0xcd, 0xd8, 0x03,
+ 0x06, 0x70, 0x98, 0x2d, 0xde, 0x80, 0x00, 0x8a, 0x17, 0x6f, 0x40, 0x10, 0xa5, 0xbb, 0xd0, 0x80,
+ 0x01, 0x63, 0xa7, 0x06, 0xbc, 0x06, 0xf0, 0x41, 0x35, 0x14, 0xeb, 0x57, 0xe5, 0xea, 0x14, 0x0e,
+ 0xf9, 0x28, 0x1e, 0x17, 0xdd, 0x73, 0x21, 0xd5, 0xdd, 0x8e, 0x43, 0x43, 0x7f, 0xf9, 0x9b, 0x2c,
+ 0x14, 0x5e, 0x1a, 0x1d, 0xd3, 0x25, 0xa6, 0x61, 0xb6, 0x08, 0x3a, 0x82, 0x0c, 0x2b, 0x8d, 0xe1,
+ 0x2c, 0xa7, 0x62, 0x4d, 0xe1, 0x2c, 0x17, 0x00, 0x62, 0xf0, 0x3d, 0xa6, 0x79, 0x1e, 0xcf, 0x49,
+ 0xcd, 0x3d, 0x5f, 0x7c, 0x9d, 0x61, 0x28, 0x74, 0xc2, 0x7f, 0x09, 0x59, 0x01, 0xcf, 0x87, 0x84,
+ 0x05, 0xb0, 0x95, 0xda, 0xcd, 0xf8, 0xce, 0xa4, 0xed, 0xa5, 0xaa, 0x72, 0x18, 0x2f, 0xd5, 0xf5,
+ 0x06, 0xc0, 0x07, 0x08, 0xc3, 0xce, 0x8d, 0xe0, 0x89, 0xb5, 0x85, 0x64, 0x06, 0xa1, 0xf7, 0x11,
+ 0xd3, 0x7b, 0x17, 0xcf, 0xc7, 0xe9, 0x6d, 0x7b, 0xfc, 0x54, 0xf7, 0x21, 0x4c, 0xae, 0x1b, 0xce,
+ 0x09, 0x0a, 0x15, 0x3b, 0xe5, 0x47, 0x03, 0xb5, 0x5a, 0x5c, 0x97, 0xd0, 0x74, 0x97, 0x69, 0xba,
+ 0x85, 0xab, 0x71, 0x9a, 0x4e, 0x0c, 0x87, 0x56, 0x0f, 0x74, 0x02, 0x59, 0xfe, 0x3b, 0x82, 0xb0,
+ 0x2f, 0x03, 0xbf, 0x45, 0x08, 0xfb, 0x32, 0xf8, 0xd3, 0x83, 0xcb, 0x69, 0x72, 0x61, 0x4a, 0x3e,
+ 0xde, 0xa3, 0x5b, 0xa1, 0xa5, 0x09, 0x3e, 0xf4, 0xd7, 0xe6, 0x93, 0xba, 0x85, 0xbe, 0x87, 0x4c,
+ 0xdf, 0x1d, 0x7c, 0x33, 0x76, 0xed, 0x04, 0xf7, 0x33, 0xed, 0xf1, 0xdb, 0x1a, 0x2d, 0x13, 0xe0,
+ 0x83, 0xac, 0x91, 0xe8, 0x08, 0xe3, 0xb5, 0x91, 0xe8, 0x88, 0xe0, 0xb3, 0x78, 0x99, 0x29, 0x7f,
+ 0x8a, 0x1f, 0xc6, 0x29, 0x77, 0x6d, 0xc3, 0x74, 0x8e, 0x88, 0xfd, 0x16, 0x07, 0xd3, 0x9c, 0x93,
+ 0x4e, 0x9f, 0x46, 0xca, 0xef, 0xa7, 0x61, 0x92, 0x9e, 0x47, 0x69, 0x79, 0xf6, 0xaf, 0xf1, 0x61,
+ 0x6b, 0x22, 0xe0, 0x59, 0xd8, 0x9a, 0x28, 0x02, 0x10, 0x2d, 0xcf, 0xec, 0xb7, 0xe6, 0x84, 0x31,
+ 0x51, 0xaf, 0x3b, 0x50, 0x50, 0xee, 0xfa, 0x28, 0x46, 0x60, 0x10, 0x99, 0x0b, 0xd7, 0x85, 0x18,
+ 0xa0, 0x00, 0xdf, 0x66, 0x3a, 0xe7, 0xf0, 0x6c, 0x40, 0x67, 0x9b, 0x73, 0x51, 0xa5, 0x7f, 0x0d,
+ 0x45, 0x15, 0x13, 0x40, 0x31, 0x32, 0x43, 0xc8, 0x5f, 0x38, 0x25, 0xc6, 0x41, 0x0a, 0xd1, 0xec,
+ 0xe0, 0xfd, 0xae, 0x5e, 0xb2, 0x52, 0xe5, 0x7d, 0xc8, 0x09, 0xa0, 0x20, 0x6e, 0xb6, 0x41, 0xa8,
+ 0x30, 0x6e, 0xb6, 0x21, 0x94, 0x21, 0x7a, 0xcc, 0x63, 0x5a, 0xe9, 0x7d, 0x48, 0x96, 0x20, 0xa1,
+ 0xf1, 0x05, 0x71, 0x93, 0x34, 0xfa, 0xd8, 0x57, 0x92, 0x46, 0xe5, 0x2e, 0x3a, 0x4a, 0xe3, 0x31,
+ 0x71, 0x45, 0x2c, 0xc9, 0x7b, 0x1e, 0x4a, 0x10, 0xa8, 0xa6, 0x7c, 0x3c, 0x8a, 0x25, 0xe9, 0x54,
+ 0xee, 0x2b, 0x15, 0xf9, 0x1e, 0x7d, 0x0e, 0xe0, 0x43, 0x1a, 0xe1, 0xd3, 0x56, 0x2c, 0x2e, 0x1a,
+ 0x3e, 0x6d, 0xc5, 0xa3, 0x22, 0xd1, 0xfc, 0xe1, 0xeb, 0xe6, 0x17, 0x03, 0xaa, 0xfd, 0x5f, 0x34,
+ 0x40, 0x51, 0x04, 0x04, 0x3d, 0x89, 0xd7, 0x10, 0x8b, 0xb8, 0xd6, 0x9e, 0x5e, 0x8e, 0x39, 0xa9,
+ 0x44, 0xf8, 0x66, 0xb5, 0xd8, 0x88, 0xfe, 0x6b, 0x6a, 0xd8, 0x97, 0x1a, 0x94, 0x02, 0x10, 0x0a,
+ 0x7a, 0x90, 0xb0, 0xc6, 0x21, 0xd0, 0xb6, 0xf6, 0xf0, 0x42, 0xbe, 0xa4, 0x93, 0x98, 0xb2, 0x23,
+ 0xe4, 0x41, 0xfc, 0x1f, 0x35, 0x28, 0x07, 0x61, 0x17, 0x94, 0x20, 0x3f, 0x02, 0xfc, 0xd6, 0x16,
+ 0x2f, 0x66, 0xbc, 0x78, 0xa9, 0xfc, 0xb3, 0x79, 0x1f, 0x72, 0x02, 0xac, 0x89, 0x0b, 0x88, 0x20,
+ 0x6c, 0x1c, 0x17, 0x10, 0x21, 0xa4, 0x27, 0x21, 0x20, 0x6c, 0xab, 0x4b, 0x94, 0x10, 0x14, 0x88,
+ 0x4e, 0x92, 0xc6, 0xd1, 0x21, 0x18, 0x82, 0x83, 0x46, 0x69, 0xf4, 0x43, 0x50, 0xc2, 0x39, 0x28,
+ 0x41, 0xe0, 0x05, 0x21, 0x18, 0x46, 0x83, 0x12, 0x42, 0x90, 0x29, 0x55, 0x42, 0xd0, 0x07, 0x5f,
+ 0xe2, 0x42, 0x30, 0x82, 0x88, 0xc7, 0x85, 0x60, 0x14, 0xbf, 0x49, 0x58, 0x57, 0xa6, 0x3b, 0x10,
+ 0x82, 0x33, 0x31, 0x58, 0x0d, 0x7a, 0x9a, 0xe0, 0xd0, 0x58, 0xb0, 0xbd, 0xf6, 0xd6, 0x25, 0xb9,
+ 0x47, 0xee, 0x7d, 0xbe, 0x14, 0x72, 0xef, 0x7f, 0xad, 0xc1, 0x6c, 0x1c, 0xd6, 0x83, 0x12, 0x74,
+ 0x25, 0x00, 0xf5, 0xb5, 0xa5, 0xcb, 0xb2, 0x5f, 0xec, 0x35, 0x2f, 0x1a, 0x9e, 0x57, 0xfe, 0xfb,
+ 0xbb, 0x79, 0xed, 0xff, 0xbe, 0x9b, 0xd7, 0x7e, 0xf1, 0xdd, 0xbc, 0xf6, 0xaf, 0xbf, 0x9c, 0x9f,
+ 0x38, 0xcc, 0xb2, 0xff, 0xe1, 0xf5, 0xee, 0x1f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x74, 0x55, 0x61,
+ 0xe6, 0x68, 0x36, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/membership/cluster.go b/vendor/github.com/coreos/etcd/etcdserver/membership/cluster.go
new file mode 100644
index 00000000..4f0b1572
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/membership/cluster.go
@@ -0,0 +1,512 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package membership
+
+import (
+ "bytes"
+ "context"
+ "crypto/sha1"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "path"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/pkg/netutil"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/store"
+ "github.com/coreos/etcd/version"
+
+ "github.com/coreos/go-semver/semver"
+)
+
+// RaftCluster is a list of Members that belong to the same raft cluster
+type RaftCluster struct {
+ id types.ID
+ token string
+
+ store store.Store
+ be backend.Backend
+
+ sync.Mutex // guards the fields below
+ version *semver.Version
+ members map[types.ID]*Member
+ // removed contains the ids of removed members in the cluster.
+ // removed id cannot be reused.
+ removed map[types.ID]bool
+}
+
+func NewClusterFromURLsMap(token string, urlsmap types.URLsMap) (*RaftCluster, error) {
+ c := NewCluster(token)
+ for name, urls := range urlsmap {
+ m := NewMember(name, urls, token, nil)
+ if _, ok := c.members[m.ID]; ok {
+ return nil, fmt.Errorf("member exists with identical ID %v", m)
+ }
+ if uint64(m.ID) == raft.None {
+ return nil, fmt.Errorf("cannot use %x as member id", raft.None)
+ }
+ c.members[m.ID] = m
+ }
+ c.genID()
+ return c, nil
+}
+
+func NewClusterFromMembers(token string, id types.ID, membs []*Member) *RaftCluster {
+ c := NewCluster(token)
+ c.id = id
+ for _, m := range membs {
+ c.members[m.ID] = m
+ }
+ return c
+}
+
+func NewCluster(token string) *RaftCluster {
+ return &RaftCluster{
+ token: token,
+ members: make(map[types.ID]*Member),
+ removed: make(map[types.ID]bool),
+ }
+}
+
+func (c *RaftCluster) ID() types.ID { return c.id }
+
+func (c *RaftCluster) Members() []*Member {
+ c.Lock()
+ defer c.Unlock()
+ var ms MembersByID
+ for _, m := range c.members {
+ ms = append(ms, m.Clone())
+ }
+ sort.Sort(ms)
+ return []*Member(ms)
+}
+
+func (c *RaftCluster) Member(id types.ID) *Member {
+ c.Lock()
+ defer c.Unlock()
+ return c.members[id].Clone()
+}
+
+// MemberByName returns a Member with the given name if exists.
+// If more than one member has the given name, it will panic.
+func (c *RaftCluster) MemberByName(name string) *Member {
+ c.Lock()
+ defer c.Unlock()
+ var memb *Member
+ for _, m := range c.members {
+ if m.Name == name {
+ if memb != nil {
+ plog.Panicf("two members with the given name %q exist", name)
+ }
+ memb = m
+ }
+ }
+ return memb.Clone()
+}
+
+func (c *RaftCluster) MemberIDs() []types.ID {
+ c.Lock()
+ defer c.Unlock()
+ var ids []types.ID
+ for _, m := range c.members {
+ ids = append(ids, m.ID)
+ }
+ sort.Sort(types.IDSlice(ids))
+ return ids
+}
+
+func (c *RaftCluster) IsIDRemoved(id types.ID) bool {
+ c.Lock()
+ defer c.Unlock()
+ return c.removed[id]
+}
+
+// PeerURLs returns a list of all peer addresses.
+// The returned list is sorted in ascending lexicographical order.
+func (c *RaftCluster) PeerURLs() []string {
+ c.Lock()
+ defer c.Unlock()
+ urls := make([]string, 0)
+ for _, p := range c.members {
+ urls = append(urls, p.PeerURLs...)
+ }
+ sort.Strings(urls)
+ return urls
+}
+
+// ClientURLs returns a list of all client addresses.
+// The returned list is sorted in ascending lexicographical order.
+func (c *RaftCluster) ClientURLs() []string {
+ c.Lock()
+ defer c.Unlock()
+ urls := make([]string, 0)
+ for _, p := range c.members {
+ urls = append(urls, p.ClientURLs...)
+ }
+ sort.Strings(urls)
+ return urls
+}
+
+func (c *RaftCluster) String() string {
+ c.Lock()
+ defer c.Unlock()
+ b := &bytes.Buffer{}
+ fmt.Fprintf(b, "{ClusterID:%s ", c.id)
+ var ms []string
+ for _, m := range c.members {
+ ms = append(ms, fmt.Sprintf("%+v", m))
+ }
+ fmt.Fprintf(b, "Members:[%s] ", strings.Join(ms, " "))
+ var ids []string
+ for id := range c.removed {
+ ids = append(ids, id.String())
+ }
+ fmt.Fprintf(b, "RemovedMemberIDs:[%s]}", strings.Join(ids, " "))
+ return b.String()
+}
+
+func (c *RaftCluster) genID() {
+ mIDs := c.MemberIDs()
+ b := make([]byte, 8*len(mIDs))
+ for i, id := range mIDs {
+ binary.BigEndian.PutUint64(b[8*i:], uint64(id))
+ }
+ hash := sha1.Sum(b)
+ c.id = types.ID(binary.BigEndian.Uint64(hash[:8]))
+}
+
+func (c *RaftCluster) SetID(id types.ID) { c.id = id }
+
+func (c *RaftCluster) SetStore(st store.Store) { c.store = st }
+
+func (c *RaftCluster) SetBackend(be backend.Backend) {
+ c.be = be
+ mustCreateBackendBuckets(c.be)
+}
+
+func (c *RaftCluster) Recover(onSet func(*semver.Version)) {
+ c.Lock()
+ defer c.Unlock()
+
+ c.members, c.removed = membersFromStore(c.store)
+ c.version = clusterVersionFromStore(c.store)
+ mustDetectDowngrade(c.version)
+ onSet(c.version)
+
+ for _, m := range c.members {
+ plog.Infof("added member %s %v to cluster %s from store", m.ID, m.PeerURLs, c.id)
+ }
+ if c.version != nil {
+ plog.Infof("set the cluster version to %v from store", version.Cluster(c.version.String()))
+ }
+}
+
+// ValidateConfigurationChange takes a proposed ConfChange and
+// ensures that it is still valid.
+func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error {
+ members, removed := membersFromStore(c.store)
+ id := types.ID(cc.NodeID)
+ if removed[id] {
+ return ErrIDRemoved
+ }
+ switch cc.Type {
+ case raftpb.ConfChangeAddNode:
+ if members[id] != nil {
+ return ErrIDExists
+ }
+ urls := make(map[string]bool)
+ for _, m := range members {
+ for _, u := range m.PeerURLs {
+ urls[u] = true
+ }
+ }
+ m := new(Member)
+ if err := json.Unmarshal(cc.Context, m); err != nil {
+ plog.Panicf("unmarshal member should never fail: %v", err)
+ }
+ for _, u := range m.PeerURLs {
+ if urls[u] {
+ return ErrPeerURLexists
+ }
+ }
+ case raftpb.ConfChangeRemoveNode:
+ if members[id] == nil {
+ return ErrIDNotFound
+ }
+ case raftpb.ConfChangeUpdateNode:
+ if members[id] == nil {
+ return ErrIDNotFound
+ }
+ urls := make(map[string]bool)
+ for _, m := range members {
+ if m.ID == id {
+ continue
+ }
+ for _, u := range m.PeerURLs {
+ urls[u] = true
+ }
+ }
+ m := new(Member)
+ if err := json.Unmarshal(cc.Context, m); err != nil {
+ plog.Panicf("unmarshal member should never fail: %v", err)
+ }
+ for _, u := range m.PeerURLs {
+ if urls[u] {
+ return ErrPeerURLexists
+ }
+ }
+ default:
+ plog.Panicf("ConfChange type should be either AddNode, RemoveNode or UpdateNode")
+ }
+ return nil
+}
+
+// AddMember adds a new Member into the cluster, and saves the given member's
+// raftAttributes into the store. The given member should have empty attributes.
+// A Member with a matching id must not exist.
+func (c *RaftCluster) AddMember(m *Member) {
+ c.Lock()
+ defer c.Unlock()
+ if c.store != nil {
+ mustSaveMemberToStore(c.store, m)
+ }
+ if c.be != nil {
+ mustSaveMemberToBackend(c.be, m)
+ }
+
+ c.members[m.ID] = m
+
+ plog.Infof("added member %s %v to cluster %s", m.ID, m.PeerURLs, c.id)
+}
+
+// RemoveMember removes a member from the store.
+// The given id MUST exist, or the function panics.
+func (c *RaftCluster) RemoveMember(id types.ID) {
+ c.Lock()
+ defer c.Unlock()
+ if c.store != nil {
+ mustDeleteMemberFromStore(c.store, id)
+ }
+ if c.be != nil {
+ mustDeleteMemberFromBackend(c.be, id)
+ }
+
+ delete(c.members, id)
+ c.removed[id] = true
+
+ plog.Infof("removed member %s from cluster %s", id, c.id)
+}
+
+func (c *RaftCluster) UpdateAttributes(id types.ID, attr Attributes) {
+ c.Lock()
+ defer c.Unlock()
+ if m, ok := c.members[id]; ok {
+ m.Attributes = attr
+ if c.store != nil {
+ mustUpdateMemberAttrInStore(c.store, m)
+ }
+ if c.be != nil {
+ mustSaveMemberToBackend(c.be, m)
+ }
+ return
+ }
+ _, ok := c.removed[id]
+ if !ok {
+ plog.Panicf("error updating attributes of unknown member %s", id)
+ }
+ plog.Warningf("skipped updating attributes of removed member %s", id)
+}
+
+func (c *RaftCluster) UpdateRaftAttributes(id types.ID, raftAttr RaftAttributes) {
+ c.Lock()
+ defer c.Unlock()
+
+ c.members[id].RaftAttributes = raftAttr
+ if c.store != nil {
+ mustUpdateMemberInStore(c.store, c.members[id])
+ }
+ if c.be != nil {
+ mustSaveMemberToBackend(c.be, c.members[id])
+ }
+
+ plog.Noticef("updated member %s %v in cluster %s", id, raftAttr.PeerURLs, c.id)
+}
+
+func (c *RaftCluster) Version() *semver.Version {
+ c.Lock()
+ defer c.Unlock()
+ if c.version == nil {
+ return nil
+ }
+ return semver.Must(semver.NewVersion(c.version.String()))
+}
+
+func (c *RaftCluster) SetVersion(ver *semver.Version, onSet func(*semver.Version)) {
+ c.Lock()
+ defer c.Unlock()
+ if c.version != nil {
+ plog.Noticef("updated the cluster version from %v to %v", version.Cluster(c.version.String()), version.Cluster(ver.String()))
+ } else {
+ plog.Noticef("set the initial cluster version to %v", version.Cluster(ver.String()))
+ }
+ c.version = ver
+ mustDetectDowngrade(c.version)
+ if c.store != nil {
+ mustSaveClusterVersionToStore(c.store, ver)
+ }
+ if c.be != nil {
+ mustSaveClusterVersionToBackend(c.be, ver)
+ }
+ onSet(ver)
+}
+
+func (c *RaftCluster) IsReadyToAddNewMember() bool {
+ nmembers := 1
+ nstarted := 0
+
+ for _, member := range c.members {
+ if member.IsStarted() {
+ nstarted++
+ }
+ nmembers++
+ }
+
+ if nstarted == 1 && nmembers == 2 {
+ // a case of adding a new node to 1-member cluster for restoring cluster data
+ // https://github.com/coreos/etcd/blob/master/Documentation/v2/admin_guide.md#restoring-the-cluster
+
+ plog.Debugf("The number of started member is 1. This cluster can accept add member request.")
+ return true
+ }
+
+ nquorum := nmembers/2 + 1
+ if nstarted < nquorum {
+ plog.Warningf("Reject add member request: the number of started member (%d) will be less than the quorum number of the cluster (%d)", nstarted, nquorum)
+ return false
+ }
+
+ return true
+}
+
+func (c *RaftCluster) IsReadyToRemoveMember(id uint64) bool {
+ nmembers := 0
+ nstarted := 0
+
+ for _, member := range c.members {
+ if uint64(member.ID) == id {
+ continue
+ }
+
+ if member.IsStarted() {
+ nstarted++
+ }
+ nmembers++
+ }
+
+ nquorum := nmembers/2 + 1
+ if nstarted < nquorum {
+ plog.Warningf("Reject remove member request: the number of started member (%d) will be less than the quorum number of the cluster (%d)", nstarted, nquorum)
+ return false
+ }
+
+ return true
+}
+
+func membersFromStore(st store.Store) (map[types.ID]*Member, map[types.ID]bool) {
+ members := make(map[types.ID]*Member)
+ removed := make(map[types.ID]bool)
+ e, err := st.Get(StoreMembersPrefix, true, true)
+ if err != nil {
+ if isKeyNotFound(err) {
+ return members, removed
+ }
+ plog.Panicf("get storeMembers should never fail: %v", err)
+ }
+ for _, n := range e.Node.Nodes {
+ var m *Member
+ m, err = nodeToMember(n)
+ if err != nil {
+ plog.Panicf("nodeToMember should never fail: %v", err)
+ }
+ members[m.ID] = m
+ }
+
+ e, err = st.Get(storeRemovedMembersPrefix, true, true)
+ if err != nil {
+ if isKeyNotFound(err) {
+ return members, removed
+ }
+ plog.Panicf("get storeRemovedMembers should never fail: %v", err)
+ }
+ for _, n := range e.Node.Nodes {
+ removed[MustParseMemberIDFromKey(n.Key)] = true
+ }
+ return members, removed
+}
+
+func clusterVersionFromStore(st store.Store) *semver.Version {
+ e, err := st.Get(path.Join(storePrefix, "version"), false, false)
+ if err != nil {
+ if isKeyNotFound(err) {
+ return nil
+ }
+ plog.Panicf("unexpected error (%v) when getting cluster version from store", err)
+ }
+ return semver.Must(semver.NewVersion(*e.Node.Value))
+}
+
+// ValidateClusterAndAssignIDs validates the local cluster by matching the PeerURLs
+// with the existing cluster. If the validation succeeds, it assigns the IDs
+// from the existing cluster to the local cluster.
+// If the validation fails, an error will be returned.
+func ValidateClusterAndAssignIDs(local *RaftCluster, existing *RaftCluster) error {
+ ems := existing.Members()
+ lms := local.Members()
+ if len(ems) != len(lms) {
+ return fmt.Errorf("member count is unequal")
+ }
+ sort.Sort(MembersByPeerURLs(ems))
+ sort.Sort(MembersByPeerURLs(lms))
+
+ ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
+ defer cancel()
+ for i := range ems {
+ if ok, err := netutil.URLStringsEqual(ctx, ems[i].PeerURLs, lms[i].PeerURLs); !ok {
+ return fmt.Errorf("unmatched member while checking PeerURLs (%v)", err)
+ }
+ lms[i].ID = ems[i].ID
+ }
+ local.members = make(map[types.ID]*Member)
+ for _, m := range lms {
+ local.members[m.ID] = m
+ }
+ return nil
+}
+
+func mustDetectDowngrade(cv *semver.Version) {
+ lv := semver.Must(semver.NewVersion(version.Version))
+ // only keep major.minor version for comparison against cluster version
+ lv = &semver.Version{Major: lv.Major, Minor: lv.Minor}
+ if cv != nil && lv.LessThan(*cv) {
+ plog.Fatalf("cluster cannot be downgraded (current version: %s is lower than determined cluster version: %s).", version.Version, version.Cluster(cv.String()))
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/membership/doc.go b/vendor/github.com/coreos/etcd/etcdserver/membership/doc.go
new file mode 100644
index 00000000..b07fb2d9
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/membership/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package membership describes individual etcd members and clusters of members.
+package membership
diff --git a/vendor/github.com/coreos/etcd/etcdserver/membership/errors.go b/vendor/github.com/coreos/etcd/etcdserver/membership/errors.go
new file mode 100644
index 00000000..e4d36af2
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/membership/errors.go
@@ -0,0 +1,33 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package membership
+
+import (
+ "errors"
+
+ etcdErr "github.com/coreos/etcd/error"
+)
+
+var (
+ ErrIDRemoved = errors.New("membership: ID removed")
+ ErrIDExists = errors.New("membership: ID exists")
+ ErrIDNotFound = errors.New("membership: ID not found")
+ ErrPeerURLexists = errors.New("membership: peerURL exists")
+)
+
+func isKeyNotFound(err error) bool {
+ e, ok := err.(*etcdErr.Error)
+ return ok && e.ErrorCode == etcdErr.EcodeKeyNotFound
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/membership/member.go b/vendor/github.com/coreos/etcd/etcdserver/membership/member.go
new file mode 100644
index 00000000..6de74d26
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/membership/member.go
@@ -0,0 +1,124 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package membership
+
+import (
+ "crypto/sha1"
+ "encoding/binary"
+ "fmt"
+ "math/rand"
+ "sort"
+ "time"
+
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "etcdserver/membership")
+)
+
+// RaftAttributes represents the raft related attributes of an etcd member.
+type RaftAttributes struct {
+ // PeerURLs is the list of peers in the raft cluster.
+ // TODO(philips): ensure these are URLs
+ PeerURLs []string `json:"peerURLs"`
+}
+
+// Attributes represents all the non-raft related attributes of an etcd member.
+type Attributes struct {
+ Name string `json:"name,omitempty"`
+ ClientURLs []string `json:"clientURLs,omitempty"`
+}
+
+type Member struct {
+ ID types.ID `json:"id"`
+ RaftAttributes
+ Attributes
+}
+
+// NewMember creates a Member without an ID and generates one based on the
+// cluster name, peer URLs, and time. This is used for bootstrapping/adding new member.
+func NewMember(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member {
+ m := &Member{
+ RaftAttributes: RaftAttributes{PeerURLs: peerURLs.StringSlice()},
+ Attributes: Attributes{Name: name},
+ }
+
+ var b []byte
+ sort.Strings(m.PeerURLs)
+ for _, p := range m.PeerURLs {
+ b = append(b, []byte(p)...)
+ }
+
+ b = append(b, []byte(clusterName)...)
+ if now != nil {
+ b = append(b, []byte(fmt.Sprintf("%d", now.Unix()))...)
+ }
+
+ hash := sha1.Sum(b)
+ m.ID = types.ID(binary.BigEndian.Uint64(hash[:8]))
+ return m
+}
+
+// PickPeerURL chooses a random address from a given Member's PeerURLs.
+// It will panic if there is no PeerURLs available in Member.
+func (m *Member) PickPeerURL() string {
+ if len(m.PeerURLs) == 0 {
+ plog.Panicf("member should always have some peer url")
+ }
+ return m.PeerURLs[rand.Intn(len(m.PeerURLs))]
+}
+
+func (m *Member) Clone() *Member {
+ if m == nil {
+ return nil
+ }
+ mm := &Member{
+ ID: m.ID,
+ Attributes: Attributes{
+ Name: m.Name,
+ },
+ }
+ if m.PeerURLs != nil {
+ mm.PeerURLs = make([]string, len(m.PeerURLs))
+ copy(mm.PeerURLs, m.PeerURLs)
+ }
+ if m.ClientURLs != nil {
+ mm.ClientURLs = make([]string, len(m.ClientURLs))
+ copy(mm.ClientURLs, m.ClientURLs)
+ }
+ return mm
+}
+
+func (m *Member) IsStarted() bool {
+ return len(m.Name) != 0
+}
+
+// MembersByID implements sort by ID interface
+type MembersByID []*Member
+
+func (ms MembersByID) Len() int { return len(ms) }
+func (ms MembersByID) Less(i, j int) bool { return ms[i].ID < ms[j].ID }
+func (ms MembersByID) Swap(i, j int) { ms[i], ms[j] = ms[j], ms[i] }
+
+// MembersByPeerURLs implements sort by peer urls interface
+type MembersByPeerURLs []*Member
+
+func (ms MembersByPeerURLs) Len() int { return len(ms) }
+func (ms MembersByPeerURLs) Less(i, j int) bool {
+ return ms[i].PeerURLs[0] < ms[j].PeerURLs[0]
+}
+func (ms MembersByPeerURLs) Swap(i, j int) { ms[i], ms[j] = ms[j], ms[i] }
diff --git a/vendor/github.com/coreos/etcd/etcdserver/membership/store.go b/vendor/github.com/coreos/etcd/etcdserver/membership/store.go
new file mode 100644
index 00000000..d3f8f247
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/membership/store.go
@@ -0,0 +1,193 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package membership
+
+import (
+ "encoding/json"
+ "fmt"
+ "path"
+
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/store"
+
+ "github.com/coreos/go-semver/semver"
+)
+
+const (
+ attributesSuffix = "attributes"
+ raftAttributesSuffix = "raftAttributes"
+
+ // the prefix for stroing membership related information in store provided by store pkg.
+ storePrefix = "/0"
+)
+
+var (
+ membersBucketName = []byte("members")
+ membersRemovedBucketName = []byte("members_removed")
+ clusterBucketName = []byte("cluster")
+
+ StoreMembersPrefix = path.Join(storePrefix, "members")
+ storeRemovedMembersPrefix = path.Join(storePrefix, "removed_members")
+)
+
+func mustSaveMemberToBackend(be backend.Backend, m *Member) {
+ mkey := backendMemberKey(m.ID)
+ mvalue, err := json.Marshal(m)
+ if err != nil {
+ plog.Panicf("marshal raftAttributes should never fail: %v", err)
+ }
+
+ tx := be.BatchTx()
+ tx.Lock()
+ tx.UnsafePut(membersBucketName, mkey, mvalue)
+ tx.Unlock()
+}
+
+func mustDeleteMemberFromBackend(be backend.Backend, id types.ID) {
+ mkey := backendMemberKey(id)
+
+ tx := be.BatchTx()
+ tx.Lock()
+ tx.UnsafeDelete(membersBucketName, mkey)
+ tx.UnsafePut(membersRemovedBucketName, mkey, []byte("removed"))
+ tx.Unlock()
+}
+
+func mustSaveClusterVersionToBackend(be backend.Backend, ver *semver.Version) {
+ ckey := backendClusterVersionKey()
+
+ tx := be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+ tx.UnsafePut(clusterBucketName, ckey, []byte(ver.String()))
+}
+
+func mustSaveMemberToStore(s store.Store, m *Member) {
+ b, err := json.Marshal(m.RaftAttributes)
+ if err != nil {
+ plog.Panicf("marshal raftAttributes should never fail: %v", err)
+ }
+ p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix)
+ if _, err := s.Create(p, false, string(b), false, store.TTLOptionSet{ExpireTime: store.Permanent}); err != nil {
+ plog.Panicf("create raftAttributes should never fail: %v", err)
+ }
+}
+
+func mustDeleteMemberFromStore(s store.Store, id types.ID) {
+ if _, err := s.Delete(MemberStoreKey(id), true, true); err != nil {
+ plog.Panicf("delete member should never fail: %v", err)
+ }
+ if _, err := s.Create(RemovedMemberStoreKey(id), false, "", false, store.TTLOptionSet{ExpireTime: store.Permanent}); err != nil {
+ plog.Panicf("create removedMember should never fail: %v", err)
+ }
+}
+
+func mustUpdateMemberInStore(s store.Store, m *Member) {
+ b, err := json.Marshal(m.RaftAttributes)
+ if err != nil {
+ plog.Panicf("marshal raftAttributes should never fail: %v", err)
+ }
+ p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix)
+ if _, err := s.Update(p, string(b), store.TTLOptionSet{ExpireTime: store.Permanent}); err != nil {
+ plog.Panicf("update raftAttributes should never fail: %v", err)
+ }
+}
+
+func mustUpdateMemberAttrInStore(s store.Store, m *Member) {
+ b, err := json.Marshal(m.Attributes)
+ if err != nil {
+ plog.Panicf("marshal raftAttributes should never fail: %v", err)
+ }
+ p := path.Join(MemberStoreKey(m.ID), attributesSuffix)
+ if _, err := s.Set(p, false, string(b), store.TTLOptionSet{ExpireTime: store.Permanent}); err != nil {
+ plog.Panicf("update raftAttributes should never fail: %v", err)
+ }
+}
+
+func mustSaveClusterVersionToStore(s store.Store, ver *semver.Version) {
+ if _, err := s.Set(StoreClusterVersionKey(), false, ver.String(), store.TTLOptionSet{ExpireTime: store.Permanent}); err != nil {
+ plog.Panicf("save cluster version should never fail: %v", err)
+ }
+}
+
+// nodeToMember builds member from a key value node.
+// the child nodes of the given node MUST be sorted by key.
+func nodeToMember(n *store.NodeExtern) (*Member, error) {
+ m := &Member{ID: MustParseMemberIDFromKey(n.Key)}
+ attrs := make(map[string][]byte)
+ raftAttrKey := path.Join(n.Key, raftAttributesSuffix)
+ attrKey := path.Join(n.Key, attributesSuffix)
+ for _, nn := range n.Nodes {
+ if nn.Key != raftAttrKey && nn.Key != attrKey {
+ return nil, fmt.Errorf("unknown key %q", nn.Key)
+ }
+ attrs[nn.Key] = []byte(*nn.Value)
+ }
+ if data := attrs[raftAttrKey]; data != nil {
+ if err := json.Unmarshal(data, &m.RaftAttributes); err != nil {
+ return nil, fmt.Errorf("unmarshal raftAttributes error: %v", err)
+ }
+ } else {
+ return nil, fmt.Errorf("raftAttributes key doesn't exist")
+ }
+ if data := attrs[attrKey]; data != nil {
+ if err := json.Unmarshal(data, &m.Attributes); err != nil {
+ return m, fmt.Errorf("unmarshal attributes error: %v", err)
+ }
+ }
+ return m, nil
+}
+
+func backendMemberKey(id types.ID) []byte {
+ return []byte(id.String())
+}
+
+func backendClusterVersionKey() []byte {
+ return []byte("clusterVersion")
+}
+
+func mustCreateBackendBuckets(be backend.Backend) {
+ tx := be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+ tx.UnsafeCreateBucket(membersBucketName)
+ tx.UnsafeCreateBucket(membersRemovedBucketName)
+ tx.UnsafeCreateBucket(clusterBucketName)
+}
+
+func MemberStoreKey(id types.ID) string {
+ return path.Join(StoreMembersPrefix, id.String())
+}
+
+func StoreClusterVersionKey() string {
+ return path.Join(storePrefix, "version")
+}
+
+func MemberAttributesStorePath(id types.ID) string {
+ return path.Join(MemberStoreKey(id), attributesSuffix)
+}
+
+func MustParseMemberIDFromKey(key string) types.ID {
+ id, err := types.IDFromString(path.Base(key))
+ if err != nil {
+ plog.Panicf("unexpected parse member id error: %v", err)
+ }
+ return id
+}
+
+func RemovedMemberStoreKey(id types.ID) string {
+ return path.Join(storeRemovedMembersPrefix, id.String())
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/metrics.go b/vendor/github.com/coreos/etcd/etcdserver/metrics.go
new file mode 100644
index 00000000..f6f2d7b6
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/metrics.go
@@ -0,0 +1,162 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ goruntime "runtime"
+ "time"
+
+ "github.com/coreos/etcd/pkg/runtime"
+ "github.com/coreos/etcd/version"
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+ hasLeader = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "has_leader",
+ Help: "Whether or not a leader exists. 1 is existence, 0 is not.",
+ })
+ isLeader = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "is_leader",
+ Help: "Whether or not this member is a leader. 1 if is, 0 otherwise.",
+ })
+ leaderChanges = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "leader_changes_seen_total",
+ Help: "The number of leader changes seen.",
+ })
+ heartbeatSendFailures = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "heartbeat_send_failures_total",
+ Help: "The total number of leader heartbeat send failures (likely overloaded from slow disk).",
+ })
+ slowApplies = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "slow_apply_total",
+ Help: "The total number of slow apply requests (likely overloaded from slow disk).",
+ })
+ proposalsCommitted = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "proposals_committed_total",
+ Help: "The total number of consensus proposals committed.",
+ })
+ proposalsApplied = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "proposals_applied_total",
+ Help: "The total number of consensus proposals applied.",
+ })
+ proposalsPending = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "proposals_pending",
+ Help: "The current number of pending proposals to commit.",
+ })
+ proposalsFailed = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "proposals_failed_total",
+ Help: "The total number of failed proposals seen.",
+ })
+ leaseExpired = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "server",
+ Name: "lease_expired_total",
+ Help: "The total number of expired leases.",
+ })
+ slowReadIndex = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "slow_read_indexes_total",
+ Help: "The total number of pending read indexes not in sync with leader's or timed out read index requests.",
+ })
+ quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "quota_backend_bytes",
+ Help: "Current backend storage quota size in bytes.",
+ })
+ currentVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "version",
+ Help: "Which version is running. 1 for 'server_version' label with current version.",
+ },
+ []string{"server_version"})
+ currentGoVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "server",
+ Name: "go_version",
+ Help: "Which Go version server is running with. 1 for 'server_go_version' label with current version.",
+ },
+ []string{"server_go_version"})
+)
+
+func init() {
+ prometheus.MustRegister(hasLeader)
+ prometheus.MustRegister(isLeader)
+ prometheus.MustRegister(leaderChanges)
+ prometheus.MustRegister(heartbeatSendFailures)
+ prometheus.MustRegister(slowApplies)
+ prometheus.MustRegister(proposalsCommitted)
+ prometheus.MustRegister(proposalsApplied)
+ prometheus.MustRegister(proposalsPending)
+ prometheus.MustRegister(proposalsFailed)
+ prometheus.MustRegister(leaseExpired)
+ prometheus.MustRegister(slowReadIndex)
+ prometheus.MustRegister(quotaBackendBytes)
+ prometheus.MustRegister(currentVersion)
+ prometheus.MustRegister(currentGoVersion)
+
+ currentVersion.With(prometheus.Labels{
+ "server_version": version.Version,
+ }).Set(1)
+ currentGoVersion.With(prometheus.Labels{
+ "server_go_version": goruntime.Version(),
+ }).Set(1)
+}
+
+func monitorFileDescriptor(done <-chan struct{}) {
+ ticker := time.NewTicker(5 * time.Second)
+ defer ticker.Stop()
+ for {
+ used, err := runtime.FDUsage()
+ if err != nil {
+ plog.Errorf("cannot monitor file descriptor usage (%v)", err)
+ return
+ }
+ limit, err := runtime.FDLimit()
+ if err != nil {
+ plog.Errorf("cannot monitor file descriptor usage (%v)", err)
+ return
+ }
+ if used >= limit/5*4 {
+ plog.Warningf("80%% of the file descriptor limit is used [used = %d, limit = %d]", used, limit)
+ }
+ select {
+ case <-ticker.C:
+ case <-done:
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/quota.go b/vendor/github.com/coreos/etcd/etcdserver/quota.go
new file mode 100644
index 00000000..882eb76f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/quota.go
@@ -0,0 +1,124 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+const (
+ // DefaultQuotaBytes is the number of bytes the backend Size may
+ // consume before exceeding the space quota.
+ DefaultQuotaBytes = int64(2 * 1024 * 1024 * 1024) // 2GB
+ // MaxQuotaBytes is the maximum number of bytes suggested for a backend
+ // quota. A larger quota may lead to degraded performance.
+ MaxQuotaBytes = int64(8 * 1024 * 1024 * 1024) // 8GB
+)
+
+// Quota represents an arbitrary quota against arbitrary requests. Each request
+// costs some charge; if there is not enough remaining charge, then there are
+// too few resources available within the quota to apply the request.
+type Quota interface {
+ // Available judges whether the given request fits within the quota.
+ Available(req interface{}) bool
+ // Cost computes the charge against the quota for a given request.
+ Cost(req interface{}) int
+ // Remaining is the amount of charge left for the quota.
+ Remaining() int64
+}
+
+type passthroughQuota struct{}
+
+func (*passthroughQuota) Available(interface{}) bool { return true }
+func (*passthroughQuota) Cost(interface{}) int { return 0 }
+func (*passthroughQuota) Remaining() int64 { return 1 }
+
+type backendQuota struct {
+ s *EtcdServer
+ maxBackendBytes int64
+}
+
+const (
+ // leaseOverhead is an estimate for the cost of storing a lease
+ leaseOverhead = 64
+ // kvOverhead is an estimate for the cost of storing a key's metadata
+ kvOverhead = 256
+)
+
+func NewBackendQuota(s *EtcdServer) Quota {
+ quotaBackendBytes.Set(float64(s.Cfg.QuotaBackendBytes))
+
+ if s.Cfg.QuotaBackendBytes < 0 {
+ // disable quotas if negative
+ plog.Warningf("disabling backend quota")
+ return &passthroughQuota{}
+ }
+
+ if s.Cfg.QuotaBackendBytes == 0 {
+ // use default size if no quota size given
+ quotaBackendBytes.Set(float64(DefaultQuotaBytes))
+ return &backendQuota{s, DefaultQuotaBytes}
+ }
+
+ if s.Cfg.QuotaBackendBytes > MaxQuotaBytes {
+ plog.Warningf("backend quota %v exceeds maximum recommended quota %v", s.Cfg.QuotaBackendBytes, MaxQuotaBytes)
+ }
+ return &backendQuota{s, s.Cfg.QuotaBackendBytes}
+}
+
+func (b *backendQuota) Available(v interface{}) bool {
+ // TODO: maybe optimize backend.Size()
+ return b.s.Backend().Size()+int64(b.Cost(v)) < b.maxBackendBytes
+}
+
+func (b *backendQuota) Cost(v interface{}) int {
+ switch r := v.(type) {
+ case *pb.PutRequest:
+ return costPut(r)
+ case *pb.TxnRequest:
+ return costTxn(r)
+ case *pb.LeaseGrantRequest:
+ return leaseOverhead
+ default:
+ panic("unexpected cost")
+ }
+}
+
+func costPut(r *pb.PutRequest) int { return kvOverhead + len(r.Key) + len(r.Value) }
+
+func costTxnReq(u *pb.RequestOp) int {
+ r := u.GetRequestPut()
+ if r == nil {
+ return 0
+ }
+ return costPut(r)
+}
+
+func costTxn(r *pb.TxnRequest) int {
+ sizeSuccess := 0
+ for _, u := range r.Success {
+ sizeSuccess += costTxnReq(u)
+ }
+ sizeFailure := 0
+ for _, u := range r.Failure {
+ sizeFailure += costTxnReq(u)
+ }
+ if sizeFailure > sizeSuccess {
+ return sizeFailure
+ }
+ return sizeSuccess
+}
+
+func (b *backendQuota) Remaining() int64 {
+ return b.maxBackendBytes - b.s.Backend().Size()
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/raft.go b/vendor/github.com/coreos/etcd/etcdserver/raft.go
new file mode 100644
index 00000000..1080633b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/raft.go
@@ -0,0 +1,608 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "encoding/json"
+ "expvar"
+ "sort"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/etcdserver/membership"
+ "github.com/coreos/etcd/pkg/contention"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/rafthttp"
+ "github.com/coreos/etcd/wal"
+ "github.com/coreos/etcd/wal/walpb"
+ "github.com/coreos/pkg/capnslog"
+)
+
+const (
+ // Number of entries for slow follower to catch-up after compacting
+ // the raft storage entries.
+ // We expect the follower has a millisecond level latency with the leader.
+ // The max throughput is around 10K. Keep a 5K entries is enough for helping
+ // follower to catch up.
+ numberOfCatchUpEntries = 5000
+
+ // The max throughput of etcd will not exceed 100MB/s (100K * 1KB value).
+ // Assuming the RTT is around 10ms, 1MB max size is large enough.
+ maxSizePerMsg = 1 * 1024 * 1024
+ // Never overflow the rafthttp buffer, which is 4096.
+ // TODO: a better const?
+ maxInflightMsgs = 4096 / 8
+)
+
+var (
+ // protects raftStatus
+ raftStatusMu sync.Mutex
+ // indirection for expvar func interface
+ // expvar panics when publishing duplicate name
+ // expvar does not support remove a registered name
+ // so only register a func that calls raftStatus
+ // and change raftStatus as we need.
+ raftStatus func() raft.Status
+)
+
+func init() {
+ raft.SetLogger(capnslog.NewPackageLogger("github.com/coreos/etcd", "raft"))
+ expvar.Publish("raft.status", expvar.Func(func() interface{} {
+ raftStatusMu.Lock()
+ defer raftStatusMu.Unlock()
+ return raftStatus()
+ }))
+}
+
+type RaftTimer interface {
+ Index() uint64
+ Term() uint64
+}
+
+// apply contains entries, snapshot to be applied. Once
+// an apply is consumed, the entries will be persisted to
+// to raft storage concurrently; the application must read
+// raftDone before assuming the raft messages are stable.
+type apply struct {
+ entries []raftpb.Entry
+ snapshot raftpb.Snapshot
+ // notifyc synchronizes etcd server applies with the raft node
+ notifyc chan struct{}
+}
+
+type raftNode struct {
+ // Cache of the latest raft index and raft term the server has seen.
+ // These three unit64 fields must be the first elements to keep 64-bit
+ // alignment for atomic access to the fields.
+ index uint64
+ term uint64
+ lead uint64
+
+ tickMu *sync.Mutex
+ raftNodeConfig
+
+ // a chan to send/receive snapshot
+ msgSnapC chan raftpb.Message
+
+ // a chan to send out apply
+ applyc chan apply
+
+ // a chan to send out readState
+ readStateC chan raft.ReadState
+
+ // utility
+ ticker *time.Ticker
+ // contention detectors for raft heartbeat message
+ td *contention.TimeoutDetector
+
+ stopped chan struct{}
+ done chan struct{}
+}
+
+type raftNodeConfig struct {
+ // to check if msg receiver is removed from cluster
+ isIDRemoved func(id uint64) bool
+ raft.Node
+ raftStorage *raft.MemoryStorage
+ storage Storage
+ heartbeat time.Duration // for logging
+ // transport specifies the transport to send and receive msgs to members.
+ // Sending messages MUST NOT block. It is okay to drop messages, since
+ // clients should timeout and reissue their messages.
+ // If transport is nil, server will panic.
+ transport rafthttp.Transporter
+}
+
+func newRaftNode(cfg raftNodeConfig) *raftNode {
+ r := &raftNode{
+ tickMu: new(sync.Mutex),
+ raftNodeConfig: cfg,
+ // set up contention detectors for raft heartbeat message.
+ // expect to send a heartbeat within 2 heartbeat intervals.
+ td: contention.NewTimeoutDetector(2 * cfg.heartbeat),
+ readStateC: make(chan raft.ReadState, 1),
+ msgSnapC: make(chan raftpb.Message, maxInFlightMsgSnap),
+ applyc: make(chan apply),
+ stopped: make(chan struct{}),
+ done: make(chan struct{}),
+ }
+ if r.heartbeat == 0 {
+ r.ticker = &time.Ticker{}
+ } else {
+ r.ticker = time.NewTicker(r.heartbeat)
+ }
+ return r
+}
+
+// raft.Node does not have locks in Raft package
+func (r *raftNode) tick() {
+ r.tickMu.Lock()
+ r.Tick()
+ r.tickMu.Unlock()
+}
+
+// start prepares and starts raftNode in a new goroutine. It is no longer safe
+// to modify the fields after it has been started.
+func (r *raftNode) start(rh *raftReadyHandler) {
+ internalTimeout := time.Second
+
+ go func() {
+ defer r.onStop()
+ islead := false
+
+ for {
+ select {
+ case <-r.ticker.C:
+ r.tick()
+ case rd := <-r.Ready():
+ if rd.SoftState != nil {
+ newLeader := rd.SoftState.Lead != raft.None && atomic.LoadUint64(&r.lead) != rd.SoftState.Lead
+ if newLeader {
+ leaderChanges.Inc()
+ }
+
+ if rd.SoftState.Lead == raft.None {
+ hasLeader.Set(0)
+ } else {
+ hasLeader.Set(1)
+ }
+
+ atomic.StoreUint64(&r.lead, rd.SoftState.Lead)
+ islead = rd.RaftState == raft.StateLeader
+ if islead {
+ isLeader.Set(1)
+ } else {
+ isLeader.Set(0)
+ }
+ rh.updateLeadership(newLeader)
+ r.td.Reset()
+ }
+
+ if len(rd.ReadStates) != 0 {
+ select {
+ case r.readStateC <- rd.ReadStates[len(rd.ReadStates)-1]:
+ case <-time.After(internalTimeout):
+ plog.Warningf("timed out sending read state")
+ case <-r.stopped:
+ return
+ }
+ }
+
+ notifyc := make(chan struct{}, 1)
+ ap := apply{
+ entries: rd.CommittedEntries,
+ snapshot: rd.Snapshot,
+ notifyc: notifyc,
+ }
+
+ updateCommittedIndex(&ap, rh)
+
+ select {
+ case r.applyc <- ap:
+ case <-r.stopped:
+ return
+ }
+
+ // the leader can write to its disk in parallel with replicating to the followers and them
+ // writing to their disks.
+ // For more details, check raft thesis 10.2.1
+ if islead {
+ // gofail: var raftBeforeLeaderSend struct{}
+ r.transport.Send(r.processMessages(rd.Messages))
+ }
+
+ // gofail: var raftBeforeSave struct{}
+ if err := r.storage.Save(rd.HardState, rd.Entries); err != nil {
+ plog.Fatalf("raft save state and entries error: %v", err)
+ }
+ if !raft.IsEmptyHardState(rd.HardState) {
+ proposalsCommitted.Set(float64(rd.HardState.Commit))
+ }
+ // gofail: var raftAfterSave struct{}
+
+ if !raft.IsEmptySnap(rd.Snapshot) {
+ // gofail: var raftBeforeSaveSnap struct{}
+ if err := r.storage.SaveSnap(rd.Snapshot); err != nil {
+ plog.Fatalf("raft save snapshot error: %v", err)
+ }
+ // etcdserver now claim the snapshot has been persisted onto the disk
+ notifyc <- struct{}{}
+
+ // gofail: var raftAfterSaveSnap struct{}
+ r.raftStorage.ApplySnapshot(rd.Snapshot)
+ plog.Infof("raft applied incoming snapshot at index %d", rd.Snapshot.Metadata.Index)
+ // gofail: var raftAfterApplySnap struct{}
+ }
+
+ r.raftStorage.Append(rd.Entries)
+
+ if !islead {
+ // finish processing incoming messages before we signal raftdone chan
+ msgs := r.processMessages(rd.Messages)
+
+ // now unblocks 'applyAll' that waits on Raft log disk writes before triggering snapshots
+ notifyc <- struct{}{}
+
+ // Candidate or follower needs to wait for all pending configuration
+ // changes to be applied before sending messages.
+ // Otherwise we might incorrectly count votes (e.g. votes from removed members).
+ // Also slow machine's follower raft-layer could proceed to become the leader
+ // on its own single-node cluster, before apply-layer applies the config change.
+ // We simply wait for ALL pending entries to be applied for now.
+ // We might improve this later on if it causes unnecessary long blocking issues.
+ waitApply := false
+ for _, ent := range rd.CommittedEntries {
+ if ent.Type == raftpb.EntryConfChange {
+ waitApply = true
+ break
+ }
+ }
+ if waitApply {
+ // blocks until 'applyAll' calls 'applyWait.Trigger'
+ // to be in sync with scheduled config-change job
+ // (assume notifyc has cap of 1)
+ select {
+ case notifyc <- struct{}{}:
+ case <-r.stopped:
+ return
+ }
+ }
+
+ // gofail: var raftBeforeFollowerSend struct{}
+ r.transport.Send(msgs)
+ } else {
+ // leader already processed 'MsgSnap' and signaled
+ notifyc <- struct{}{}
+ }
+
+ r.Advance()
+ case <-r.stopped:
+ return
+ }
+ }
+ }()
+}
+
+func updateCommittedIndex(ap *apply, rh *raftReadyHandler) {
+ var ci uint64
+ if len(ap.entries) != 0 {
+ ci = ap.entries[len(ap.entries)-1].Index
+ }
+ if ap.snapshot.Metadata.Index > ci {
+ ci = ap.snapshot.Metadata.Index
+ }
+ if ci != 0 {
+ rh.updateCommittedIndex(ci)
+ }
+}
+
+func (r *raftNode) processMessages(ms []raftpb.Message) []raftpb.Message {
+ sentAppResp := false
+ for i := len(ms) - 1; i >= 0; i-- {
+ if r.isIDRemoved(ms[i].To) {
+ ms[i].To = 0
+ }
+
+ if ms[i].Type == raftpb.MsgAppResp {
+ if sentAppResp {
+ ms[i].To = 0
+ } else {
+ sentAppResp = true
+ }
+ }
+
+ if ms[i].Type == raftpb.MsgSnap {
+ // There are two separate data store: the store for v2, and the KV for v3.
+ // The msgSnap only contains the most recent snapshot of store without KV.
+ // So we need to redirect the msgSnap to etcd server main loop for merging in the
+ // current store snapshot and KV snapshot.
+ select {
+ case r.msgSnapC <- ms[i]:
+ default:
+ // drop msgSnap if the inflight chan if full.
+ }
+ ms[i].To = 0
+ }
+ if ms[i].Type == raftpb.MsgHeartbeat {
+ ok, exceed := r.td.Observe(ms[i].To)
+ if !ok {
+ // TODO: limit request rate.
+ plog.Warningf("failed to send out heartbeat on time (exceeded the %v timeout for %v)", r.heartbeat, exceed)
+ plog.Warningf("server is likely overloaded")
+ heartbeatSendFailures.Inc()
+ }
+ }
+ }
+ return ms
+}
+
+func (r *raftNode) apply() chan apply {
+ return r.applyc
+}
+
+func (r *raftNode) stop() {
+ r.stopped <- struct{}{}
+ <-r.done
+}
+
+func (r *raftNode) onStop() {
+ r.Stop()
+ r.ticker.Stop()
+ r.transport.Stop()
+ if err := r.storage.Close(); err != nil {
+ plog.Panicf("raft close storage error: %v", err)
+ }
+ close(r.done)
+}
+
+// for testing
+func (r *raftNode) pauseSending() {
+ p := r.transport.(rafthttp.Pausable)
+ p.Pause()
+}
+
+func (r *raftNode) resumeSending() {
+ p := r.transport.(rafthttp.Pausable)
+ p.Resume()
+}
+
+// advanceTicks advances ticks of Raft node.
+// This can be used for fast-forwarding election
+// ticks in multi data-center deployments, thus
+// speeding up election process.
+func (r *raftNode) advanceTicks(ticks int) {
+ for i := 0; i < ticks; i++ {
+ r.tick()
+ }
+}
+
+func startNode(cfg ServerConfig, cl *membership.RaftCluster, ids []types.ID) (id types.ID, n raft.Node, s *raft.MemoryStorage, w *wal.WAL) {
+ var err error
+ member := cl.MemberByName(cfg.Name)
+ metadata := pbutil.MustMarshal(
+ &pb.Metadata{
+ NodeID: uint64(member.ID),
+ ClusterID: uint64(cl.ID()),
+ },
+ )
+ if w, err = wal.Create(cfg.WALDir(), metadata); err != nil {
+ plog.Fatalf("create wal error: %v", err)
+ }
+ peers := make([]raft.Peer, len(ids))
+ for i, id := range ids {
+ ctx, err := json.Marshal((*cl).Member(id))
+ if err != nil {
+ plog.Panicf("marshal member should never fail: %v", err)
+ }
+ peers[i] = raft.Peer{ID: uint64(id), Context: ctx}
+ }
+ id = member.ID
+ plog.Infof("starting member %s in cluster %s", id, cl.ID())
+ s = raft.NewMemoryStorage()
+ c := &raft.Config{
+ ID: uint64(id),
+ ElectionTick: cfg.ElectionTicks,
+ HeartbeatTick: 1,
+ Storage: s,
+ MaxSizePerMsg: maxSizePerMsg,
+ MaxInflightMsgs: maxInflightMsgs,
+ CheckQuorum: true,
+ }
+
+ n = raft.StartNode(c, peers)
+ raftStatusMu.Lock()
+ raftStatus = n.Status
+ raftStatusMu.Unlock()
+ return id, n, s, w
+}
+
+func restartNode(cfg ServerConfig, snapshot *raftpb.Snapshot) (types.ID, *membership.RaftCluster, raft.Node, *raft.MemoryStorage, *wal.WAL) {
+ var walsnap walpb.Snapshot
+ if snapshot != nil {
+ walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term
+ }
+ w, id, cid, st, ents := readWAL(cfg.WALDir(), walsnap)
+
+ plog.Infof("restarting member %s in cluster %s at commit index %d", id, cid, st.Commit)
+ cl := membership.NewCluster("")
+ cl.SetID(cid)
+ s := raft.NewMemoryStorage()
+ if snapshot != nil {
+ s.ApplySnapshot(*snapshot)
+ }
+ s.SetHardState(st)
+ s.Append(ents)
+ c := &raft.Config{
+ ID: uint64(id),
+ ElectionTick: cfg.ElectionTicks,
+ HeartbeatTick: 1,
+ Storage: s,
+ MaxSizePerMsg: maxSizePerMsg,
+ MaxInflightMsgs: maxInflightMsgs,
+ CheckQuorum: true,
+ }
+
+ n := raft.RestartNode(c)
+ raftStatusMu.Lock()
+ raftStatus = n.Status
+ raftStatusMu.Unlock()
+ return id, cl, n, s, w
+}
+
+func restartAsStandaloneNode(cfg ServerConfig, snapshot *raftpb.Snapshot) (types.ID, *membership.RaftCluster, raft.Node, *raft.MemoryStorage, *wal.WAL) {
+ var walsnap walpb.Snapshot
+ if snapshot != nil {
+ walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term
+ }
+ w, id, cid, st, ents := readWAL(cfg.WALDir(), walsnap)
+
+ // discard the previously uncommitted entries
+ for i, ent := range ents {
+ if ent.Index > st.Commit {
+ plog.Infof("discarding %d uncommitted WAL entries ", len(ents)-i)
+ ents = ents[:i]
+ break
+ }
+ }
+
+ // force append the configuration change entries
+ toAppEnts := createConfigChangeEnts(getIDs(snapshot, ents), uint64(id), st.Term, st.Commit)
+ ents = append(ents, toAppEnts...)
+
+ // force commit newly appended entries
+ err := w.Save(raftpb.HardState{}, toAppEnts)
+ if err != nil {
+ plog.Fatalf("%v", err)
+ }
+ if len(ents) != 0 {
+ st.Commit = ents[len(ents)-1].Index
+ }
+
+ plog.Printf("forcing restart of member %s in cluster %s at commit index %d", id, cid, st.Commit)
+ cl := membership.NewCluster("")
+ cl.SetID(cid)
+ s := raft.NewMemoryStorage()
+ if snapshot != nil {
+ s.ApplySnapshot(*snapshot)
+ }
+ s.SetHardState(st)
+ s.Append(ents)
+ c := &raft.Config{
+ ID: uint64(id),
+ ElectionTick: cfg.ElectionTicks,
+ HeartbeatTick: 1,
+ Storage: s,
+ MaxSizePerMsg: maxSizePerMsg,
+ MaxInflightMsgs: maxInflightMsgs,
+ CheckQuorum: true,
+ }
+ n := raft.RestartNode(c)
+ raftStatus = n.Status
+ return id, cl, n, s, w
+}
+
+// getIDs returns an ordered set of IDs included in the given snapshot and
+// the entries. The given snapshot/entries can contain two kinds of
+// ID-related entry:
+// - ConfChangeAddNode, in which case the contained ID will be added into the set.
+// - ConfChangeRemoveNode, in which case the contained ID will be removed from the set.
+func getIDs(snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 {
+ ids := make(map[uint64]bool)
+ if snap != nil {
+ for _, id := range snap.Metadata.ConfState.Nodes {
+ ids[id] = true
+ }
+ }
+ for _, e := range ents {
+ if e.Type != raftpb.EntryConfChange {
+ continue
+ }
+ var cc raftpb.ConfChange
+ pbutil.MustUnmarshal(&cc, e.Data)
+ switch cc.Type {
+ case raftpb.ConfChangeAddNode:
+ ids[cc.NodeID] = true
+ case raftpb.ConfChangeRemoveNode:
+ delete(ids, cc.NodeID)
+ case raftpb.ConfChangeUpdateNode:
+ // do nothing
+ default:
+ plog.Panicf("ConfChange Type should be either ConfChangeAddNode or ConfChangeRemoveNode!")
+ }
+ }
+ sids := make(types.Uint64Slice, 0, len(ids))
+ for id := range ids {
+ sids = append(sids, id)
+ }
+ sort.Sort(sids)
+ return []uint64(sids)
+}
+
+// createConfigChangeEnts creates a series of Raft entries (i.e.
+// EntryConfChange) to remove the set of given IDs from the cluster. The ID
+// `self` is _not_ removed, even if present in the set.
+// If `self` is not inside the given ids, it creates a Raft entry to add a
+// default member with the given `self`.
+func createConfigChangeEnts(ids []uint64, self uint64, term, index uint64) []raftpb.Entry {
+ ents := make([]raftpb.Entry, 0)
+ next := index + 1
+ found := false
+ for _, id := range ids {
+ if id == self {
+ found = true
+ continue
+ }
+ cc := &raftpb.ConfChange{
+ Type: raftpb.ConfChangeRemoveNode,
+ NodeID: id,
+ }
+ e := raftpb.Entry{
+ Type: raftpb.EntryConfChange,
+ Data: pbutil.MustMarshal(cc),
+ Term: term,
+ Index: next,
+ }
+ ents = append(ents, e)
+ next++
+ }
+ if !found {
+ m := membership.Member{
+ ID: types.ID(self),
+ RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:2380"}},
+ }
+ ctx, err := json.Marshal(m)
+ if err != nil {
+ plog.Panicf("marshal member should never fail: %v", err)
+ }
+ cc := &raftpb.ConfChange{
+ Type: raftpb.ConfChangeAddNode,
+ NodeID: self,
+ Context: ctx,
+ }
+ e := raftpb.Entry{
+ Type: raftpb.EntryConfChange,
+ Data: pbutil.MustMarshal(cc),
+ Term: term,
+ Index: next,
+ }
+ ents = append(ents, e)
+ }
+ return ents
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/server.go b/vendor/github.com/coreos/etcd/etcdserver/server.go
new file mode 100644
index 00000000..f891c862
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/server.go
@@ -0,0 +1,1743 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "context"
+ "encoding/json"
+ "expvar"
+ "fmt"
+ "math"
+ "math/rand"
+ "net/http"
+ "os"
+ "path"
+ "regexp"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/coreos/etcd/alarm"
+ "github.com/coreos/etcd/auth"
+ "github.com/coreos/etcd/compactor"
+ "github.com/coreos/etcd/discovery"
+ "github.com/coreos/etcd/etcdserver/api"
+ "github.com/coreos/etcd/etcdserver/api/v2http/httptypes"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/etcdserver/membership"
+ "github.com/coreos/etcd/etcdserver/stats"
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/lease/leasehttp"
+ "github.com/coreos/etcd/mvcc"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/pkg/fileutil"
+ "github.com/coreos/etcd/pkg/idutil"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/pkg/runtime"
+ "github.com/coreos/etcd/pkg/schedule"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/pkg/wait"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/rafthttp"
+ "github.com/coreos/etcd/snap"
+ "github.com/coreos/etcd/store"
+ "github.com/coreos/etcd/version"
+ "github.com/coreos/etcd/wal"
+
+ "github.com/coreos/go-semver/semver"
+ "github.com/coreos/pkg/capnslog"
+)
+
+const (
+ DefaultSnapCount = 100000
+
+ StoreClusterPrefix = "/0"
+ StoreKeysPrefix = "/1"
+
+ // HealthInterval is the minimum time the cluster should be healthy
+ // before accepting add member requests.
+ HealthInterval = 5 * time.Second
+
+ purgeFileInterval = 30 * time.Second
+ // monitorVersionInterval should be smaller than the timeout
+ // on the connection. Or we will not be able to reuse the connection
+ // (since it will timeout).
+ monitorVersionInterval = rafthttp.ConnWriteTimeout - time.Second
+
+ // max number of in-flight snapshot messages etcdserver allows to have
+ // This number is more than enough for most clusters with 5 machines.
+ maxInFlightMsgSnap = 16
+
+ releaseDelayAfterSnapshot = 30 * time.Second
+
+ // maxPendingRevokes is the maximum number of outstanding expired lease revocations.
+ maxPendingRevokes = 16
+
+ recommendedMaxRequestBytes = 10 * 1024 * 1024
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "etcdserver")
+
+ storeMemberAttributeRegexp = regexp.MustCompile(path.Join(membership.StoreMembersPrefix, "[[:xdigit:]]{1,16}", "attributes"))
+)
+
+func init() {
+ rand.Seed(time.Now().UnixNano())
+
+ expvar.Publish(
+ "file_descriptor_limit",
+ expvar.Func(
+ func() interface{} {
+ n, _ := runtime.FDLimit()
+ return n
+ },
+ ),
+ )
+}
+
+type Response struct {
+ Term uint64
+ Index uint64
+ Event *store.Event
+ Watcher store.Watcher
+ Err error
+}
+
+type ServerV2 interface {
+ Server
+ // Do takes a V2 request and attempts to fulfill it, returning a Response.
+ Do(ctx context.Context, r pb.Request) (Response, error)
+ stats.Stats
+ ClientCertAuthEnabled() bool
+}
+
+type ServerV3 interface {
+ Server
+ ID() types.ID
+ RaftTimer
+}
+
+func (s *EtcdServer) ClientCertAuthEnabled() bool { return s.Cfg.ClientCertAuthEnabled }
+
+type Server interface {
+ // Leader returns the ID of the leader Server.
+ Leader() types.ID
+
+ // AddMember attempts to add a member into the cluster. It will return
+ // ErrIDRemoved if member ID is removed from the cluster, or return
+ // ErrIDExists if member ID exists in the cluster.
+ AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error)
+ // RemoveMember attempts to remove a member from the cluster. It will
+ // return ErrIDRemoved if member ID is removed from the cluster, or return
+ // ErrIDNotFound if member ID is not in the cluster.
+ RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error)
+ // UpdateMember attempts to update an existing member in the cluster. It will
+ // return ErrIDNotFound if the member ID does not exist.
+ UpdateMember(ctx context.Context, updateMemb membership.Member) ([]*membership.Member, error)
+
+ // ClusterVersion is the cluster-wide minimum major.minor version.
+ // Cluster version is set to the min version that an etcd member is
+ // compatible with when first bootstrap.
+ //
+ // ClusterVersion is nil until the cluster is bootstrapped (has a quorum).
+ //
+ // During a rolling upgrades, the ClusterVersion will be updated
+ // automatically after a sync. (5 second by default)
+ //
+ // The API/raft component can utilize ClusterVersion to determine if
+ // it can accept a client request or a raft RPC.
+ // NOTE: ClusterVersion might be nil when etcd 2.1 works with etcd 2.0 and
+ // the leader is etcd 2.0. etcd 2.0 leader will not update clusterVersion since
+ // this feature is introduced post 2.0.
+ ClusterVersion() *semver.Version
+ Cluster() api.Cluster
+ Alarms() []*pb.AlarmMember
+}
+
+// EtcdServer is the production implementation of the Server interface
+type EtcdServer struct {
+ // inflightSnapshots holds count the number of snapshots currently inflight.
+ inflightSnapshots int64 // must use atomic operations to access; keep 64-bit aligned.
+ appliedIndex uint64 // must use atomic operations to access; keep 64-bit aligned.
+ committedIndex uint64 // must use atomic operations to access; keep 64-bit aligned.
+ // consistIndex used to hold the offset of current executing entry
+ // It is initialized to 0 before executing any entry.
+ consistIndex consistentIndex // must use atomic operations to access; keep 64-bit aligned.
+ r raftNode // uses 64-bit atomics; keep 64-bit aligned.
+
+ readych chan struct{}
+ Cfg ServerConfig
+
+ w wait.Wait
+
+ readMu sync.RWMutex
+ // read routine notifies etcd server that it waits for reading by sending an empty struct to
+ // readwaitC
+ readwaitc chan struct{}
+ // readNotifier is used to notify the read routine that it can process the request
+ // when there is no error
+ readNotifier *notifier
+
+ // stop signals the run goroutine should shutdown.
+ stop chan struct{}
+ // stopping is closed by run goroutine on shutdown.
+ stopping chan struct{}
+ // done is closed when all goroutines from start() complete.
+ done chan struct{}
+
+ errorc chan error
+ id types.ID
+ attributes membership.Attributes
+
+ cluster *membership.RaftCluster
+
+ store store.Store
+ snapshotter *snap.Snapshotter
+
+ applyV2 ApplierV2
+
+ // applyV3 is the applier with auth and quotas
+ applyV3 applierV3
+ // applyV3Base is the core applier without auth or quotas
+ applyV3Base applierV3
+ applyWait wait.WaitTime
+
+ kv mvcc.ConsistentWatchableKV
+ lessor lease.Lessor
+ bemu sync.Mutex
+ be backend.Backend
+ authStore auth.AuthStore
+ alarmStore *alarm.AlarmStore
+
+ stats *stats.ServerStats
+ lstats *stats.LeaderStats
+
+ SyncTicker *time.Ticker
+ // compactor is used to auto-compact the KV.
+ compactor compactor.Compactor
+
+ // peerRt used to send requests (version, lease) to peers.
+ peerRt http.RoundTripper
+ reqIDGen *idutil.Generator
+
+ // forceVersionC is used to force the version monitor loop
+ // to detect the cluster version immediately.
+ forceVersionC chan struct{}
+
+ // wgMu blocks concurrent waitgroup mutation while server stopping
+ wgMu sync.RWMutex
+ // wg is used to wait for the go routines that depends on the server state
+ // to exit when stopping the server.
+ wg sync.WaitGroup
+
+ // ctx is used for etcd-initiated requests that may need to be canceled
+ // on etcd server shutdown.
+ ctx context.Context
+ cancel context.CancelFunc
+
+ leadTimeMu sync.RWMutex
+ leadElectedTime time.Time
+}
+
+// NewServer creates a new EtcdServer from the supplied configuration. The
+// configuration is considered static for the lifetime of the EtcdServer.
+func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) {
+ st := store.New(StoreClusterPrefix, StoreKeysPrefix)
+
+ var (
+ w *wal.WAL
+ n raft.Node
+ s *raft.MemoryStorage
+ id types.ID
+ cl *membership.RaftCluster
+ )
+
+ if cfg.MaxRequestBytes > recommendedMaxRequestBytes {
+ plog.Warningf("MaxRequestBytes %v exceeds maximum recommended size %v", cfg.MaxRequestBytes, recommendedMaxRequestBytes)
+ }
+
+ if terr := fileutil.TouchDirAll(cfg.DataDir); terr != nil {
+ return nil, fmt.Errorf("cannot access data directory: %v", terr)
+ }
+
+ haveWAL := wal.Exist(cfg.WALDir())
+
+ if err = fileutil.TouchDirAll(cfg.SnapDir()); err != nil {
+ plog.Fatalf("create snapshot directory error: %v", err)
+ }
+ ss := snap.New(cfg.SnapDir())
+
+ bepath := cfg.backendPath()
+ beExist := fileutil.Exist(bepath)
+ be := openBackend(cfg)
+
+ defer func() {
+ if err != nil {
+ be.Close()
+ }
+ }()
+
+ prt, err := rafthttp.NewRoundTripper(cfg.PeerTLSInfo, cfg.peerDialTimeout())
+ if err != nil {
+ return nil, err
+ }
+ var (
+ remotes []*membership.Member
+ snapshot *raftpb.Snapshot
+ )
+
+ switch {
+ case !haveWAL && !cfg.NewCluster:
+ if err = cfg.VerifyJoinExisting(); err != nil {
+ return nil, err
+ }
+ cl, err = membership.NewClusterFromURLsMap(cfg.InitialClusterToken, cfg.InitialPeerURLsMap)
+ if err != nil {
+ return nil, err
+ }
+ existingCluster, gerr := GetClusterFromRemotePeers(getRemotePeerURLs(cl, cfg.Name), prt)
+ if gerr != nil {
+ return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %v", gerr)
+ }
+ if err = membership.ValidateClusterAndAssignIDs(cl, existingCluster); err != nil {
+ return nil, fmt.Errorf("error validating peerURLs %s: %v", existingCluster, err)
+ }
+ if !isCompatibleWithCluster(cl, cl.MemberByName(cfg.Name).ID, prt) {
+ return nil, fmt.Errorf("incompatible with current running cluster")
+ }
+
+ remotes = existingCluster.Members()
+ cl.SetID(existingCluster.ID())
+ cl.SetStore(st)
+ cl.SetBackend(be)
+ cfg.Print()
+ id, n, s, w = startNode(cfg, cl, nil)
+ case !haveWAL && cfg.NewCluster:
+ if err = cfg.VerifyBootstrap(); err != nil {
+ return nil, err
+ }
+ cl, err = membership.NewClusterFromURLsMap(cfg.InitialClusterToken, cfg.InitialPeerURLsMap)
+ if err != nil {
+ return nil, err
+ }
+ m := cl.MemberByName(cfg.Name)
+ if isMemberBootstrapped(cl, cfg.Name, prt, cfg.bootstrapTimeout()) {
+ return nil, fmt.Errorf("member %s has already been bootstrapped", m.ID)
+ }
+ if cfg.ShouldDiscover() {
+ var str string
+ str, err = discovery.JoinCluster(cfg.DiscoveryURL, cfg.DiscoveryProxy, m.ID, cfg.InitialPeerURLsMap.String())
+ if err != nil {
+ return nil, &DiscoveryError{Op: "join", Err: err}
+ }
+ var urlsmap types.URLsMap
+ urlsmap, err = types.NewURLsMap(str)
+ if err != nil {
+ return nil, err
+ }
+ if checkDuplicateURL(urlsmap) {
+ return nil, fmt.Errorf("discovery cluster %s has duplicate url", urlsmap)
+ }
+ if cl, err = membership.NewClusterFromURLsMap(cfg.InitialClusterToken, urlsmap); err != nil {
+ return nil, err
+ }
+ }
+ cl.SetStore(st)
+ cl.SetBackend(be)
+ cfg.PrintWithInitial()
+ id, n, s, w = startNode(cfg, cl, cl.MemberIDs())
+ case haveWAL:
+ if err = fileutil.IsDirWriteable(cfg.MemberDir()); err != nil {
+ return nil, fmt.Errorf("cannot write to member directory: %v", err)
+ }
+
+ if err = fileutil.IsDirWriteable(cfg.WALDir()); err != nil {
+ return nil, fmt.Errorf("cannot write to WAL directory: %v", err)
+ }
+
+ if cfg.ShouldDiscover() {
+ plog.Warningf("discovery token ignored since a cluster has already been initialized. Valid log found at %q", cfg.WALDir())
+ }
+ snapshot, err = ss.Load()
+ if err != nil && err != snap.ErrNoSnapshot {
+ return nil, err
+ }
+ if snapshot != nil {
+ if err = st.Recovery(snapshot.Data); err != nil {
+ plog.Panicf("recovered store from snapshot error: %v", err)
+ }
+ plog.Infof("recovered store from snapshot at index %d", snapshot.Metadata.Index)
+ if be, err = recoverSnapshotBackend(cfg, be, *snapshot); err != nil {
+ plog.Panicf("recovering backend from snapshot error: %v", err)
+ }
+ }
+ cfg.Print()
+ if !cfg.ForceNewCluster {
+ id, cl, n, s, w = restartNode(cfg, snapshot)
+ } else {
+ id, cl, n, s, w = restartAsStandaloneNode(cfg, snapshot)
+ }
+ cl.SetStore(st)
+ cl.SetBackend(be)
+ cl.Recover(api.UpdateCapability)
+ if cl.Version() != nil && !cl.Version().LessThan(semver.Version{Major: 3}) && !beExist {
+ os.RemoveAll(bepath)
+ return nil, fmt.Errorf("database file (%v) of the backend is missing", bepath)
+ }
+ default:
+ return nil, fmt.Errorf("unsupported bootstrap config")
+ }
+
+ if terr := fileutil.TouchDirAll(cfg.MemberDir()); terr != nil {
+ return nil, fmt.Errorf("cannot access member directory: %v", terr)
+ }
+
+ sstats := stats.NewServerStats(cfg.Name, id.String())
+ lstats := stats.NewLeaderStats(id.String())
+
+ heartbeat := time.Duration(cfg.TickMs) * time.Millisecond
+ srv = &EtcdServer{
+ readych: make(chan struct{}),
+ Cfg: cfg,
+ errorc: make(chan error, 1),
+ store: st,
+ snapshotter: ss,
+ r: *newRaftNode(
+ raftNodeConfig{
+ isIDRemoved: func(id uint64) bool { return cl.IsIDRemoved(types.ID(id)) },
+ Node: n,
+ heartbeat: heartbeat,
+ raftStorage: s,
+ storage: NewStorage(w, ss),
+ },
+ ),
+ id: id,
+ attributes: membership.Attributes{Name: cfg.Name, ClientURLs: cfg.ClientURLs.StringSlice()},
+ cluster: cl,
+ stats: sstats,
+ lstats: lstats,
+ SyncTicker: time.NewTicker(500 * time.Millisecond),
+ peerRt: prt,
+ reqIDGen: idutil.NewGenerator(uint16(id), time.Now()),
+ forceVersionC: make(chan struct{}),
+ }
+
+ srv.applyV2 = &applierV2store{store: srv.store, cluster: srv.cluster}
+
+ srv.be = be
+ minTTL := time.Duration((3*cfg.ElectionTicks)/2) * heartbeat
+
+ // always recover lessor before kv. When we recover the mvcc.KV it will reattach keys to its leases.
+ // If we recover mvcc.KV first, it will attach the keys to the wrong lessor before it recovers.
+ srv.lessor = lease.NewLessor(srv.be, int64(math.Ceil(minTTL.Seconds())))
+ srv.kv = mvcc.New(srv.be, srv.lessor, &srv.consistIndex)
+ if beExist {
+ kvindex := srv.kv.ConsistentIndex()
+ // TODO: remove kvindex != 0 checking when we do not expect users to upgrade
+ // etcd from pre-3.0 release.
+ if snapshot != nil && kvindex < snapshot.Metadata.Index {
+ if kvindex != 0 {
+ return nil, fmt.Errorf("database file (%v index %d) does not match with snapshot (index %d).", bepath, kvindex, snapshot.Metadata.Index)
+ }
+ plog.Warningf("consistent index never saved (snapshot index=%d)", snapshot.Metadata.Index)
+ }
+ }
+ newSrv := srv // since srv == nil in defer if srv is returned as nil
+ defer func() {
+ // closing backend without first closing kv can cause
+ // resumed compactions to fail with closed tx errors
+ if err != nil {
+ newSrv.kv.Close()
+ }
+ }()
+
+ srv.consistIndex.setConsistentIndex(srv.kv.ConsistentIndex())
+ tp, err := auth.NewTokenProvider(cfg.AuthToken,
+ func(index uint64) <-chan struct{} {
+ return srv.applyWait.Wait(index)
+ },
+ )
+ if err != nil {
+ plog.Errorf("failed to create token provider: %s", err)
+ return nil, err
+ }
+ srv.authStore = auth.NewAuthStore(srv.be, tp)
+ if num := cfg.AutoCompactionRetention; num != 0 {
+ srv.compactor, err = compactor.New(cfg.AutoCompactionMode, num, srv.kv, srv)
+ if err != nil {
+ return nil, err
+ }
+ srv.compactor.Run()
+ }
+
+ srv.applyV3Base = srv.newApplierV3Backend()
+ if err = srv.restoreAlarms(); err != nil {
+ return nil, err
+ }
+
+ // TODO: move transport initialization near the definition of remote
+ tr := &rafthttp.Transport{
+ TLSInfo: cfg.PeerTLSInfo,
+ DialTimeout: cfg.peerDialTimeout(),
+ ID: id,
+ URLs: cfg.PeerURLs,
+ ClusterID: cl.ID(),
+ Raft: srv,
+ Snapshotter: ss,
+ ServerStats: sstats,
+ LeaderStats: lstats,
+ ErrorC: srv.errorc,
+ }
+ if err = tr.Start(); err != nil {
+ return nil, err
+ }
+ // add all remotes into transport
+ for _, m := range remotes {
+ if m.ID != id {
+ tr.AddRemote(m.ID, m.PeerURLs)
+ }
+ }
+ for _, m := range cl.Members() {
+ if m.ID != id {
+ tr.AddPeer(m.ID, m.PeerURLs)
+ }
+ }
+ srv.r.transport = tr
+
+ return srv, nil
+}
+
+func (s *EtcdServer) adjustTicks() {
+ clusterN := len(s.cluster.Members())
+
+ // single-node fresh start, or single-node recovers from snapshot
+ if clusterN == 1 {
+ ticks := s.Cfg.ElectionTicks - 1
+ plog.Infof("%s as single-node; fast-forwarding %d ticks (election ticks %d)", s.ID(), ticks, s.Cfg.ElectionTicks)
+ s.r.advanceTicks(ticks)
+ return
+ }
+
+ if !s.Cfg.InitialElectionTickAdvance {
+ plog.Infof("skipping initial election tick advance (election tick %d)", s.Cfg.ElectionTicks)
+ return
+ }
+
+ // retry up to "rafthttp.ConnReadTimeout", which is 5-sec
+ // until peer connection reports; otherwise:
+ // 1. all connections failed, or
+ // 2. no active peers, or
+ // 3. restarted single-node with no snapshot
+ // then, do nothing, because advancing ticks would have no effect
+ waitTime := rafthttp.ConnReadTimeout
+ itv := 50 * time.Millisecond
+ for i := int64(0); i < int64(waitTime/itv); i++ {
+ select {
+ case <-time.After(itv):
+ case <-s.stopping:
+ return
+ }
+
+ peerN := s.r.transport.ActivePeers()
+ if peerN > 1 {
+ // multi-node received peer connection reports
+ // adjust ticks, in case slow leader message receive
+ ticks := s.Cfg.ElectionTicks - 2
+ plog.Infof("%s initialzed peer connection; fast-forwarding %d ticks (election ticks %d) with %d active peer(s)", s.ID(), ticks, s.Cfg.ElectionTicks, peerN)
+ s.r.advanceTicks(ticks)
+ return
+ }
+ }
+}
+
+// Start performs any initialization of the Server necessary for it to
+// begin serving requests. It must be called before Do or Process.
+// Start must be non-blocking; any long-running server functionality
+// should be implemented in goroutines.
+func (s *EtcdServer) Start() {
+ s.start()
+ s.goAttach(func() { s.adjustTicks() })
+ s.goAttach(func() { s.publish(s.Cfg.ReqTimeout()) })
+ s.goAttach(s.purgeFile)
+ s.goAttach(func() { monitorFileDescriptor(s.stopping) })
+ s.goAttach(s.monitorVersions)
+ s.goAttach(s.linearizableReadLoop)
+ s.goAttach(s.monitorKVHash)
+}
+
+// start prepares and starts server in a new goroutine. It is no longer safe to
+// modify a server's fields after it has been sent to Start.
+// This function is just used for testing.
+func (s *EtcdServer) start() {
+ if s.Cfg.SnapCount == 0 {
+ plog.Infof("set snapshot count to default %d", DefaultSnapCount)
+ s.Cfg.SnapCount = DefaultSnapCount
+ }
+ s.w = wait.New()
+ s.applyWait = wait.NewTimeList()
+ s.done = make(chan struct{})
+ s.stop = make(chan struct{})
+ s.stopping = make(chan struct{})
+ s.ctx, s.cancel = context.WithCancel(context.Background())
+ s.readwaitc = make(chan struct{}, 1)
+ s.readNotifier = newNotifier()
+ if s.ClusterVersion() != nil {
+ plog.Infof("starting server... [version: %v, cluster version: %v]", version.Version, version.Cluster(s.ClusterVersion().String()))
+ } else {
+ plog.Infof("starting server... [version: %v, cluster version: to_be_decided]", version.Version)
+ }
+ // TODO: if this is an empty log, writes all peer infos
+ // into the first entry
+ go s.run()
+}
+
+func (s *EtcdServer) purgeFile() {
+ var dberrc, serrc, werrc <-chan error
+ if s.Cfg.MaxSnapFiles > 0 {
+ dberrc = fileutil.PurgeFile(s.Cfg.SnapDir(), "snap.db", s.Cfg.MaxSnapFiles, purgeFileInterval, s.done)
+ serrc = fileutil.PurgeFile(s.Cfg.SnapDir(), "snap", s.Cfg.MaxSnapFiles, purgeFileInterval, s.done)
+ }
+ if s.Cfg.MaxWALFiles > 0 {
+ werrc = fileutil.PurgeFile(s.Cfg.WALDir(), "wal", s.Cfg.MaxWALFiles, purgeFileInterval, s.done)
+ }
+ select {
+ case e := <-dberrc:
+ plog.Fatalf("failed to purge snap db file %v", e)
+ case e := <-serrc:
+ plog.Fatalf("failed to purge snap file %v", e)
+ case e := <-werrc:
+ plog.Fatalf("failed to purge wal file %v", e)
+ case <-s.stopping:
+ return
+ }
+}
+
+func (s *EtcdServer) ID() types.ID { return s.id }
+
+func (s *EtcdServer) Cluster() api.Cluster { return s.cluster }
+
+func (s *EtcdServer) ApplyWait() <-chan struct{} { return s.applyWait.Wait(s.getCommittedIndex()) }
+
+type ServerPeer interface {
+ ServerV2
+ RaftHandler() http.Handler
+ LeaseHandler() http.Handler
+}
+
+func (s *EtcdServer) LeaseHandler() http.Handler {
+ if s.lessor == nil {
+ return nil
+ }
+ return leasehttp.NewHandler(s.lessor, s.ApplyWait)
+}
+
+func (s *EtcdServer) RaftHandler() http.Handler { return s.r.transport.Handler() }
+
+// Process takes a raft message and applies it to the server's raft state
+// machine, respecting any timeout of the given context.
+func (s *EtcdServer) Process(ctx context.Context, m raftpb.Message) error {
+ if s.cluster.IsIDRemoved(types.ID(m.From)) {
+ plog.Warningf("reject message from removed member %s", types.ID(m.From).String())
+ return httptypes.NewHTTPError(http.StatusForbidden, "cannot process message from removed member")
+ }
+ if m.Type == raftpb.MsgApp {
+ s.stats.RecvAppendReq(types.ID(m.From).String(), m.Size())
+ }
+ return s.r.Step(ctx, m)
+}
+
+func (s *EtcdServer) IsIDRemoved(id uint64) bool { return s.cluster.IsIDRemoved(types.ID(id)) }
+
+func (s *EtcdServer) ReportUnreachable(id uint64) { s.r.ReportUnreachable(id) }
+
+// ReportSnapshot reports snapshot sent status to the raft state machine,
+// and clears the used snapshot from the snapshot store.
+func (s *EtcdServer) ReportSnapshot(id uint64, status raft.SnapshotStatus) {
+ s.r.ReportSnapshot(id, status)
+}
+
+type etcdProgress struct {
+ confState raftpb.ConfState
+ snapi uint64
+ appliedt uint64
+ appliedi uint64
+}
+
+// raftReadyHandler contains a set of EtcdServer operations to be called by raftNode,
+// and helps decouple state machine logic from Raft algorithms.
+// TODO: add a state machine interface to apply the commit entries and do snapshot/recover
+type raftReadyHandler struct {
+ updateLeadership func(newLeader bool)
+ updateCommittedIndex func(uint64)
+}
+
+func (s *EtcdServer) run() {
+ sn, err := s.r.raftStorage.Snapshot()
+ if err != nil {
+ plog.Panicf("get snapshot from raft storage error: %v", err)
+ }
+
+ // asynchronously accept apply packets, dispatch progress in-order
+ sched := schedule.NewFIFOScheduler()
+
+ var (
+ smu sync.RWMutex
+ syncC <-chan time.Time
+ )
+ setSyncC := func(ch <-chan time.Time) {
+ smu.Lock()
+ syncC = ch
+ smu.Unlock()
+ }
+ getSyncC := func() (ch <-chan time.Time) {
+ smu.RLock()
+ ch = syncC
+ smu.RUnlock()
+ return
+ }
+ rh := &raftReadyHandler{
+ updateLeadership: func(newLeader bool) {
+ if !s.isLeader() {
+ if s.lessor != nil {
+ s.lessor.Demote()
+ }
+ if s.compactor != nil {
+ s.compactor.Pause()
+ }
+ setSyncC(nil)
+ } else {
+ if newLeader {
+ t := time.Now()
+ s.leadTimeMu.Lock()
+ s.leadElectedTime = t
+ s.leadTimeMu.Unlock()
+ }
+ setSyncC(s.SyncTicker.C)
+ if s.compactor != nil {
+ s.compactor.Resume()
+ }
+ }
+
+ // TODO: remove the nil checking
+ // current test utility does not provide the stats
+ if s.stats != nil {
+ s.stats.BecomeLeader()
+ }
+ },
+ updateCommittedIndex: func(ci uint64) {
+ cci := s.getCommittedIndex()
+ if ci > cci {
+ s.setCommittedIndex(ci)
+ }
+ },
+ }
+ s.r.start(rh)
+
+ ep := etcdProgress{
+ confState: sn.Metadata.ConfState,
+ snapi: sn.Metadata.Index,
+ appliedt: sn.Metadata.Term,
+ appliedi: sn.Metadata.Index,
+ }
+
+ defer func() {
+ s.wgMu.Lock() // block concurrent waitgroup adds in goAttach while stopping
+ close(s.stopping)
+ s.wgMu.Unlock()
+ s.cancel()
+
+ sched.Stop()
+
+ // wait for gouroutines before closing raft so wal stays open
+ s.wg.Wait()
+
+ s.SyncTicker.Stop()
+
+ // must stop raft after scheduler-- etcdserver can leak rafthttp pipelines
+ // by adding a peer after raft stops the transport
+ s.r.stop()
+
+ // kv, lessor and backend can be nil if running without v3 enabled
+ // or running unit tests.
+ if s.lessor != nil {
+ s.lessor.Stop()
+ }
+ if s.kv != nil {
+ s.kv.Close()
+ }
+ if s.authStore != nil {
+ s.authStore.Close()
+ }
+ if s.be != nil {
+ s.be.Close()
+ }
+ if s.compactor != nil {
+ s.compactor.Stop()
+ }
+ close(s.done)
+ }()
+
+ var expiredLeaseC <-chan []*lease.Lease
+ if s.lessor != nil {
+ expiredLeaseC = s.lessor.ExpiredLeasesC()
+ }
+
+ for {
+ select {
+ case ap := <-s.r.apply():
+ f := func(context.Context) { s.applyAll(&ep, &ap) }
+ sched.Schedule(f)
+ case leases := <-expiredLeaseC:
+ s.goAttach(func() {
+ // Increases throughput of expired leases deletion process through parallelization
+ c := make(chan struct{}, maxPendingRevokes)
+ for _, lease := range leases {
+ select {
+ case c <- struct{}{}:
+ case <-s.stopping:
+ return
+ }
+ lid := lease.ID
+ s.goAttach(func() {
+ ctx := s.authStore.WithRoot(s.ctx)
+ _, lerr := s.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: int64(lid)})
+ if lerr == nil {
+ leaseExpired.Inc()
+ } else {
+ plog.Warningf("failed to revoke %016x (%q)", lid, lerr.Error())
+ }
+
+ <-c
+ })
+ }
+ })
+ case err := <-s.errorc:
+ plog.Errorf("%s", err)
+ plog.Infof("the data-dir used by this member must be removed.")
+ return
+ case <-getSyncC():
+ if s.store.HasTTLKeys() {
+ s.sync(s.Cfg.ReqTimeout())
+ }
+ case <-s.stop:
+ return
+ }
+ }
+}
+
+func (s *EtcdServer) applyAll(ep *etcdProgress, apply *apply) {
+ s.applySnapshot(ep, apply)
+ s.applyEntries(ep, apply)
+
+ proposalsApplied.Set(float64(ep.appliedi))
+ s.applyWait.Trigger(ep.appliedi)
+ // wait for the raft routine to finish the disk writes before triggering a
+ // snapshot. or applied index might be greater than the last index in raft
+ // storage, since the raft routine might be slower than apply routine.
+ <-apply.notifyc
+
+ s.triggerSnapshot(ep)
+ select {
+ // snapshot requested via send()
+ case m := <-s.r.msgSnapC:
+ merged := s.createMergedSnapshotMessage(m, ep.appliedt, ep.appliedi, ep.confState)
+ s.sendMergedSnap(merged)
+ default:
+ }
+}
+
+func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) {
+ if raft.IsEmptySnap(apply.snapshot) {
+ return
+ }
+
+ plog.Infof("applying snapshot at index %d...", ep.snapi)
+ defer plog.Infof("finished applying incoming snapshot at index %d", ep.snapi)
+
+ if apply.snapshot.Metadata.Index <= ep.appliedi {
+ plog.Panicf("snapshot index [%d] should > appliedi[%d] + 1",
+ apply.snapshot.Metadata.Index, ep.appliedi)
+ }
+
+ // wait for raftNode to persist snapshot onto the disk
+ <-apply.notifyc
+
+ newbe, err := openSnapshotBackend(s.Cfg, s.snapshotter, apply.snapshot)
+ if err != nil {
+ plog.Panic(err)
+ }
+
+ // always recover lessor before kv. When we recover the mvcc.KV it will reattach keys to its leases.
+ // If we recover mvcc.KV first, it will attach the keys to the wrong lessor before it recovers.
+ if s.lessor != nil {
+ plog.Info("recovering lessor...")
+ s.lessor.Recover(newbe, func() lease.TxnDelete { return s.kv.Write() })
+ plog.Info("finished recovering lessor")
+ }
+
+ plog.Info("restoring mvcc store...")
+
+ if err := s.kv.Restore(newbe); err != nil {
+ plog.Panicf("restore KV error: %v", err)
+ }
+ s.consistIndex.setConsistentIndex(s.kv.ConsistentIndex())
+
+ plog.Info("finished restoring mvcc store")
+
+ // Closing old backend might block until all the txns
+ // on the backend are finished.
+ // We do not want to wait on closing the old backend.
+ s.bemu.Lock()
+ oldbe := s.be
+ go func() {
+ plog.Info("closing old backend...")
+ defer plog.Info("finished closing old backend")
+
+ if err := oldbe.Close(); err != nil {
+ plog.Panicf("close backend error: %v", err)
+ }
+ }()
+
+ s.be = newbe
+ s.bemu.Unlock()
+
+ plog.Info("recovering alarms...")
+ if err := s.restoreAlarms(); err != nil {
+ plog.Panicf("restore alarms error: %v", err)
+ }
+ plog.Info("finished recovering alarms")
+
+ if s.authStore != nil {
+ plog.Info("recovering auth store...")
+ s.authStore.Recover(newbe)
+ plog.Info("finished recovering auth store")
+ }
+
+ plog.Info("recovering store v2...")
+ if err := s.store.Recovery(apply.snapshot.Data); err != nil {
+ plog.Panicf("recovery store error: %v", err)
+ }
+ plog.Info("finished recovering store v2")
+
+ s.cluster.SetBackend(s.be)
+ plog.Info("recovering cluster configuration...")
+ s.cluster.Recover(api.UpdateCapability)
+ plog.Info("finished recovering cluster configuration")
+
+ plog.Info("removing old peers from network...")
+ // recover raft transport
+ s.r.transport.RemoveAllPeers()
+ plog.Info("finished removing old peers from network")
+
+ plog.Info("adding peers from new cluster configuration into network...")
+ for _, m := range s.cluster.Members() {
+ if m.ID == s.ID() {
+ continue
+ }
+ s.r.transport.AddPeer(m.ID, m.PeerURLs)
+ }
+ plog.Info("finished adding peers from new cluster configuration into network...")
+
+ ep.appliedt = apply.snapshot.Metadata.Term
+ ep.appliedi = apply.snapshot.Metadata.Index
+ ep.snapi = ep.appliedi
+ ep.confState = apply.snapshot.Metadata.ConfState
+}
+
+func (s *EtcdServer) applyEntries(ep *etcdProgress, apply *apply) {
+ if len(apply.entries) == 0 {
+ return
+ }
+ firsti := apply.entries[0].Index
+ if firsti > ep.appliedi+1 {
+ plog.Panicf("first index of committed entry[%d] should <= appliedi[%d] + 1", firsti, ep.appliedi)
+ }
+ var ents []raftpb.Entry
+ if ep.appliedi+1-firsti < uint64(len(apply.entries)) {
+ ents = apply.entries[ep.appliedi+1-firsti:]
+ }
+ if len(ents) == 0 {
+ return
+ }
+ var shouldstop bool
+ if ep.appliedt, ep.appliedi, shouldstop = s.apply(ents, &ep.confState); shouldstop {
+ go s.stopWithDelay(10*100*time.Millisecond, fmt.Errorf("the member has been permanently removed from the cluster"))
+ }
+}
+
+func (s *EtcdServer) triggerSnapshot(ep *etcdProgress) {
+ if ep.appliedi-ep.snapi <= s.Cfg.SnapCount {
+ return
+ }
+
+ plog.Infof("start to snapshot (applied: %d, lastsnap: %d)", ep.appliedi, ep.snapi)
+ s.snapshot(ep.appliedi, ep.confState)
+ ep.snapi = ep.appliedi
+}
+
+func (s *EtcdServer) isMultiNode() bool {
+ return s.cluster != nil && len(s.cluster.MemberIDs()) > 1
+}
+
+func (s *EtcdServer) isLeader() bool {
+ return uint64(s.ID()) == s.Lead()
+}
+
+// MoveLeader transfers the leader to the given transferee.
+func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) error {
+ now := time.Now()
+ interval := time.Duration(s.Cfg.TickMs) * time.Millisecond
+
+ plog.Infof("%s starts leadership transfer from %s to %s", s.ID(), types.ID(lead), types.ID(transferee))
+ s.r.TransferLeadership(ctx, lead, transferee)
+ for s.Lead() != transferee {
+ select {
+ case <-ctx.Done(): // time out
+ return ErrTimeoutLeaderTransfer
+ case <-time.After(interval):
+ }
+ }
+
+ // TODO: drain all requests, or drop all messages to the old leader
+
+ plog.Infof("%s finished leadership transfer from %s to %s (took %v)", s.ID(), types.ID(lead), types.ID(transferee), time.Since(now))
+ return nil
+}
+
+// TransferLeadership transfers the leader to the chosen transferee.
+func (s *EtcdServer) TransferLeadership() error {
+ if !s.isLeader() {
+ plog.Printf("skipped leadership transfer for stopping non-leader member")
+ return nil
+ }
+
+ if !s.isMultiNode() {
+ plog.Printf("skipped leadership transfer for single member cluster")
+ return nil
+ }
+
+ transferee, ok := longestConnected(s.r.transport, s.cluster.MemberIDs())
+ if !ok {
+ return ErrUnhealthy
+ }
+
+ tm := s.Cfg.ReqTimeout()
+ ctx, cancel := context.WithTimeout(s.ctx, tm)
+ err := s.MoveLeader(ctx, s.Lead(), uint64(transferee))
+ cancel()
+ return err
+}
+
+// HardStop stops the server without coordination with other members in the cluster.
+func (s *EtcdServer) HardStop() {
+ select {
+ case s.stop <- struct{}{}:
+ case <-s.done:
+ return
+ }
+ <-s.done
+}
+
+// Stop stops the server gracefully, and shuts down the running goroutine.
+// Stop should be called after a Start(s), otherwise it will block forever.
+// When stopping leader, Stop transfers its leadership to one of its peers
+// before stopping the server.
+// Stop terminates the Server and performs any necessary finalization.
+// Do and Process cannot be called after Stop has been invoked.
+func (s *EtcdServer) Stop() {
+ if err := s.TransferLeadership(); err != nil {
+ plog.Warningf("%s failed to transfer leadership (%v)", s.ID(), err)
+ }
+ s.HardStop()
+}
+
+// ReadyNotify returns a channel that will be closed when the server
+// is ready to serve client requests
+func (s *EtcdServer) ReadyNotify() <-chan struct{} { return s.readych }
+
+func (s *EtcdServer) stopWithDelay(d time.Duration, err error) {
+ select {
+ case <-time.After(d):
+ case <-s.done:
+ }
+ select {
+ case s.errorc <- err:
+ default:
+ }
+}
+
+// StopNotify returns a channel that receives a empty struct
+// when the server is stopped.
+func (s *EtcdServer) StopNotify() <-chan struct{} { return s.done }
+
+func (s *EtcdServer) SelfStats() []byte { return s.stats.JSON() }
+
+func (s *EtcdServer) LeaderStats() []byte {
+ lead := atomic.LoadUint64(&s.r.lead)
+ if lead != uint64(s.id) {
+ return nil
+ }
+ return s.lstats.JSON()
+}
+
+func (s *EtcdServer) StoreStats() []byte { return s.store.JsonStats() }
+
+func (s *EtcdServer) checkMembershipOperationPermission(ctx context.Context) error {
+ if s.authStore == nil {
+ // In the context of ordinary etcd process, s.authStore will never be nil.
+ // This branch is for handling cases in server_test.go
+ return nil
+ }
+
+ // Note that this permission check is done in the API layer,
+ // so TOCTOU problem can be caused potentially in a schedule like this:
+ // update membership with user A -> revoke root role of A -> apply membership change
+ // in the state machine layer
+ // However, both of membership change and role management requires the root privilege.
+ // So careful operation by admins can prevent the problem.
+ authInfo, err := s.AuthInfoFromCtx(ctx)
+ if err != nil {
+ return err
+ }
+
+ return s.AuthStore().IsAdminPermitted(authInfo)
+}
+
+func (s *EtcdServer) AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) {
+ if err := s.checkMembershipOperationPermission(ctx); err != nil {
+ return nil, err
+ }
+
+ if s.Cfg.StrictReconfigCheck {
+ // by default StrictReconfigCheck is enabled; reject new members if unhealthy
+ if !s.cluster.IsReadyToAddNewMember() {
+ plog.Warningf("not enough started members, rejecting member add %+v", memb)
+ return nil, ErrNotEnoughStartedMembers
+ }
+ if !isConnectedFullySince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), s.cluster.Members()) {
+ plog.Warningf("not healthy for reconfigure, rejecting member add %+v", memb)
+ return nil, ErrUnhealthy
+ }
+ }
+
+ // TODO: move Member to protobuf type
+ b, err := json.Marshal(memb)
+ if err != nil {
+ return nil, err
+ }
+ cc := raftpb.ConfChange{
+ Type: raftpb.ConfChangeAddNode,
+ NodeID: uint64(memb.ID),
+ Context: b,
+ }
+ return s.configure(ctx, cc)
+}
+
+func (s *EtcdServer) RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error) {
+ if err := s.checkMembershipOperationPermission(ctx); err != nil {
+ return nil, err
+ }
+
+ // by default StrictReconfigCheck is enabled; reject removal if leads to quorum loss
+ if err := s.mayRemoveMember(types.ID(id)); err != nil {
+ return nil, err
+ }
+
+ cc := raftpb.ConfChange{
+ Type: raftpb.ConfChangeRemoveNode,
+ NodeID: id,
+ }
+ return s.configure(ctx, cc)
+}
+
+func (s *EtcdServer) mayRemoveMember(id types.ID) error {
+ if !s.Cfg.StrictReconfigCheck {
+ return nil
+ }
+
+ if !s.cluster.IsReadyToRemoveMember(uint64(id)) {
+ plog.Warningf("not enough started members, rejecting remove member %s", id)
+ return ErrNotEnoughStartedMembers
+ }
+
+ // downed member is safe to remove since it's not part of the active quorum
+ if t := s.r.transport.ActiveSince(id); id != s.ID() && t.IsZero() {
+ return nil
+ }
+
+ // protect quorum if some members are down
+ m := s.cluster.Members()
+ active := numConnectedSince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), m)
+ if (active - 1) < 1+((len(m)-1)/2) {
+ plog.Warningf("reconfigure breaks active quorum, rejecting remove member %s", id)
+ return ErrUnhealthy
+ }
+
+ return nil
+}
+
+func (s *EtcdServer) UpdateMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) {
+ b, merr := json.Marshal(memb)
+ if merr != nil {
+ return nil, merr
+ }
+
+ if err := s.checkMembershipOperationPermission(ctx); err != nil {
+ return nil, err
+ }
+ cc := raftpb.ConfChange{
+ Type: raftpb.ConfChangeUpdateNode,
+ NodeID: uint64(memb.ID),
+ Context: b,
+ }
+ return s.configure(ctx, cc)
+}
+
+// Implement the RaftTimer interface
+
+func (s *EtcdServer) Index() uint64 { return atomic.LoadUint64(&s.r.index) }
+
+func (s *EtcdServer) Term() uint64 { return atomic.LoadUint64(&s.r.term) }
+
+// Lead is only for testing purposes.
+// TODO: add Raft server interface to expose raft related info:
+// Index, Term, Lead, Committed, Applied, LastIndex, etc.
+func (s *EtcdServer) Lead() uint64 { return atomic.LoadUint64(&s.r.lead) }
+
+func (s *EtcdServer) Leader() types.ID { return types.ID(s.Lead()) }
+
+type confChangeResponse struct {
+ membs []*membership.Member
+ err error
+}
+
+// configure sends a configuration change through consensus and
+// then waits for it to be applied to the server. It
+// will block until the change is performed or there is an error.
+func (s *EtcdServer) configure(ctx context.Context, cc raftpb.ConfChange) ([]*membership.Member, error) {
+ cc.ID = s.reqIDGen.Next()
+ ch := s.w.Register(cc.ID)
+ start := time.Now()
+ if err := s.r.ProposeConfChange(ctx, cc); err != nil {
+ s.w.Trigger(cc.ID, nil)
+ return nil, err
+ }
+ select {
+ case x := <-ch:
+ if x == nil {
+ plog.Panicf("configure trigger value should never be nil")
+ }
+ resp := x.(*confChangeResponse)
+ return resp.membs, resp.err
+ case <-ctx.Done():
+ s.w.Trigger(cc.ID, nil) // GC wait
+ return nil, s.parseProposeCtxErr(ctx.Err(), start)
+ case <-s.stopping:
+ return nil, ErrStopped
+ }
+}
+
+// sync proposes a SYNC request and is non-blocking.
+// This makes no guarantee that the request will be proposed or performed.
+// The request will be canceled after the given timeout.
+func (s *EtcdServer) sync(timeout time.Duration) {
+ req := pb.Request{
+ Method: "SYNC",
+ ID: s.reqIDGen.Next(),
+ Time: time.Now().UnixNano(),
+ }
+ data := pbutil.MustMarshal(&req)
+ // There is no promise that node has leader when do SYNC request,
+ // so it uses goroutine to propose.
+ ctx, cancel := context.WithTimeout(s.ctx, timeout)
+ s.goAttach(func() {
+ s.r.Propose(ctx, data)
+ cancel()
+ })
+}
+
+// publish registers server information into the cluster. The information
+// is the JSON representation of this server's member struct, updated with the
+// static clientURLs of the server.
+// The function keeps attempting to register until it succeeds,
+// or its server is stopped.
+func (s *EtcdServer) publish(timeout time.Duration) {
+ b, err := json.Marshal(s.attributes)
+ if err != nil {
+ plog.Panicf("json marshal error: %v", err)
+ return
+ }
+ req := pb.Request{
+ Method: "PUT",
+ Path: membership.MemberAttributesStorePath(s.id),
+ Val: string(b),
+ }
+
+ for {
+ ctx, cancel := context.WithTimeout(s.ctx, timeout)
+ _, err := s.Do(ctx, req)
+ cancel()
+ switch err {
+ case nil:
+ close(s.readych)
+ plog.Infof("published %+v to cluster %s", s.attributes, s.cluster.ID())
+ return
+ case ErrStopped:
+ plog.Infof("aborting publish because server is stopped")
+ return
+ default:
+ plog.Errorf("publish error: %v", err)
+ }
+ }
+}
+
+func (s *EtcdServer) sendMergedSnap(merged snap.Message) {
+ atomic.AddInt64(&s.inflightSnapshots, 1)
+
+ s.r.transport.SendSnapshot(merged)
+ s.goAttach(func() {
+ select {
+ case ok := <-merged.CloseNotify():
+ // delay releasing inflight snapshot for another 30 seconds to
+ // block log compaction.
+ // If the follower still fails to catch up, it is probably just too slow
+ // to catch up. We cannot avoid the snapshot cycle anyway.
+ if ok {
+ select {
+ case <-time.After(releaseDelayAfterSnapshot):
+ case <-s.stopping:
+ }
+ }
+ atomic.AddInt64(&s.inflightSnapshots, -1)
+ case <-s.stopping:
+ return
+ }
+ })
+}
+
+// apply takes entries received from Raft (after it has been committed) and
+// applies them to the current state of the EtcdServer.
+// The given entries should not be empty.
+func (s *EtcdServer) apply(es []raftpb.Entry, confState *raftpb.ConfState) (appliedt uint64, appliedi uint64, shouldStop bool) {
+ for i := range es {
+ e := es[i]
+ switch e.Type {
+ case raftpb.EntryNormal:
+ s.applyEntryNormal(&e)
+ case raftpb.EntryConfChange:
+ // set the consistent index of current executing entry
+ if e.Index > s.consistIndex.ConsistentIndex() {
+ s.consistIndex.setConsistentIndex(e.Index)
+ }
+ var cc raftpb.ConfChange
+ pbutil.MustUnmarshal(&cc, e.Data)
+ removedSelf, err := s.applyConfChange(cc, confState)
+ s.setAppliedIndex(e.Index)
+ shouldStop = shouldStop || removedSelf
+ s.w.Trigger(cc.ID, &confChangeResponse{s.cluster.Members(), err})
+ default:
+ plog.Panicf("entry type should be either EntryNormal or EntryConfChange")
+ }
+ atomic.StoreUint64(&s.r.index, e.Index)
+ atomic.StoreUint64(&s.r.term, e.Term)
+ appliedt = e.Term
+ appliedi = e.Index
+ }
+ return appliedt, appliedi, shouldStop
+}
+
+// applyEntryNormal apples an EntryNormal type raftpb request to the EtcdServer
+func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) {
+ shouldApplyV3 := false
+ if e.Index > s.consistIndex.ConsistentIndex() {
+ // set the consistent index of current executing entry
+ s.consistIndex.setConsistentIndex(e.Index)
+ shouldApplyV3 = true
+ }
+ defer s.setAppliedIndex(e.Index)
+
+ // raft state machine may generate noop entry when leader confirmation.
+ // skip it in advance to avoid some potential bug in the future
+ if len(e.Data) == 0 {
+ select {
+ case s.forceVersionC <- struct{}{}:
+ default:
+ }
+ // promote lessor when the local member is leader and finished
+ // applying all entries from the last term.
+ if s.isLeader() {
+ s.lessor.Promote(s.Cfg.electionTimeout())
+ }
+ return
+ }
+
+ var raftReq pb.InternalRaftRequest
+ if !pbutil.MaybeUnmarshal(&raftReq, e.Data) { // backward compatible
+ var r pb.Request
+ rp := &r
+ pbutil.MustUnmarshal(rp, e.Data)
+ s.w.Trigger(r.ID, s.applyV2Request((*RequestV2)(rp)))
+ return
+ }
+ if raftReq.V2 != nil {
+ req := (*RequestV2)(raftReq.V2)
+ s.w.Trigger(req.ID, s.applyV2Request(req))
+ return
+ }
+
+ // do not re-apply applied entries.
+ if !shouldApplyV3 {
+ return
+ }
+
+ id := raftReq.ID
+ if id == 0 {
+ id = raftReq.Header.ID
+ }
+
+ var ar *applyResult
+ needResult := s.w.IsRegistered(id)
+ if needResult || !noSideEffect(&raftReq) {
+ if !needResult && raftReq.Txn != nil {
+ removeNeedlessRangeReqs(raftReq.Txn)
+ }
+ ar = s.applyV3.Apply(&raftReq)
+ }
+
+ if ar == nil {
+ return
+ }
+
+ if ar.err != ErrNoSpace || len(s.alarmStore.Get(pb.AlarmType_NOSPACE)) > 0 {
+ s.w.Trigger(id, ar)
+ return
+ }
+
+ plog.Errorf("applying raft message exceeded backend quota")
+ s.goAttach(func() {
+ a := &pb.AlarmRequest{
+ MemberID: uint64(s.ID()),
+ Action: pb.AlarmRequest_ACTIVATE,
+ Alarm: pb.AlarmType_NOSPACE,
+ }
+ s.raftRequest(s.ctx, pb.InternalRaftRequest{Alarm: a})
+ s.w.Trigger(id, ar)
+ })
+}
+
+// applyConfChange applies a ConfChange to the server. It is only
+// invoked with a ConfChange that has already passed through Raft
+func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.ConfState) (bool, error) {
+ if err := s.cluster.ValidateConfigurationChange(cc); err != nil {
+ cc.NodeID = raft.None
+ s.r.ApplyConfChange(cc)
+ return false, err
+ }
+ *confState = *s.r.ApplyConfChange(cc)
+ switch cc.Type {
+ case raftpb.ConfChangeAddNode:
+ m := new(membership.Member)
+ if err := json.Unmarshal(cc.Context, m); err != nil {
+ plog.Panicf("unmarshal member should never fail: %v", err)
+ }
+ if cc.NodeID != uint64(m.ID) {
+ plog.Panicf("nodeID should always be equal to member ID")
+ }
+ s.cluster.AddMember(m)
+ if m.ID != s.id {
+ s.r.transport.AddPeer(m.ID, m.PeerURLs)
+ }
+ case raftpb.ConfChangeRemoveNode:
+ id := types.ID(cc.NodeID)
+ s.cluster.RemoveMember(id)
+ if id == s.id {
+ return true, nil
+ }
+ s.r.transport.RemovePeer(id)
+ case raftpb.ConfChangeUpdateNode:
+ m := new(membership.Member)
+ if err := json.Unmarshal(cc.Context, m); err != nil {
+ plog.Panicf("unmarshal member should never fail: %v", err)
+ }
+ if cc.NodeID != uint64(m.ID) {
+ plog.Panicf("nodeID should always be equal to member ID")
+ }
+ s.cluster.UpdateRaftAttributes(m.ID, m.RaftAttributes)
+ if m.ID != s.id {
+ s.r.transport.UpdatePeer(m.ID, m.PeerURLs)
+ }
+ }
+ return false, nil
+}
+
+// TODO: non-blocking snapshot
+func (s *EtcdServer) snapshot(snapi uint64, confState raftpb.ConfState) {
+ clone := s.store.Clone()
+ // commit kv to write metadata (for example: consistent index) to disk.
+ // KV().commit() updates the consistent index in backend.
+ // All operations that update consistent index must be called sequentially
+ // from applyAll function.
+ // So KV().Commit() cannot run in parallel with apply. It has to be called outside
+ // the go routine created below.
+ s.KV().Commit()
+
+ s.goAttach(func() {
+ d, err := clone.SaveNoCopy()
+ // TODO: current store will never fail to do a snapshot
+ // what should we do if the store might fail?
+ if err != nil {
+ plog.Panicf("store save should never fail: %v", err)
+ }
+ snap, err := s.r.raftStorage.CreateSnapshot(snapi, &confState, d)
+ if err != nil {
+ // the snapshot was done asynchronously with the progress of raft.
+ // raft might have already got a newer snapshot.
+ if err == raft.ErrSnapOutOfDate {
+ return
+ }
+ plog.Panicf("unexpected create snapshot error %v", err)
+ }
+ // SaveSnap saves the snapshot and releases the locked wal files
+ // to the snapshot index.
+ if err = s.r.storage.SaveSnap(snap); err != nil {
+ plog.Fatalf("save snapshot error: %v", err)
+ }
+ plog.Infof("saved snapshot at index %d", snap.Metadata.Index)
+
+ // When sending a snapshot, etcd will pause compaction.
+ // After receives a snapshot, the slow follower needs to get all the entries right after
+ // the snapshot sent to catch up. If we do not pause compaction, the log entries right after
+ // the snapshot sent might already be compacted. It happens when the snapshot takes long time
+ // to send and save. Pausing compaction avoids triggering a snapshot sending cycle.
+ if atomic.LoadInt64(&s.inflightSnapshots) != 0 {
+ plog.Infof("skip compaction since there is an inflight snapshot")
+ return
+ }
+
+ // keep some in memory log entries for slow followers.
+ compacti := uint64(1)
+ if snapi > numberOfCatchUpEntries {
+ compacti = snapi - numberOfCatchUpEntries
+ }
+ err = s.r.raftStorage.Compact(compacti)
+ if err != nil {
+ // the compaction was done asynchronously with the progress of raft.
+ // raft log might already been compact.
+ if err == raft.ErrCompacted {
+ return
+ }
+ plog.Panicf("unexpected compaction error %v", err)
+ }
+ plog.Infof("compacted raft log at %d", compacti)
+ })
+}
+
+// CutPeer drops messages to the specified peer.
+func (s *EtcdServer) CutPeer(id types.ID) {
+ tr, ok := s.r.transport.(*rafthttp.Transport)
+ if ok {
+ tr.CutPeer(id)
+ }
+}
+
+// MendPeer recovers the message dropping behavior of the given peer.
+func (s *EtcdServer) MendPeer(id types.ID) {
+ tr, ok := s.r.transport.(*rafthttp.Transport)
+ if ok {
+ tr.MendPeer(id)
+ }
+}
+
+func (s *EtcdServer) PauseSending() { s.r.pauseSending() }
+
+func (s *EtcdServer) ResumeSending() { s.r.resumeSending() }
+
+func (s *EtcdServer) ClusterVersion() *semver.Version {
+ if s.cluster == nil {
+ return nil
+ }
+ return s.cluster.Version()
+}
+
+// monitorVersions checks the member's version every monitorVersionInterval.
+// It updates the cluster version if all members agrees on a higher one.
+// It prints out log if there is a member with a higher version than the
+// local version.
+func (s *EtcdServer) monitorVersions() {
+ for {
+ select {
+ case <-s.forceVersionC:
+ case <-time.After(monitorVersionInterval):
+ case <-s.stopping:
+ return
+ }
+
+ if s.Leader() != s.ID() {
+ continue
+ }
+
+ v := decideClusterVersion(getVersions(s.cluster, s.id, s.peerRt))
+ if v != nil {
+ // only keep major.minor version for comparison
+ v = &semver.Version{
+ Major: v.Major,
+ Minor: v.Minor,
+ }
+ }
+
+ // if the current version is nil:
+ // 1. use the decided version if possible
+ // 2. or use the min cluster version
+ if s.cluster.Version() == nil {
+ verStr := version.MinClusterVersion
+ if v != nil {
+ verStr = v.String()
+ }
+ s.goAttach(func() { s.updateClusterVersion(verStr) })
+ continue
+ }
+
+ // update cluster version only if the decided version is greater than
+ // the current cluster version
+ if v != nil && s.cluster.Version().LessThan(*v) {
+ s.goAttach(func() { s.updateClusterVersion(v.String()) })
+ }
+ }
+}
+
+func (s *EtcdServer) updateClusterVersion(ver string) {
+ if s.cluster.Version() == nil {
+ plog.Infof("setting up the initial cluster version to %s", version.Cluster(ver))
+ } else {
+ plog.Infof("updating the cluster version from %s to %s", version.Cluster(s.cluster.Version().String()), version.Cluster(ver))
+ }
+ req := pb.Request{
+ Method: "PUT",
+ Path: membership.StoreClusterVersionKey(),
+ Val: ver,
+ }
+ ctx, cancel := context.WithTimeout(s.ctx, s.Cfg.ReqTimeout())
+ _, err := s.Do(ctx, req)
+ cancel()
+ switch err {
+ case nil:
+ return
+ case ErrStopped:
+ plog.Infof("aborting update cluster version because server is stopped")
+ return
+ default:
+ plog.Errorf("error updating cluster version (%v)", err)
+ }
+}
+
+func (s *EtcdServer) parseProposeCtxErr(err error, start time.Time) error {
+ switch err {
+ case context.Canceled:
+ return ErrCanceled
+ case context.DeadlineExceeded:
+ s.leadTimeMu.RLock()
+ curLeadElected := s.leadElectedTime
+ s.leadTimeMu.RUnlock()
+ prevLeadLost := curLeadElected.Add(-2 * time.Duration(s.Cfg.ElectionTicks) * time.Duration(s.Cfg.TickMs) * time.Millisecond)
+ if start.After(prevLeadLost) && start.Before(curLeadElected) {
+ return ErrTimeoutDueToLeaderFail
+ }
+
+ lead := types.ID(atomic.LoadUint64(&s.r.lead))
+ switch lead {
+ case types.ID(raft.None):
+ // TODO: return error to specify it happens because the cluster does not have leader now
+ case s.ID():
+ if !isConnectedToQuorumSince(s.r.transport, start, s.ID(), s.cluster.Members()) {
+ return ErrTimeoutDueToConnectionLost
+ }
+ default:
+ if !isConnectedSince(s.r.transport, start, lead) {
+ return ErrTimeoutDueToConnectionLost
+ }
+ }
+
+ return ErrTimeout
+ default:
+ return err
+ }
+}
+
+func (s *EtcdServer) KV() mvcc.ConsistentWatchableKV { return s.kv }
+func (s *EtcdServer) Backend() backend.Backend {
+ s.bemu.Lock()
+ defer s.bemu.Unlock()
+ return s.be
+}
+
+func (s *EtcdServer) AuthStore() auth.AuthStore { return s.authStore }
+
+func (s *EtcdServer) restoreAlarms() error {
+ s.applyV3 = s.newApplierV3()
+ as, err := alarm.NewAlarmStore(s)
+ if err != nil {
+ return err
+ }
+ s.alarmStore = as
+ if len(as.Get(pb.AlarmType_NOSPACE)) > 0 {
+ s.applyV3 = newApplierV3Capped(s.applyV3)
+ }
+ if len(as.Get(pb.AlarmType_CORRUPT)) > 0 {
+ s.applyV3 = newApplierV3Corrupt(s.applyV3)
+ }
+ return nil
+}
+
+func (s *EtcdServer) getAppliedIndex() uint64 {
+ return atomic.LoadUint64(&s.appliedIndex)
+}
+
+func (s *EtcdServer) setAppliedIndex(v uint64) {
+ atomic.StoreUint64(&s.appliedIndex, v)
+}
+
+func (s *EtcdServer) getCommittedIndex() uint64 {
+ return atomic.LoadUint64(&s.committedIndex)
+}
+
+func (s *EtcdServer) setCommittedIndex(v uint64) {
+ atomic.StoreUint64(&s.committedIndex, v)
+}
+
+// goAttach creates a goroutine on a given function and tracks it using
+// the etcdserver waitgroup.
+func (s *EtcdServer) goAttach(f func()) {
+ s.wgMu.RLock() // this blocks with ongoing close(s.stopping)
+ defer s.wgMu.RUnlock()
+ select {
+ case <-s.stopping:
+ plog.Warning("server has stopped (skipping goAttach)")
+ return
+ default:
+ }
+
+ // now safe to add since waitgroup wait has not started yet
+ s.wg.Add(1)
+ go func() {
+ defer s.wg.Done()
+ f()
+ }()
+}
+
+func (s *EtcdServer) Alarms() []*pb.AlarmMember {
+ return s.alarmStore.Get(pb.AlarmType_NONE)
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/snapshot_merge.go b/vendor/github.com/coreos/etcd/etcdserver/snapshot_merge.go
new file mode 100644
index 00000000..928aa95b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/snapshot_merge.go
@@ -0,0 +1,73 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "io"
+
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/snap"
+)
+
+// createMergedSnapshotMessage creates a snapshot message that contains: raft status (term, conf),
+// a snapshot of v2 store inside raft.Snapshot as []byte, a snapshot of v3 KV in the top level message
+// as ReadCloser.
+func (s *EtcdServer) createMergedSnapshotMessage(m raftpb.Message, snapt, snapi uint64, confState raftpb.ConfState) snap.Message {
+ // get a snapshot of v2 store as []byte
+ clone := s.store.Clone()
+ d, err := clone.SaveNoCopy()
+ if err != nil {
+ plog.Panicf("store save should never fail: %v", err)
+ }
+
+ // commit kv to write metadata(for example: consistent index).
+ s.KV().Commit()
+ dbsnap := s.be.Snapshot()
+ // get a snapshot of v3 KV as readCloser
+ rc := newSnapshotReaderCloser(dbsnap)
+
+ // put the []byte snapshot of store into raft snapshot and return the merged snapshot with
+ // KV readCloser snapshot.
+ snapshot := raftpb.Snapshot{
+ Metadata: raftpb.SnapshotMetadata{
+ Index: snapi,
+ Term: snapt,
+ ConfState: confState,
+ },
+ Data: d,
+ }
+ m.Snapshot = snapshot
+
+ return *snap.NewMessage(m, rc, dbsnap.Size())
+}
+
+func newSnapshotReaderCloser(snapshot backend.Snapshot) io.ReadCloser {
+ pr, pw := io.Pipe()
+ go func() {
+ n, err := snapshot.WriteTo(pw)
+ if err == nil {
+ plog.Infof("wrote database snapshot out [total bytes: %d]", n)
+ } else {
+ plog.Warningf("failed to write database snapshot out [written bytes: %d]: %v", n, err)
+ }
+ pw.CloseWithError(err)
+ err = snapshot.Close()
+ if err != nil {
+ plog.Panicf("failed to close database snapshot: %v", err)
+ }
+ }()
+ return pr
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/stats/leader.go b/vendor/github.com/coreos/etcd/etcdserver/stats/leader.go
new file mode 100644
index 00000000..8f6a54ff
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/stats/leader.go
@@ -0,0 +1,128 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package stats
+
+import (
+ "encoding/json"
+ "math"
+ "sync"
+ "time"
+)
+
+// LeaderStats is used by the leader in an etcd cluster, and encapsulates
+// statistics about communication with its followers
+type LeaderStats struct {
+ leaderStats
+ sync.Mutex
+}
+
+type leaderStats struct {
+ // Leader is the ID of the leader in the etcd cluster.
+ // TODO(jonboulle): clarify that these are IDs, not names
+ Leader string `json:"leader"`
+ Followers map[string]*FollowerStats `json:"followers"`
+}
+
+// NewLeaderStats generates a new LeaderStats with the given id as leader
+func NewLeaderStats(id string) *LeaderStats {
+ return &LeaderStats{
+ leaderStats: leaderStats{
+ Leader: id,
+ Followers: make(map[string]*FollowerStats),
+ },
+ }
+}
+
+func (ls *LeaderStats) JSON() []byte {
+ ls.Lock()
+ stats := ls.leaderStats
+ ls.Unlock()
+ b, err := json.Marshal(stats)
+ // TODO(jonboulle): appropriate error handling?
+ if err != nil {
+ plog.Errorf("error marshalling leader stats (%v)", err)
+ }
+ return b
+}
+
+func (ls *LeaderStats) Follower(name string) *FollowerStats {
+ ls.Lock()
+ defer ls.Unlock()
+ fs, ok := ls.Followers[name]
+ if !ok {
+ fs = &FollowerStats{}
+ fs.Latency.Minimum = 1 << 63
+ ls.Followers[name] = fs
+ }
+ return fs
+}
+
+// FollowerStats encapsulates various statistics about a follower in an etcd cluster
+type FollowerStats struct {
+ Latency LatencyStats `json:"latency"`
+ Counts CountsStats `json:"counts"`
+
+ sync.Mutex
+}
+
+// LatencyStats encapsulates latency statistics.
+type LatencyStats struct {
+ Current float64 `json:"current"`
+ Average float64 `json:"average"`
+ averageSquare float64
+ StandardDeviation float64 `json:"standardDeviation"`
+ Minimum float64 `json:"minimum"`
+ Maximum float64 `json:"maximum"`
+}
+
+// CountsStats encapsulates raft statistics.
+type CountsStats struct {
+ Fail uint64 `json:"fail"`
+ Success uint64 `json:"success"`
+}
+
+// Succ updates the FollowerStats with a successful send
+func (fs *FollowerStats) Succ(d time.Duration) {
+ fs.Lock()
+ defer fs.Unlock()
+
+ total := float64(fs.Counts.Success) * fs.Latency.Average
+ totalSquare := float64(fs.Counts.Success) * fs.Latency.averageSquare
+
+ fs.Counts.Success++
+
+ fs.Latency.Current = float64(d) / (1000000.0)
+
+ if fs.Latency.Current > fs.Latency.Maximum {
+ fs.Latency.Maximum = fs.Latency.Current
+ }
+
+ if fs.Latency.Current < fs.Latency.Minimum {
+ fs.Latency.Minimum = fs.Latency.Current
+ }
+
+ fs.Latency.Average = (total + fs.Latency.Current) / float64(fs.Counts.Success)
+ fs.Latency.averageSquare = (totalSquare + fs.Latency.Current*fs.Latency.Current) / float64(fs.Counts.Success)
+
+ // sdv = sqrt(avg(x^2) - avg(x)^2)
+ fs.Latency.StandardDeviation = math.Sqrt(fs.Latency.averageSquare - fs.Latency.Average*fs.Latency.Average)
+}
+
+// Fail updates the FollowerStats with an unsuccessful send
+func (fs *FollowerStats) Fail() {
+ fs.Lock()
+ defer fs.Unlock()
+ fs.Counts.Fail++
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/stats/queue.go b/vendor/github.com/coreos/etcd/etcdserver/stats/queue.go
new file mode 100644
index 00000000..635074c4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/stats/queue.go
@@ -0,0 +1,110 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package stats
+
+import (
+ "sync"
+ "time"
+)
+
+const (
+ queueCapacity = 200
+)
+
+// RequestStats represent the stats for a request.
+// It encapsulates the sending time and the size of the request.
+type RequestStats struct {
+ SendingTime time.Time
+ Size int
+}
+
+type statsQueue struct {
+ items [queueCapacity]*RequestStats
+ size int
+ front int
+ back int
+ totalReqSize int
+ rwl sync.RWMutex
+}
+
+func (q *statsQueue) Len() int {
+ return q.size
+}
+
+func (q *statsQueue) ReqSize() int {
+ return q.totalReqSize
+}
+
+// FrontAndBack gets the front and back elements in the queue
+// We must grab front and back together with the protection of the lock
+func (q *statsQueue) frontAndBack() (*RequestStats, *RequestStats) {
+ q.rwl.RLock()
+ defer q.rwl.RUnlock()
+ if q.size != 0 {
+ return q.items[q.front], q.items[q.back]
+ }
+ return nil, nil
+}
+
+// Insert function insert a RequestStats into the queue and update the records
+func (q *statsQueue) Insert(p *RequestStats) {
+ q.rwl.Lock()
+ defer q.rwl.Unlock()
+
+ q.back = (q.back + 1) % queueCapacity
+
+ if q.size == queueCapacity { //dequeue
+ q.totalReqSize -= q.items[q.front].Size
+ q.front = (q.back + 1) % queueCapacity
+ } else {
+ q.size++
+ }
+
+ q.items[q.back] = p
+ q.totalReqSize += q.items[q.back].Size
+
+}
+
+// Rate function returns the package rate and byte rate
+func (q *statsQueue) Rate() (float64, float64) {
+ front, back := q.frontAndBack()
+
+ if front == nil || back == nil {
+ return 0, 0
+ }
+
+ if time.Since(back.SendingTime) > time.Second {
+ q.Clear()
+ return 0, 0
+ }
+
+ sampleDuration := back.SendingTime.Sub(front.SendingTime)
+
+ pr := float64(q.Len()) / float64(sampleDuration) * float64(time.Second)
+
+ br := float64(q.ReqSize()) / float64(sampleDuration) * float64(time.Second)
+
+ return pr, br
+}
+
+// Clear function clear up the statsQueue
+func (q *statsQueue) Clear() {
+ q.rwl.Lock()
+ defer q.rwl.Unlock()
+ q.back = -1
+ q.front = 0
+ q.size = 0
+ q.totalReqSize = 0
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/stats/server.go b/vendor/github.com/coreos/etcd/etcdserver/stats/server.go
new file mode 100644
index 00000000..b026e448
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/stats/server.go
@@ -0,0 +1,142 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package stats
+
+import (
+ "encoding/json"
+ "log"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/raft"
+)
+
+// ServerStats encapsulates various statistics about an EtcdServer and its
+// communication with other members of the cluster
+type ServerStats struct {
+ serverStats
+ sync.Mutex
+}
+
+func NewServerStats(name, id string) *ServerStats {
+ ss := &ServerStats{
+ serverStats: serverStats{
+ Name: name,
+ ID: id,
+ },
+ }
+ now := time.Now()
+ ss.StartTime = now
+ ss.LeaderInfo.StartTime = now
+ ss.sendRateQueue = &statsQueue{back: -1}
+ ss.recvRateQueue = &statsQueue{back: -1}
+ return ss
+}
+
+type serverStats struct {
+ Name string `json:"name"`
+ // ID is the raft ID of the node.
+ // TODO(jonboulle): use ID instead of name?
+ ID string `json:"id"`
+ State raft.StateType `json:"state"`
+ StartTime time.Time `json:"startTime"`
+
+ LeaderInfo struct {
+ Name string `json:"leader"`
+ Uptime string `json:"uptime"`
+ StartTime time.Time `json:"startTime"`
+ } `json:"leaderInfo"`
+
+ RecvAppendRequestCnt uint64 `json:"recvAppendRequestCnt,"`
+ RecvingPkgRate float64 `json:"recvPkgRate,omitempty"`
+ RecvingBandwidthRate float64 `json:"recvBandwidthRate,omitempty"`
+
+ SendAppendRequestCnt uint64 `json:"sendAppendRequestCnt"`
+ SendingPkgRate float64 `json:"sendPkgRate,omitempty"`
+ SendingBandwidthRate float64 `json:"sendBandwidthRate,omitempty"`
+
+ sendRateQueue *statsQueue
+ recvRateQueue *statsQueue
+}
+
+func (ss *ServerStats) JSON() []byte {
+ ss.Lock()
+ stats := ss.serverStats
+ stats.SendingPkgRate, stats.SendingBandwidthRate = stats.sendRateQueue.Rate()
+ stats.RecvingPkgRate, stats.RecvingBandwidthRate = stats.recvRateQueue.Rate()
+ stats.LeaderInfo.Uptime = time.Since(stats.LeaderInfo.StartTime).String()
+ ss.Unlock()
+ b, err := json.Marshal(stats)
+ // TODO(jonboulle): appropriate error handling?
+ if err != nil {
+ log.Printf("stats: error marshalling server stats: %v", err)
+ }
+ return b
+}
+
+// RecvAppendReq updates the ServerStats in response to an AppendRequest
+// from the given leader being received
+func (ss *ServerStats) RecvAppendReq(leader string, reqSize int) {
+ ss.Lock()
+ defer ss.Unlock()
+
+ now := time.Now()
+
+ ss.State = raft.StateFollower
+ if leader != ss.LeaderInfo.Name {
+ ss.LeaderInfo.Name = leader
+ ss.LeaderInfo.StartTime = now
+ }
+
+ ss.recvRateQueue.Insert(
+ &RequestStats{
+ SendingTime: now,
+ Size: reqSize,
+ },
+ )
+ ss.RecvAppendRequestCnt++
+}
+
+// SendAppendReq updates the ServerStats in response to an AppendRequest
+// being sent by this server
+func (ss *ServerStats) SendAppendReq(reqSize int) {
+ ss.Lock()
+ defer ss.Unlock()
+
+ ss.becomeLeader()
+
+ ss.sendRateQueue.Insert(
+ &RequestStats{
+ SendingTime: time.Now(),
+ Size: reqSize,
+ },
+ )
+
+ ss.SendAppendRequestCnt++
+}
+
+func (ss *ServerStats) BecomeLeader() {
+ ss.Lock()
+ defer ss.Unlock()
+ ss.becomeLeader()
+}
+
+func (ss *ServerStats) becomeLeader() {
+ if ss.State != raft.StateLeader {
+ ss.State = raft.StateLeader
+ ss.LeaderInfo.Name = ss.ID
+ ss.LeaderInfo.StartTime = time.Now()
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/stats/stats.go b/vendor/github.com/coreos/etcd/etcdserver/stats/stats.go
new file mode 100644
index 00000000..2b5f7071
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/stats/stats.go
@@ -0,0 +1,32 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package stats defines a standard interface for etcd cluster statistics.
+package stats
+
+import "github.com/coreos/pkg/capnslog"
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "etcdserver/stats")
+)
+
+type Stats interface {
+ // SelfStats returns the struct representing statistics of this server
+ SelfStats() []byte
+ // LeaderStats returns the statistics of all followers in the cluster
+ // if this server is leader. Otherwise, nil is returned.
+ LeaderStats() []byte
+ // StoreStats returns statistics of the store backing this EtcdServer
+ StoreStats() []byte
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/storage.go b/vendor/github.com/coreos/etcd/etcdserver/storage.go
new file mode 100644
index 00000000..55c2dd4b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/storage.go
@@ -0,0 +1,98 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "io"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/snap"
+ "github.com/coreos/etcd/wal"
+ "github.com/coreos/etcd/wal/walpb"
+)
+
+type Storage interface {
+ // Save function saves ents and state to the underlying stable storage.
+ // Save MUST block until st and ents are on stable storage.
+ Save(st raftpb.HardState, ents []raftpb.Entry) error
+ // SaveSnap function saves snapshot to the underlying stable storage.
+ SaveSnap(snap raftpb.Snapshot) error
+ // Close closes the Storage and performs finalization.
+ Close() error
+}
+
+type storage struct {
+ *wal.WAL
+ *snap.Snapshotter
+}
+
+func NewStorage(w *wal.WAL, s *snap.Snapshotter) Storage {
+ return &storage{w, s}
+}
+
+// SaveSnap saves the snapshot to disk and release the locked
+// wal files since they will not be used.
+func (st *storage) SaveSnap(snap raftpb.Snapshot) error {
+ walsnap := walpb.Snapshot{
+ Index: snap.Metadata.Index,
+ Term: snap.Metadata.Term,
+ }
+ err := st.WAL.SaveSnapshot(walsnap)
+ if err != nil {
+ return err
+ }
+ err = st.Snapshotter.SaveSnap(snap)
+ if err != nil {
+ return err
+ }
+ return st.WAL.ReleaseLockTo(snap.Metadata.Index)
+}
+
+func readWAL(waldir string, snap walpb.Snapshot) (w *wal.WAL, id, cid types.ID, st raftpb.HardState, ents []raftpb.Entry) {
+ var (
+ err error
+ wmetadata []byte
+ )
+
+ repaired := false
+ for {
+ if w, err = wal.Open(waldir, snap); err != nil {
+ plog.Fatalf("open wal error: %v", err)
+ }
+ if wmetadata, st, ents, err = w.ReadAll(); err != nil {
+ w.Close()
+ // we can only repair ErrUnexpectedEOF and we never repair twice.
+ if repaired || err != io.ErrUnexpectedEOF {
+ plog.Fatalf("read wal error (%v) and cannot be repaired", err)
+ }
+ if !wal.Repair(waldir) {
+ plog.Fatalf("WAL error (%v) cannot be repaired", err)
+ } else {
+ plog.Infof("repaired WAL error (%v)", err)
+ repaired = true
+ }
+ continue
+ }
+ break
+ }
+ var metadata pb.Metadata
+ pbutil.MustUnmarshal(&metadata, wmetadata)
+ id = types.ID(metadata.NodeID)
+ cid = types.ID(metadata.ClusterID)
+ return w, id, cid, st, ents
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/util.go b/vendor/github.com/coreos/etcd/etcdserver/util.go
new file mode 100644
index 00000000..79bb6b85
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/util.go
@@ -0,0 +1,155 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "time"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/etcdserver/membership"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/rafthttp"
+ "github.com/golang/protobuf/proto"
+)
+
+// isConnectedToQuorumSince checks whether the local member is connected to the
+// quorum of the cluster since the given time.
+func isConnectedToQuorumSince(transport rafthttp.Transporter, since time.Time, self types.ID, members []*membership.Member) bool {
+ return numConnectedSince(transport, since, self, members) >= (len(members)/2)+1
+}
+
+// isConnectedSince checks whether the local member is connected to the
+// remote member since the given time.
+func isConnectedSince(transport rafthttp.Transporter, since time.Time, remote types.ID) bool {
+ t := transport.ActiveSince(remote)
+ return !t.IsZero() && t.Before(since)
+}
+
+// isConnectedFullySince checks whether the local member is connected to all
+// members in the cluster since the given time.
+func isConnectedFullySince(transport rafthttp.Transporter, since time.Time, self types.ID, members []*membership.Member) bool {
+ return numConnectedSince(transport, since, self, members) == len(members)
+}
+
+// numConnectedSince counts how many members are connected to the local member
+// since the given time.
+func numConnectedSince(transport rafthttp.Transporter, since time.Time, self types.ID, members []*membership.Member) int {
+ connectedNum := 0
+ for _, m := range members {
+ if m.ID == self || isConnectedSince(transport, since, m.ID) {
+ connectedNum++
+ }
+ }
+ return connectedNum
+}
+
+// longestConnected chooses the member with longest active-since-time.
+// It returns false, if nothing is active.
+func longestConnected(tp rafthttp.Transporter, membs []types.ID) (types.ID, bool) {
+ var longest types.ID
+ var oldest time.Time
+ for _, id := range membs {
+ tm := tp.ActiveSince(id)
+ if tm.IsZero() { // inactive
+ continue
+ }
+
+ if oldest.IsZero() { // first longest candidate
+ oldest = tm
+ longest = id
+ }
+
+ if tm.Before(oldest) {
+ oldest = tm
+ longest = id
+ }
+ }
+ if uint64(longest) == 0 {
+ return longest, false
+ }
+ return longest, true
+}
+
+type notifier struct {
+ c chan struct{}
+ err error
+}
+
+func newNotifier() *notifier {
+ return ¬ifier{
+ c: make(chan struct{}),
+ }
+}
+
+func (nc *notifier) notify(err error) {
+ nc.err = err
+ close(nc.c)
+}
+
+func warnOfExpensiveRequest(now time.Time, reqStringer fmt.Stringer, respMsg proto.Message, err error) {
+ var resp string
+ if !isNil(respMsg) {
+ resp = fmt.Sprintf("size:%d", proto.Size(respMsg))
+ }
+ warnOfExpensiveGenericRequest(now, reqStringer, "", resp, err)
+}
+
+func warnOfExpensiveReadOnlyTxnRequest(now time.Time, r *pb.TxnRequest, txnResponse *pb.TxnResponse, err error) {
+ reqStringer := pb.NewLoggableTxnRequest(r)
+ var resp string
+ if !isNil(txnResponse) {
+ var resps []string
+ for _, r := range txnResponse.Responses {
+ switch op := r.Response.(type) {
+ case *pb.ResponseOp_ResponseRange:
+ resps = append(resps, fmt.Sprintf("range_response_count:%d", len(op.ResponseRange.Kvs)))
+ default:
+ // only range responses should be in a read only txn request
+ }
+ }
+ resp = fmt.Sprintf("responses:<%s> size:%d", strings.Join(resps, " "), proto.Size(txnResponse))
+ }
+ warnOfExpensiveGenericRequest(now, reqStringer, "read-only range ", resp, err)
+}
+
+func warnOfExpensiveReadOnlyRangeRequest(now time.Time, reqStringer fmt.Stringer, rangeResponse *pb.RangeResponse, err error) {
+ var resp string
+ if !isNil(rangeResponse) {
+ resp = fmt.Sprintf("range_response_count:%d size:%d", len(rangeResponse.Kvs), proto.Size(rangeResponse))
+ }
+ warnOfExpensiveGenericRequest(now, reqStringer, "read-only range ", resp, err)
+}
+
+func warnOfExpensiveGenericRequest(now time.Time, reqStringer fmt.Stringer, prefix string, resp string, err error) {
+ // TODO: add metrics
+ d := time.Since(now)
+ if d > warnApplyDuration {
+ var result string
+ if err != nil {
+ result = fmt.Sprintf("error:%v", err)
+ } else {
+ result = resp
+ }
+ plog.Warningf("%srequest %q with result %q took too long (%v) to execute", prefix, reqStringer.String(), result, d)
+ slowApplies.Inc()
+ }
+}
+
+func isNil(msg proto.Message) bool {
+ return msg == nil || reflect.ValueOf(msg).IsNil()
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/v2_server.go b/vendor/github.com/coreos/etcd/etcdserver/v2_server.go
new file mode 100644
index 00000000..b458350c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/v2_server.go
@@ -0,0 +1,165 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "context"
+ "time"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/store"
+)
+
+type RequestV2 pb.Request
+
+type RequestV2Handler interface {
+ Post(ctx context.Context, r *RequestV2) (Response, error)
+ Put(ctx context.Context, r *RequestV2) (Response, error)
+ Delete(ctx context.Context, r *RequestV2) (Response, error)
+ QGet(ctx context.Context, r *RequestV2) (Response, error)
+ Get(ctx context.Context, r *RequestV2) (Response, error)
+ Head(ctx context.Context, r *RequestV2) (Response, error)
+}
+
+type reqV2HandlerEtcdServer struct {
+ reqV2HandlerStore
+ s *EtcdServer
+}
+
+type reqV2HandlerStore struct {
+ store store.Store
+ applier ApplierV2
+}
+
+func NewStoreRequestV2Handler(s store.Store, applier ApplierV2) RequestV2Handler {
+ return &reqV2HandlerStore{s, applier}
+}
+
+func (a *reqV2HandlerStore) Post(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.applier.Post(r), nil
+}
+
+func (a *reqV2HandlerStore) Put(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.applier.Put(r), nil
+}
+
+func (a *reqV2HandlerStore) Delete(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.applier.Delete(r), nil
+}
+
+func (a *reqV2HandlerStore) QGet(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.applier.QGet(r), nil
+}
+
+func (a *reqV2HandlerStore) Get(ctx context.Context, r *RequestV2) (Response, error) {
+ if r.Wait {
+ wc, err := a.store.Watch(r.Path, r.Recursive, r.Stream, r.Since)
+ return Response{Watcher: wc}, err
+ }
+ ev, err := a.store.Get(r.Path, r.Recursive, r.Sorted)
+ return Response{Event: ev}, err
+}
+
+func (a *reqV2HandlerStore) Head(ctx context.Context, r *RequestV2) (Response, error) {
+ ev, err := a.store.Get(r.Path, r.Recursive, r.Sorted)
+ return Response{Event: ev}, err
+}
+
+func (a *reqV2HandlerEtcdServer) Post(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.processRaftRequest(ctx, r)
+}
+
+func (a *reqV2HandlerEtcdServer) Put(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.processRaftRequest(ctx, r)
+}
+
+func (a *reqV2HandlerEtcdServer) Delete(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.processRaftRequest(ctx, r)
+}
+
+func (a *reqV2HandlerEtcdServer) QGet(ctx context.Context, r *RequestV2) (Response, error) {
+ return a.processRaftRequest(ctx, r)
+}
+
+func (a *reqV2HandlerEtcdServer) processRaftRequest(ctx context.Context, r *RequestV2) (Response, error) {
+ data, err := ((*pb.Request)(r)).Marshal()
+ if err != nil {
+ return Response{}, err
+ }
+ ch := a.s.w.Register(r.ID)
+
+ start := time.Now()
+ a.s.r.Propose(ctx, data)
+ proposalsPending.Inc()
+ defer proposalsPending.Dec()
+
+ select {
+ case x := <-ch:
+ resp := x.(Response)
+ return resp, resp.Err
+ case <-ctx.Done():
+ proposalsFailed.Inc()
+ a.s.w.Trigger(r.ID, nil) // GC wait
+ return Response{}, a.s.parseProposeCtxErr(ctx.Err(), start)
+ case <-a.s.stopping:
+ }
+ return Response{}, ErrStopped
+}
+
+func (s *EtcdServer) Do(ctx context.Context, r pb.Request) (Response, error) {
+ r.ID = s.reqIDGen.Next()
+ h := &reqV2HandlerEtcdServer{
+ reqV2HandlerStore: reqV2HandlerStore{
+ store: s.store,
+ applier: s.applyV2,
+ },
+ s: s,
+ }
+ rp := &r
+ resp, err := ((*RequestV2)(rp)).Handle(ctx, h)
+ resp.Term, resp.Index = s.Term(), s.Index()
+ return resp, err
+}
+
+// Handle interprets r and performs an operation on s.store according to r.Method
+// and other fields. If r.Method is "POST", "PUT", "DELETE", or a "GET" with
+// Quorum == true, r will be sent through consensus before performing its
+// respective operation. Do will block until an action is performed or there is
+// an error.
+func (r *RequestV2) Handle(ctx context.Context, v2api RequestV2Handler) (Response, error) {
+ if r.Method == "GET" && r.Quorum {
+ r.Method = "QGET"
+ }
+ switch r.Method {
+ case "POST":
+ return v2api.Post(ctx, r)
+ case "PUT":
+ return v2api.Put(ctx, r)
+ case "DELETE":
+ return v2api.Delete(ctx, r)
+ case "QGET":
+ return v2api.QGet(ctx, r)
+ case "GET":
+ return v2api.Get(ctx, r)
+ case "HEAD":
+ return v2api.Head(ctx, r)
+ }
+ return Response{}, ErrUnknownMethod
+}
+
+func (r *RequestV2) String() string {
+ rpb := pb.Request(*r)
+ return rpb.String()
+}
diff --git a/vendor/github.com/coreos/etcd/etcdserver/v3_server.go b/vendor/github.com/coreos/etcd/etcdserver/v3_server.go
new file mode 100644
index 00000000..8d5961bb
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/etcdserver/v3_server.go
@@ -0,0 +1,719 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdserver
+
+import (
+ "bytes"
+ "context"
+ "encoding/binary"
+ "time"
+
+ "github.com/coreos/etcd/auth"
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/etcdserver/membership"
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/lease/leasehttp"
+ "github.com/coreos/etcd/mvcc"
+ "github.com/coreos/etcd/raft"
+
+ "github.com/gogo/protobuf/proto"
+)
+
+const (
+ // In the health case, there might be a small gap (10s of entries) between
+ // the applied index and committed index.
+ // However, if the committed entries are very heavy to apply, the gap might grow.
+ // We should stop accepting new proposals if the gap growing to a certain point.
+ maxGapBetweenApplyAndCommitIndex = 5000
+)
+
+type RaftKV interface {
+ Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error)
+ Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error)
+ DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error)
+ Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error)
+ Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error)
+}
+
+type Lessor interface {
+ // LeaseGrant sends LeaseGrant request to raft and apply it after committed.
+ LeaseGrant(ctx context.Context, r *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error)
+ // LeaseRevoke sends LeaseRevoke request to raft and apply it after committed.
+ LeaseRevoke(ctx context.Context, r *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error)
+
+ // LeaseRenew renews the lease with given ID. The renewed TTL is returned. Or an error
+ // is returned.
+ LeaseRenew(ctx context.Context, id lease.LeaseID) (int64, error)
+
+ // LeaseTimeToLive retrieves lease information.
+ LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error)
+
+ // LeaseLeases lists all leases.
+ LeaseLeases(ctx context.Context, r *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error)
+}
+
+type Authenticator interface {
+ AuthEnable(ctx context.Context, r *pb.AuthEnableRequest) (*pb.AuthEnableResponse, error)
+ AuthDisable(ctx context.Context, r *pb.AuthDisableRequest) (*pb.AuthDisableResponse, error)
+ Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error)
+ UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error)
+ UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error)
+ UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error)
+ UserGrantRole(ctx context.Context, r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error)
+ UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error)
+ UserRevokeRole(ctx context.Context, r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error)
+ RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
+ RoleGrantPermission(ctx context.Context, r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error)
+ RoleGet(ctx context.Context, r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error)
+ RoleRevokePermission(ctx context.Context, r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error)
+ RoleDelete(ctx context.Context, r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error)
+ UserList(ctx context.Context, r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error)
+ RoleList(ctx context.Context, r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error)
+}
+
+func (s *EtcdServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
+ var resp *pb.RangeResponse
+ var err error
+ defer func(start time.Time) {
+ warnOfExpensiveReadOnlyRangeRequest(start, r, resp, err)
+ }(time.Now())
+
+ if !r.Serializable {
+ err = s.linearizableReadNotify(ctx)
+ if err != nil {
+ return nil, err
+ }
+ }
+ chk := func(ai *auth.AuthInfo) error {
+ return s.authStore.IsRangePermitted(ai, r.Key, r.RangeEnd)
+ }
+
+ get := func() { resp, err = s.applyV3Base.Range(nil, r) }
+ if serr := s.doSerialize(ctx, chk, get); serr != nil {
+ err = serr
+ return nil, err
+ }
+ return resp, err
+}
+
+func (s *EtcdServer) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{Put: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.PutResponse), nil
+}
+
+func (s *EtcdServer) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{DeleteRange: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.DeleteRangeResponse), nil
+}
+
+func (s *EtcdServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) {
+ if isTxnReadonly(r) {
+ if !isTxnSerializable(r) {
+ err := s.linearizableReadNotify(ctx)
+ if err != nil {
+ return nil, err
+ }
+ }
+ var resp *pb.TxnResponse
+ var err error
+ chk := func(ai *auth.AuthInfo) error {
+ return checkTxnAuth(s.authStore, ai, r)
+ }
+
+ defer func(start time.Time) {
+ warnOfExpensiveReadOnlyTxnRequest(start, r, resp, err)
+ }(time.Now())
+
+ get := func() { resp, err = s.applyV3Base.Txn(r) }
+ if serr := s.doSerialize(ctx, chk, get); serr != nil {
+ return nil, serr
+ }
+ return resp, err
+ }
+
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{Txn: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.TxnResponse), nil
+}
+
+func isTxnSerializable(r *pb.TxnRequest) bool {
+ for _, u := range r.Success {
+ if r := u.GetRequestRange(); r == nil || !r.Serializable {
+ return false
+ }
+ }
+ for _, u := range r.Failure {
+ if r := u.GetRequestRange(); r == nil || !r.Serializable {
+ return false
+ }
+ }
+ return true
+}
+
+func isTxnReadonly(r *pb.TxnRequest) bool {
+ for _, u := range r.Success {
+ if r := u.GetRequestRange(); r == nil {
+ return false
+ }
+ }
+ for _, u := range r.Failure {
+ if r := u.GetRequestRange(); r == nil {
+ return false
+ }
+ }
+ return true
+}
+
+func (s *EtcdServer) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error) {
+ result, err := s.processInternalRaftRequestOnce(ctx, pb.InternalRaftRequest{Compaction: r})
+ if r.Physical && result != nil && result.physc != nil {
+ <-result.physc
+ // The compaction is done deleting keys; the hash is now settled
+ // but the data is not necessarily committed. If there's a crash,
+ // the hash may revert to a hash prior to compaction completing
+ // if the compaction resumes. Force the finished compaction to
+ // commit so it won't resume following a crash.
+ s.be.ForceCommit()
+ }
+ if err != nil {
+ return nil, err
+ }
+ if result.err != nil {
+ return nil, result.err
+ }
+ resp := result.resp.(*pb.CompactionResponse)
+ if resp == nil {
+ resp = &pb.CompactionResponse{}
+ }
+ if resp.Header == nil {
+ resp.Header = &pb.ResponseHeader{}
+ }
+ resp.Header.Revision = s.kv.Rev()
+ return resp, nil
+}
+
+func (s *EtcdServer) LeaseGrant(ctx context.Context, r *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) {
+ // no id given? choose one
+ for r.ID == int64(lease.NoLease) {
+ // only use positive int64 id's
+ r.ID = int64(s.reqIDGen.Next() & ((1 << 63) - 1))
+ }
+ resp, err := s.raftRequestOnce(ctx, pb.InternalRaftRequest{LeaseGrant: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.LeaseGrantResponse), nil
+}
+
+func (s *EtcdServer) LeaseRevoke(ctx context.Context, r *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) {
+ resp, err := s.raftRequestOnce(ctx, pb.InternalRaftRequest{LeaseRevoke: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.LeaseRevokeResponse), nil
+}
+
+func (s *EtcdServer) LeaseRenew(ctx context.Context, id lease.LeaseID) (int64, error) {
+ ttl, err := s.lessor.Renew(id)
+ if err == nil { // already requested to primary lessor(leader)
+ return ttl, nil
+ }
+ if err != lease.ErrNotPrimary {
+ return -1, err
+ }
+
+ cctx, cancel := context.WithTimeout(ctx, s.Cfg.ReqTimeout())
+ defer cancel()
+
+ // renewals don't go through raft; forward to leader manually
+ for cctx.Err() == nil && err != nil {
+ leader, lerr := s.waitLeader(cctx)
+ if lerr != nil {
+ return -1, lerr
+ }
+ for _, url := range leader.PeerURLs {
+ lurl := url + leasehttp.LeasePrefix
+ ttl, err = leasehttp.RenewHTTP(cctx, id, lurl, s.peerRt)
+ if err == nil || err == lease.ErrLeaseNotFound {
+ return ttl, err
+ }
+ }
+ }
+ return -1, ErrTimeout
+}
+
+func (s *EtcdServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) {
+ if s.Leader() == s.ID() {
+ // primary; timetolive directly from leader
+ le := s.lessor.Lookup(lease.LeaseID(r.ID))
+ if le == nil {
+ return nil, lease.ErrLeaseNotFound
+ }
+ // TODO: fill out ResponseHeader
+ resp := &pb.LeaseTimeToLiveResponse{Header: &pb.ResponseHeader{}, ID: r.ID, TTL: int64(le.Remaining().Seconds()), GrantedTTL: le.TTL()}
+ if r.Keys {
+ ks := le.Keys()
+ kbs := make([][]byte, len(ks))
+ for i := range ks {
+ kbs[i] = []byte(ks[i])
+ }
+ resp.Keys = kbs
+ }
+ return resp, nil
+ }
+
+ cctx, cancel := context.WithTimeout(ctx, s.Cfg.ReqTimeout())
+ defer cancel()
+
+ // forward to leader
+ for cctx.Err() == nil {
+ leader, err := s.waitLeader(cctx)
+ if err != nil {
+ return nil, err
+ }
+ for _, url := range leader.PeerURLs {
+ lurl := url + leasehttp.LeaseInternalPrefix
+ resp, err := leasehttp.TimeToLiveHTTP(cctx, lease.LeaseID(r.ID), r.Keys, lurl, s.peerRt)
+ if err == nil {
+ return resp.LeaseTimeToLiveResponse, nil
+ }
+ if err == lease.ErrLeaseNotFound {
+ return nil, err
+ }
+ }
+ }
+ return nil, ErrTimeout
+}
+
+func (s *EtcdServer) LeaseLeases(ctx context.Context, r *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) {
+ ls := s.lessor.Leases()
+ lss := make([]*pb.LeaseStatus, len(ls))
+ for i := range ls {
+ lss[i] = &pb.LeaseStatus{ID: int64(ls[i].ID)}
+ }
+ return &pb.LeaseLeasesResponse{Header: newHeader(s), Leases: lss}, nil
+}
+
+func (s *EtcdServer) waitLeader(ctx context.Context) (*membership.Member, error) {
+ leader := s.cluster.Member(s.Leader())
+ for leader == nil {
+ // wait an election
+ dur := time.Duration(s.Cfg.ElectionTicks) * time.Duration(s.Cfg.TickMs) * time.Millisecond
+ select {
+ case <-time.After(dur):
+ leader = s.cluster.Member(s.Leader())
+ case <-s.stopping:
+ return nil, ErrStopped
+ case <-ctx.Done():
+ return nil, ErrNoLeader
+ }
+ }
+ if leader == nil || len(leader.PeerURLs) == 0 {
+ return nil, ErrNoLeader
+ }
+ return leader, nil
+}
+
+func (s *EtcdServer) Alarm(ctx context.Context, r *pb.AlarmRequest) (*pb.AlarmResponse, error) {
+ resp, err := s.raftRequestOnce(ctx, pb.InternalRaftRequest{Alarm: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AlarmResponse), nil
+}
+
+func (s *EtcdServer) AuthEnable(ctx context.Context, r *pb.AuthEnableRequest) (*pb.AuthEnableResponse, error) {
+ resp, err := s.raftRequestOnce(ctx, pb.InternalRaftRequest{AuthEnable: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthEnableResponse), nil
+}
+
+func (s *EtcdServer) AuthDisable(ctx context.Context, r *pb.AuthDisableRequest) (*pb.AuthDisableResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthDisable: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthDisableResponse), nil
+}
+
+func (s *EtcdServer) Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) {
+ if err := s.linearizableReadNotify(ctx); err != nil {
+ return nil, err
+ }
+
+ var resp proto.Message
+ for {
+ checkedRevision, err := s.AuthStore().CheckPassword(r.Name, r.Password)
+ if err != nil {
+ if err != auth.ErrAuthNotEnabled {
+ plog.Errorf("invalid authentication request to user %s was issued", r.Name)
+ }
+ return nil, err
+ }
+
+ st, err := s.AuthStore().GenTokenPrefix()
+ if err != nil {
+ return nil, err
+ }
+
+ internalReq := &pb.InternalAuthenticateRequest{
+ Name: r.Name,
+ Password: r.Password,
+ SimpleToken: st,
+ }
+
+ resp, err = s.raftRequestOnce(ctx, pb.InternalRaftRequest{Authenticate: internalReq})
+ if err != nil {
+ return nil, err
+ }
+ if checkedRevision == s.AuthStore().Revision() {
+ break
+ }
+ plog.Infof("revision when password checked is obsolete, retrying")
+ }
+
+ return resp.(*pb.AuthenticateResponse), nil
+}
+
+func (s *EtcdServer) UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthUserAdd: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthUserAddResponse), nil
+}
+
+func (s *EtcdServer) UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthUserDelete: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthUserDeleteResponse), nil
+}
+
+func (s *EtcdServer) UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthUserChangePassword: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthUserChangePasswordResponse), nil
+}
+
+func (s *EtcdServer) UserGrantRole(ctx context.Context, r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthUserGrantRole: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthUserGrantRoleResponse), nil
+}
+
+func (s *EtcdServer) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthUserGet: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthUserGetResponse), nil
+}
+
+func (s *EtcdServer) UserList(ctx context.Context, r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthUserList: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthUserListResponse), nil
+}
+
+func (s *EtcdServer) UserRevokeRole(ctx context.Context, r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthUserRevokeRole: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthUserRevokeRoleResponse), nil
+}
+
+func (s *EtcdServer) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthRoleAdd: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthRoleAddResponse), nil
+}
+
+func (s *EtcdServer) RoleGrantPermission(ctx context.Context, r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthRoleGrantPermission: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthRoleGrantPermissionResponse), nil
+}
+
+func (s *EtcdServer) RoleGet(ctx context.Context, r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthRoleGet: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthRoleGetResponse), nil
+}
+
+func (s *EtcdServer) RoleList(ctx context.Context, r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthRoleList: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthRoleListResponse), nil
+}
+
+func (s *EtcdServer) RoleRevokePermission(ctx context.Context, r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthRoleRevokePermission: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthRoleRevokePermissionResponse), nil
+}
+
+func (s *EtcdServer) RoleDelete(ctx context.Context, r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) {
+ resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{AuthRoleDelete: r})
+ if err != nil {
+ return nil, err
+ }
+ return resp.(*pb.AuthRoleDeleteResponse), nil
+}
+
+func (s *EtcdServer) raftRequestOnce(ctx context.Context, r pb.InternalRaftRequest) (proto.Message, error) {
+ result, err := s.processInternalRaftRequestOnce(ctx, r)
+ if err != nil {
+ return nil, err
+ }
+ if result.err != nil {
+ return nil, result.err
+ }
+ return result.resp, nil
+}
+
+func (s *EtcdServer) raftRequest(ctx context.Context, r pb.InternalRaftRequest) (proto.Message, error) {
+ for {
+ resp, err := s.raftRequestOnce(ctx, r)
+ if err != auth.ErrAuthOldRevision {
+ return resp, err
+ }
+ }
+}
+
+// doSerialize handles the auth logic, with permissions checked by "chk", for a serialized request "get". Returns a non-nil error on authentication failure.
+func (s *EtcdServer) doSerialize(ctx context.Context, chk func(*auth.AuthInfo) error, get func()) error {
+ for {
+ ai, err := s.AuthInfoFromCtx(ctx)
+ if err != nil {
+ return err
+ }
+ if ai == nil {
+ // chk expects non-nil AuthInfo; use empty credentials
+ ai = &auth.AuthInfo{}
+ }
+ if err = chk(ai); err != nil {
+ if err == auth.ErrAuthOldRevision {
+ continue
+ }
+ return err
+ }
+ // fetch response for serialized request
+ get()
+ // empty credentials or current auth info means no need to retry
+ if ai.Revision == 0 || ai.Revision == s.authStore.Revision() {
+ return nil
+ }
+ // avoid TOCTOU error, retry of the request is required.
+ }
+}
+
+func (s *EtcdServer) processInternalRaftRequestOnce(ctx context.Context, r pb.InternalRaftRequest) (*applyResult, error) {
+ ai := s.getAppliedIndex()
+ ci := s.getCommittedIndex()
+ if ci > ai+maxGapBetweenApplyAndCommitIndex {
+ return nil, ErrTooManyRequests
+ }
+
+ r.Header = &pb.RequestHeader{
+ ID: s.reqIDGen.Next(),
+ }
+
+ authInfo, err := s.AuthInfoFromCtx(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if authInfo != nil {
+ r.Header.Username = authInfo.Username
+ r.Header.AuthRevision = authInfo.Revision
+ }
+
+ data, err := r.Marshal()
+ if err != nil {
+ return nil, err
+ }
+
+ if len(data) > int(s.Cfg.MaxRequestBytes) {
+ return nil, ErrRequestTooLarge
+ }
+
+ id := r.ID
+ if id == 0 {
+ id = r.Header.ID
+ }
+ ch := s.w.Register(id)
+
+ cctx, cancel := context.WithTimeout(ctx, s.Cfg.ReqTimeout())
+ defer cancel()
+
+ start := time.Now()
+ s.r.Propose(cctx, data)
+ proposalsPending.Inc()
+ defer proposalsPending.Dec()
+
+ select {
+ case x := <-ch:
+ return x.(*applyResult), nil
+ case <-cctx.Done():
+ proposalsFailed.Inc()
+ s.w.Trigger(id, nil) // GC wait
+ return nil, s.parseProposeCtxErr(cctx.Err(), start)
+ case <-s.done:
+ return nil, ErrStopped
+ }
+}
+
+// Watchable returns a watchable interface attached to the etcdserver.
+func (s *EtcdServer) Watchable() mvcc.WatchableKV { return s.KV() }
+
+func (s *EtcdServer) linearizableReadLoop() {
+ var rs raft.ReadState
+
+ for {
+ ctxToSend := make([]byte, 8)
+ id1 := s.reqIDGen.Next()
+ binary.BigEndian.PutUint64(ctxToSend, id1)
+
+ select {
+ case <-s.readwaitc:
+ case <-s.stopping:
+ return
+ }
+
+ nextnr := newNotifier()
+
+ s.readMu.Lock()
+ nr := s.readNotifier
+ s.readNotifier = nextnr
+ s.readMu.Unlock()
+
+ cctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout())
+ if err := s.r.ReadIndex(cctx, ctxToSend); err != nil {
+ cancel()
+ if err == raft.ErrStopped {
+ return
+ }
+ plog.Errorf("failed to get read index from raft: %v", err)
+ nr.notify(err)
+ continue
+ }
+ cancel()
+
+ var (
+ timeout bool
+ done bool
+ )
+ for !timeout && !done {
+ select {
+ case rs = <-s.r.readStateC:
+ done = bytes.Equal(rs.RequestCtx, ctxToSend)
+ if !done {
+ // a previous request might time out. now we should ignore the response of it and
+ // continue waiting for the response of the current requests.
+ id2 := uint64(0)
+ if len(rs.RequestCtx) == 8 {
+ id2 = binary.BigEndian.Uint64(rs.RequestCtx)
+ }
+ plog.Warningf("ignored out-of-date read index response; local node read indexes queueing up and waiting to be in sync with leader (request ID want %d, got %d)", id1, id2)
+ slowReadIndex.Inc()
+ }
+
+ case <-time.After(s.Cfg.ReqTimeout()):
+ plog.Warningf("timed out waiting for read index response")
+ nr.notify(ErrTimeout)
+ timeout = true
+ slowReadIndex.Inc()
+
+ case <-s.stopping:
+ return
+ }
+ }
+ if !done {
+ continue
+ }
+
+ if ai := s.getAppliedIndex(); ai < rs.Index {
+ select {
+ case <-s.applyWait.Wait(rs.Index):
+ case <-s.stopping:
+ return
+ }
+ }
+ // unblock all l-reads requested at indices before rs.Index
+ nr.notify(nil)
+ }
+}
+
+func (s *EtcdServer) linearizableReadNotify(ctx context.Context) error {
+ s.readMu.RLock()
+ nc := s.readNotifier
+ s.readMu.RUnlock()
+
+ // signal linearizable loop for current notify if it hasn't been already
+ select {
+ case s.readwaitc <- struct{}{}:
+ default:
+ }
+
+ // wait for read state notification
+ select {
+ case <-nc.c:
+ return nc.err
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-s.done:
+ return ErrStopped
+ }
+}
+
+func (s *EtcdServer) AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) {
+ authInfo, err := s.AuthStore().AuthInfoFromCtx(ctx)
+ if authInfo != nil || err != nil {
+ return authInfo, err
+ }
+ if !s.Cfg.ClientCertAuthEnabled {
+ return nil, nil
+ }
+ authInfo = s.AuthStore().AuthInfoFromTLS(ctx)
+ return authInfo, nil
+}
diff --git a/vendor/github.com/coreos/etcd/lease/doc.go b/vendor/github.com/coreos/etcd/lease/doc.go
new file mode 100644
index 00000000..a74eaf76
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/lease/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package lease provides an interface and implementation for time-limited leases over arbitrary resources.
+package lease
diff --git a/vendor/github.com/coreos/etcd/lease/leasehttp/doc.go b/vendor/github.com/coreos/etcd/lease/leasehttp/doc.go
new file mode 100644
index 00000000..8177a37b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/lease/leasehttp/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package leasehttp serves lease renewals made through HTTP requests.
+package leasehttp
diff --git a/vendor/github.com/coreos/etcd/lease/leasehttp/http.go b/vendor/github.com/coreos/etcd/lease/leasehttp/http.go
new file mode 100644
index 00000000..ac2e7880
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/lease/leasehttp/http.go
@@ -0,0 +1,247 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package leasehttp
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "time"
+
+ pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/lease/leasepb"
+ "github.com/coreos/etcd/pkg/httputil"
+)
+
+var (
+ LeasePrefix = "/leases"
+ LeaseInternalPrefix = "/leases/internal"
+ applyTimeout = time.Second
+ ErrLeaseHTTPTimeout = errors.New("waiting for node to catch up its applied index has timed out")
+)
+
+// NewHandler returns an http Handler for lease renewals
+func NewHandler(l lease.Lessor, waitch func() <-chan struct{}) http.Handler {
+ return &leaseHandler{l, waitch}
+}
+
+type leaseHandler struct {
+ l lease.Lessor
+ waitch func() <-chan struct{}
+}
+
+func (h *leaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "POST" {
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ b, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ http.Error(w, "error reading body", http.StatusBadRequest)
+ return
+ }
+
+ var v []byte
+ switch r.URL.Path {
+ case LeasePrefix:
+ lreq := pb.LeaseKeepAliveRequest{}
+ if err := lreq.Unmarshal(b); err != nil {
+ http.Error(w, "error unmarshalling request", http.StatusBadRequest)
+ return
+ }
+ select {
+ case <-h.waitch():
+ case <-time.After(applyTimeout):
+ http.Error(w, ErrLeaseHTTPTimeout.Error(), http.StatusRequestTimeout)
+ return
+ }
+ ttl, err := h.l.Renew(lease.LeaseID(lreq.ID))
+ if err != nil {
+ if err == lease.ErrLeaseNotFound {
+ http.Error(w, err.Error(), http.StatusNotFound)
+ return
+ }
+
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+ // TODO: fill out ResponseHeader
+ resp := &pb.LeaseKeepAliveResponse{ID: lreq.ID, TTL: ttl}
+ v, err = resp.Marshal()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ case LeaseInternalPrefix:
+ lreq := leasepb.LeaseInternalRequest{}
+ if err := lreq.Unmarshal(b); err != nil {
+ http.Error(w, "error unmarshalling request", http.StatusBadRequest)
+ return
+ }
+ select {
+ case <-h.waitch():
+ case <-time.After(applyTimeout):
+ http.Error(w, ErrLeaseHTTPTimeout.Error(), http.StatusRequestTimeout)
+ return
+ }
+ l := h.l.Lookup(lease.LeaseID(lreq.LeaseTimeToLiveRequest.ID))
+ if l == nil {
+ http.Error(w, lease.ErrLeaseNotFound.Error(), http.StatusNotFound)
+ return
+ }
+ // TODO: fill out ResponseHeader
+ resp := &leasepb.LeaseInternalResponse{
+ LeaseTimeToLiveResponse: &pb.LeaseTimeToLiveResponse{
+ Header: &pb.ResponseHeader{},
+ ID: lreq.LeaseTimeToLiveRequest.ID,
+ TTL: int64(l.Remaining().Seconds()),
+ GrantedTTL: l.TTL(),
+ },
+ }
+ if lreq.LeaseTimeToLiveRequest.Keys {
+ ks := l.Keys()
+ kbs := make([][]byte, len(ks))
+ for i := range ks {
+ kbs[i] = []byte(ks[i])
+ }
+ resp.LeaseTimeToLiveResponse.Keys = kbs
+ }
+
+ v, err = resp.Marshal()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ default:
+ http.Error(w, fmt.Sprintf("unknown request path %q", r.URL.Path), http.StatusBadRequest)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/protobuf")
+ w.Write(v)
+}
+
+// RenewHTTP renews a lease at a given primary server.
+// TODO: Batch request in future?
+func RenewHTTP(ctx context.Context, id lease.LeaseID, url string, rt http.RoundTripper) (int64, error) {
+ // will post lreq protobuf to leader
+ lreq, err := (&pb.LeaseKeepAliveRequest{ID: int64(id)}).Marshal()
+ if err != nil {
+ return -1, err
+ }
+
+ cc := &http.Client{Transport: rt}
+ req, err := http.NewRequest("POST", url, bytes.NewReader(lreq))
+ if err != nil {
+ return -1, err
+ }
+ req.Header.Set("Content-Type", "application/protobuf")
+ req.Cancel = ctx.Done()
+
+ resp, err := cc.Do(req)
+ if err != nil {
+ return -1, err
+ }
+ b, err := readResponse(resp)
+ if err != nil {
+ return -1, err
+ }
+
+ if resp.StatusCode == http.StatusRequestTimeout {
+ return -1, ErrLeaseHTTPTimeout
+ }
+
+ if resp.StatusCode == http.StatusNotFound {
+ return -1, lease.ErrLeaseNotFound
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ return -1, fmt.Errorf("lease: unknown error(%s)", string(b))
+ }
+
+ lresp := &pb.LeaseKeepAliveResponse{}
+ if err := lresp.Unmarshal(b); err != nil {
+ return -1, fmt.Errorf(`lease: %v. data = "%s"`, err, string(b))
+ }
+ if lresp.ID != int64(id) {
+ return -1, fmt.Errorf("lease: renew id mismatch")
+ }
+ return lresp.TTL, nil
+}
+
+// TimeToLiveHTTP retrieves lease information of the given lease ID.
+func TimeToLiveHTTP(ctx context.Context, id lease.LeaseID, keys bool, url string, rt http.RoundTripper) (*leasepb.LeaseInternalResponse, error) {
+ // will post lreq protobuf to leader
+ lreq, err := (&leasepb.LeaseInternalRequest{
+ LeaseTimeToLiveRequest: &pb.LeaseTimeToLiveRequest{
+ ID: int64(id),
+ Keys: keys,
+ },
+ }).Marshal()
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("POST", url, bytes.NewReader(lreq))
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", "application/protobuf")
+
+ req = req.WithContext(ctx)
+
+ cc := &http.Client{Transport: rt}
+ var b []byte
+ // buffer errc channel so that errc don't block inside the go routinue
+ resp, err := cc.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ b, err = readResponse(resp)
+ if err != nil {
+ return nil, err
+ }
+ if resp.StatusCode == http.StatusRequestTimeout {
+ return nil, ErrLeaseHTTPTimeout
+ }
+ if resp.StatusCode == http.StatusNotFound {
+ return nil, lease.ErrLeaseNotFound
+ }
+ if resp.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("lease: unknown error(%s)", string(b))
+ }
+
+ lresp := &leasepb.LeaseInternalResponse{}
+ if err := lresp.Unmarshal(b); err != nil {
+ return nil, fmt.Errorf(`lease: %v. data = "%s"`, err, string(b))
+ }
+ if lresp.LeaseTimeToLiveResponse.ID != int64(id) {
+ return nil, fmt.Errorf("lease: renew id mismatch")
+ }
+ return lresp, nil
+}
+
+func readResponse(resp *http.Response) (b []byte, err error) {
+ b, err = ioutil.ReadAll(resp.Body)
+ httputil.GracefulClose(resp)
+ return
+}
diff --git a/vendor/github.com/coreos/etcd/lease/leasepb/lease.pb.go b/vendor/github.com/coreos/etcd/lease/leasepb/lease.pb.go
new file mode 100644
index 00000000..4ab93767
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/lease/leasepb/lease.pb.go
@@ -0,0 +1,591 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: lease.proto
+
+/*
+ Package leasepb is a generated protocol buffer package.
+
+ It is generated from these files:
+ lease.proto
+
+ It has these top-level messages:
+ Lease
+ LeaseInternalRequest
+ LeaseInternalResponse
+*/
+package leasepb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ etcdserverpb "github.com/coreos/etcd/etcdserver/etcdserverpb"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Lease struct {
+ ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ TTL int64 `protobuf:"varint,2,opt,name=TTL,proto3" json:"TTL,omitempty"`
+}
+
+func (m *Lease) Reset() { *m = Lease{} }
+func (m *Lease) String() string { return proto.CompactTextString(m) }
+func (*Lease) ProtoMessage() {}
+func (*Lease) Descriptor() ([]byte, []int) { return fileDescriptorLease, []int{0} }
+
+type LeaseInternalRequest struct {
+ LeaseTimeToLiveRequest *etcdserverpb.LeaseTimeToLiveRequest `protobuf:"bytes,1,opt,name=LeaseTimeToLiveRequest" json:"LeaseTimeToLiveRequest,omitempty"`
+}
+
+func (m *LeaseInternalRequest) Reset() { *m = LeaseInternalRequest{} }
+func (m *LeaseInternalRequest) String() string { return proto.CompactTextString(m) }
+func (*LeaseInternalRequest) ProtoMessage() {}
+func (*LeaseInternalRequest) Descriptor() ([]byte, []int) { return fileDescriptorLease, []int{1} }
+
+type LeaseInternalResponse struct {
+ LeaseTimeToLiveResponse *etcdserverpb.LeaseTimeToLiveResponse `protobuf:"bytes,1,opt,name=LeaseTimeToLiveResponse" json:"LeaseTimeToLiveResponse,omitempty"`
+}
+
+func (m *LeaseInternalResponse) Reset() { *m = LeaseInternalResponse{} }
+func (m *LeaseInternalResponse) String() string { return proto.CompactTextString(m) }
+func (*LeaseInternalResponse) ProtoMessage() {}
+func (*LeaseInternalResponse) Descriptor() ([]byte, []int) { return fileDescriptorLease, []int{2} }
+
+func init() {
+ proto.RegisterType((*Lease)(nil), "leasepb.Lease")
+ proto.RegisterType((*LeaseInternalRequest)(nil), "leasepb.LeaseInternalRequest")
+ proto.RegisterType((*LeaseInternalResponse)(nil), "leasepb.LeaseInternalResponse")
+}
+func (m *Lease) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Lease) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.ID != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintLease(dAtA, i, uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintLease(dAtA, i, uint64(m.TTL))
+ }
+ return i, nil
+}
+
+func (m *LeaseInternalRequest) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseInternalRequest) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.LeaseTimeToLiveRequest != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintLease(dAtA, i, uint64(m.LeaseTimeToLiveRequest.Size()))
+ n1, err := m.LeaseTimeToLiveRequest.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ }
+ return i, nil
+}
+
+func (m *LeaseInternalResponse) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *LeaseInternalResponse) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.LeaseTimeToLiveResponse != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintLease(dAtA, i, uint64(m.LeaseTimeToLiveResponse.Size()))
+ n2, err := m.LeaseTimeToLiveResponse.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n2
+ }
+ return i, nil
+}
+
+func encodeVarintLease(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Lease) Size() (n int) {
+ var l int
+ _ = l
+ if m.ID != 0 {
+ n += 1 + sovLease(uint64(m.ID))
+ }
+ if m.TTL != 0 {
+ n += 1 + sovLease(uint64(m.TTL))
+ }
+ return n
+}
+
+func (m *LeaseInternalRequest) Size() (n int) {
+ var l int
+ _ = l
+ if m.LeaseTimeToLiveRequest != nil {
+ l = m.LeaseTimeToLiveRequest.Size()
+ n += 1 + l + sovLease(uint64(l))
+ }
+ return n
+}
+
+func (m *LeaseInternalResponse) Size() (n int) {
+ var l int
+ _ = l
+ if m.LeaseTimeToLiveResponse != nil {
+ l = m.LeaseTimeToLiveResponse.Size()
+ n += 1 + l + sovLease(uint64(l))
+ }
+ return n
+}
+
+func sovLease(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozLease(x uint64) (n int) {
+ return sovLease(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Lease) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Lease: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Lease: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType)
+ }
+ m.TTL = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.TTL |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipLease(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthLease
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseInternalRequest) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseInternalRequest: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseInternalRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LeaseTimeToLiveRequest", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthLease
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.LeaseTimeToLiveRequest == nil {
+ m.LeaseTimeToLiveRequest = &etcdserverpb.LeaseTimeToLiveRequest{}
+ }
+ if err := m.LeaseTimeToLiveRequest.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipLease(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthLease
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *LeaseInternalResponse) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: LeaseInternalResponse: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: LeaseInternalResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LeaseTimeToLiveResponse", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthLease
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.LeaseTimeToLiveResponse == nil {
+ m.LeaseTimeToLiveResponse = &etcdserverpb.LeaseTimeToLiveResponse{}
+ }
+ if err := m.LeaseTimeToLiveResponse.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipLease(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthLease
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipLease(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthLease
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowLease
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipLease(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthLease = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowLease = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("lease.proto", fileDescriptorLease) }
+
+var fileDescriptorLease = []byte{
+ // 233 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xce, 0x49, 0x4d, 0x2c,
+ 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x07, 0x73, 0x0a, 0x92, 0xa4, 0x44, 0xd2,
+ 0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x4a, 0x2d, 0xb5, 0x24, 0x39, 0x45,
+ 0x1f, 0x44, 0x14, 0xa7, 0x16, 0x95, 0xa5, 0x16, 0x21, 0x31, 0x0b, 0x92, 0xf4, 0x8b, 0x0a, 0x92,
+ 0x21, 0xea, 0x94, 0x34, 0xb9, 0x58, 0x7d, 0x40, 0x06, 0x09, 0xf1, 0x71, 0x31, 0x79, 0xba, 0x48,
+ 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0x31, 0x79, 0xba, 0x08, 0x09, 0x70, 0x31, 0x87, 0x84, 0xf8,
+ 0x48, 0x30, 0x81, 0x05, 0x40, 0x4c, 0xa5, 0x12, 0x2e, 0x11, 0xb0, 0x52, 0xcf, 0xbc, 0x92, 0xd4,
+ 0xa2, 0xbc, 0xc4, 0x9c, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0xa1, 0x18, 0x2e, 0x31, 0xb0,
+ 0x78, 0x48, 0x66, 0x6e, 0x6a, 0x48, 0xbe, 0x4f, 0x66, 0x59, 0x2a, 0x54, 0x06, 0x6c, 0x1a, 0xb7,
+ 0x91, 0x8a, 0x1e, 0xb2, 0xdd, 0x7a, 0xd8, 0xd5, 0x06, 0xe1, 0x30, 0x43, 0xa9, 0x82, 0x4b, 0x14,
+ 0xcd, 0xd6, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0xa1, 0x78, 0x2e, 0x71, 0x0c, 0x2d, 0x10, 0x29,
+ 0xa8, 0xbd, 0xaa, 0x04, 0xec, 0x85, 0x28, 0x0e, 0xc2, 0x65, 0x8a, 0x93, 0xc4, 0x89, 0x87, 0x72,
+ 0x0c, 0x17, 0x1e, 0xca, 0x31, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47,
+ 0x72, 0x8c, 0x33, 0x1e, 0xcb, 0x31, 0x24, 0xb1, 0x81, 0xc3, 0xce, 0x18, 0x10, 0x00, 0x00, 0xff,
+ 0xff, 0x9f, 0xf2, 0x42, 0xe0, 0x91, 0x01, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/lease/lessor.go b/vendor/github.com/coreos/etcd/lease/lessor.go
new file mode 100644
index 00000000..43f05035
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/lease/lessor.go
@@ -0,0 +1,680 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package lease
+
+import (
+ "encoding/binary"
+ "errors"
+ "math"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/lease/leasepb"
+ "github.com/coreos/etcd/mvcc/backend"
+)
+
+// NoLease is a special LeaseID representing the absence of a lease.
+const NoLease = LeaseID(0)
+
+// MaxLeaseTTL is the maximum lease TTL value
+const MaxLeaseTTL = 9000000000
+
+var (
+ forever = time.Time{}
+
+ leaseBucketName = []byte("lease")
+
+ // maximum number of leases to revoke per second; configurable for tests
+ leaseRevokeRate = 1000
+
+ ErrNotPrimary = errors.New("not a primary lessor")
+ ErrLeaseNotFound = errors.New("lease not found")
+ ErrLeaseExists = errors.New("lease already exists")
+ ErrLeaseTTLTooLarge = errors.New("too large lease TTL")
+)
+
+// TxnDelete is a TxnWrite that only permits deletes. Defined here
+// to avoid circular dependency with mvcc.
+type TxnDelete interface {
+ DeleteRange(key, end []byte) (n, rev int64)
+ End()
+}
+
+// RangeDeleter is a TxnDelete constructor.
+type RangeDeleter func() TxnDelete
+
+type LeaseID int64
+
+// Lessor owns leases. It can grant, revoke, renew and modify leases for lessee.
+type Lessor interface {
+ // SetRangeDeleter lets the lessor create TxnDeletes to the store.
+ // Lessor deletes the items in the revoked or expired lease by creating
+ // new TxnDeletes.
+ SetRangeDeleter(rd RangeDeleter)
+
+ // Grant grants a lease that expires at least after TTL seconds.
+ Grant(id LeaseID, ttl int64) (*Lease, error)
+ // Revoke revokes a lease with given ID. The item attached to the
+ // given lease will be removed. If the ID does not exist, an error
+ // will be returned.
+ Revoke(id LeaseID) error
+
+ // Attach attaches given leaseItem to the lease with given LeaseID.
+ // If the lease does not exist, an error will be returned.
+ Attach(id LeaseID, items []LeaseItem) error
+
+ // GetLease returns LeaseID for given item.
+ // If no lease found, NoLease value will be returned.
+ GetLease(item LeaseItem) LeaseID
+
+ // Detach detaches given leaseItem from the lease with given LeaseID.
+ // If the lease does not exist, an error will be returned.
+ Detach(id LeaseID, items []LeaseItem) error
+
+ // Promote promotes the lessor to be the primary lessor. Primary lessor manages
+ // the expiration and renew of leases.
+ // Newly promoted lessor renew the TTL of all lease to extend + previous TTL.
+ Promote(extend time.Duration)
+
+ // Demote demotes the lessor from being the primary lessor.
+ Demote()
+
+ // Renew renews a lease with given ID. It returns the renewed TTL. If the ID does not exist,
+ // an error will be returned.
+ Renew(id LeaseID) (int64, error)
+
+ // Lookup gives the lease at a given lease id, if any
+ Lookup(id LeaseID) *Lease
+
+ // Leases lists all leases.
+ Leases() []*Lease
+
+ // ExpiredLeasesC returns a chan that is used to receive expired leases.
+ ExpiredLeasesC() <-chan []*Lease
+
+ // Recover recovers the lessor state from the given backend and RangeDeleter.
+ Recover(b backend.Backend, rd RangeDeleter)
+
+ // Stop stops the lessor for managing leases. The behavior of calling Stop multiple
+ // times is undefined.
+ Stop()
+}
+
+// lessor implements Lessor interface.
+// TODO: use clockwork for testability.
+type lessor struct {
+ mu sync.Mutex
+
+ // demotec is set when the lessor is the primary.
+ // demotec will be closed if the lessor is demoted.
+ demotec chan struct{}
+
+ // TODO: probably this should be a heap with a secondary
+ // id index.
+ // Now it is O(N) to loop over the leases to find expired ones.
+ // We want to make Grant, Revoke, and findExpiredLeases all O(logN) and
+ // Renew O(1).
+ // findExpiredLeases and Renew should be the most frequent operations.
+ leaseMap map[LeaseID]*Lease
+
+ itemMap map[LeaseItem]LeaseID
+
+ // When a lease expires, the lessor will delete the
+ // leased range (or key) by the RangeDeleter.
+ rd RangeDeleter
+
+ // backend to persist leases. We only persist lease ID and expiry for now.
+ // The leased items can be recovered by iterating all the keys in kv.
+ b backend.Backend
+
+ // minLeaseTTL is the minimum lease TTL that can be granted for a lease. Any
+ // requests for shorter TTLs are extended to the minimum TTL.
+ minLeaseTTL int64
+
+ expiredC chan []*Lease
+ // stopC is a channel whose closure indicates that the lessor should be stopped.
+ stopC chan struct{}
+ // doneC is a channel whose closure indicates that the lessor is stopped.
+ doneC chan struct{}
+}
+
+func NewLessor(b backend.Backend, minLeaseTTL int64) Lessor {
+ return newLessor(b, minLeaseTTL)
+}
+
+func newLessor(b backend.Backend, minLeaseTTL int64) *lessor {
+ l := &lessor{
+ leaseMap: make(map[LeaseID]*Lease),
+ itemMap: make(map[LeaseItem]LeaseID),
+ b: b,
+ minLeaseTTL: minLeaseTTL,
+ // expiredC is a small buffered chan to avoid unnecessary blocking.
+ expiredC: make(chan []*Lease, 16),
+ stopC: make(chan struct{}),
+ doneC: make(chan struct{}),
+ }
+ l.initAndRecover()
+
+ go l.runLoop()
+
+ return l
+}
+
+// isPrimary indicates if this lessor is the primary lessor. The primary
+// lessor manages lease expiration and renew.
+//
+// in etcd, raft leader is the primary. Thus there might be two primary
+// leaders at the same time (raft allows concurrent leader but with different term)
+// for at most a leader election timeout.
+// The old primary leader cannot affect the correctness since its proposal has a
+// smaller term and will not be committed.
+//
+// TODO: raft follower do not forward lease management proposals. There might be a
+// very small window (within second normally which depends on go scheduling) that
+// a raft follow is the primary between the raft leader demotion and lessor demotion.
+// Usually this should not be a problem. Lease should not be that sensitive to timing.
+func (le *lessor) isPrimary() bool {
+ return le.demotec != nil
+}
+
+func (le *lessor) SetRangeDeleter(rd RangeDeleter) {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ le.rd = rd
+}
+
+func (le *lessor) Grant(id LeaseID, ttl int64) (*Lease, error) {
+ if id == NoLease {
+ return nil, ErrLeaseNotFound
+ }
+
+ if ttl > MaxLeaseTTL {
+ return nil, ErrLeaseTTLTooLarge
+ }
+
+ // TODO: when lessor is under high load, it should give out lease
+ // with longer TTL to reduce renew load.
+ l := &Lease{
+ ID: id,
+ ttl: ttl,
+ itemSet: make(map[LeaseItem]struct{}),
+ revokec: make(chan struct{}),
+ }
+
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ if _, ok := le.leaseMap[id]; ok {
+ return nil, ErrLeaseExists
+ }
+
+ if l.ttl < le.minLeaseTTL {
+ l.ttl = le.minLeaseTTL
+ }
+
+ if le.isPrimary() {
+ l.refresh(0)
+ } else {
+ l.forever()
+ }
+
+ le.leaseMap[id] = l
+ l.persistTo(le.b)
+
+ return l, nil
+}
+
+func (le *lessor) Revoke(id LeaseID) error {
+ le.mu.Lock()
+
+ l := le.leaseMap[id]
+ if l == nil {
+ le.mu.Unlock()
+ return ErrLeaseNotFound
+ }
+ defer close(l.revokec)
+ // unlock before doing external work
+ le.mu.Unlock()
+
+ if le.rd == nil {
+ return nil
+ }
+
+ txn := le.rd()
+
+ // sort keys so deletes are in same order among all members,
+ // otherwise the backened hashes will be different
+ keys := l.Keys()
+ sort.StringSlice(keys).Sort()
+ for _, key := range keys {
+ txn.DeleteRange([]byte(key), nil)
+ }
+
+ le.mu.Lock()
+ defer le.mu.Unlock()
+ delete(le.leaseMap, l.ID)
+ // lease deletion needs to be in the same backend transaction with the
+ // kv deletion. Or we might end up with not executing the revoke or not
+ // deleting the keys if etcdserver fails in between.
+ le.b.BatchTx().UnsafeDelete(leaseBucketName, int64ToBytes(int64(l.ID)))
+
+ txn.End()
+ return nil
+}
+
+// Renew renews an existing lease. If the given lease does not exist or
+// has expired, an error will be returned.
+func (le *lessor) Renew(id LeaseID) (int64, error) {
+ le.mu.Lock()
+
+ unlock := func() { le.mu.Unlock() }
+ defer func() { unlock() }()
+
+ if !le.isPrimary() {
+ // forward renew request to primary instead of returning error.
+ return -1, ErrNotPrimary
+ }
+
+ demotec := le.demotec
+
+ l := le.leaseMap[id]
+ if l == nil {
+ return -1, ErrLeaseNotFound
+ }
+
+ if l.expired() {
+ le.mu.Unlock()
+ unlock = func() {}
+ select {
+ // A expired lease might be pending for revoking or going through
+ // quorum to be revoked. To be accurate, renew request must wait for the
+ // deletion to complete.
+ case <-l.revokec:
+ return -1, ErrLeaseNotFound
+ // The expired lease might fail to be revoked if the primary changes.
+ // The caller will retry on ErrNotPrimary.
+ case <-demotec:
+ return -1, ErrNotPrimary
+ case <-le.stopC:
+ return -1, ErrNotPrimary
+ }
+ }
+
+ l.refresh(0)
+ return l.ttl, nil
+}
+
+func (le *lessor) Lookup(id LeaseID) *Lease {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+ return le.leaseMap[id]
+}
+
+func (le *lessor) unsafeLeases() []*Lease {
+ leases := make([]*Lease, 0, len(le.leaseMap))
+ for _, l := range le.leaseMap {
+ leases = append(leases, l)
+ }
+ sort.Sort(leasesByExpiry(leases))
+ return leases
+}
+
+func (le *lessor) Leases() []*Lease {
+ le.mu.Lock()
+ ls := le.unsafeLeases()
+ le.mu.Unlock()
+ return ls
+}
+
+func (le *lessor) Promote(extend time.Duration) {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ le.demotec = make(chan struct{})
+
+ // refresh the expiries of all leases.
+ for _, l := range le.leaseMap {
+ l.refresh(extend)
+ }
+
+ if len(le.leaseMap) < leaseRevokeRate {
+ // no possibility of lease pile-up
+ return
+ }
+
+ // adjust expiries in case of overlap
+ leases := le.unsafeLeases()
+
+ baseWindow := leases[0].Remaining()
+ nextWindow := baseWindow + time.Second
+ expires := 0
+ // have fewer expires than the total revoke rate so piled up leases
+ // don't consume the entire revoke limit
+ targetExpiresPerSecond := (3 * leaseRevokeRate) / 4
+ for _, l := range leases {
+ remaining := l.Remaining()
+ if remaining > nextWindow {
+ baseWindow = remaining
+ nextWindow = baseWindow + time.Second
+ expires = 1
+ continue
+ }
+ expires++
+ if expires <= targetExpiresPerSecond {
+ continue
+ }
+ rateDelay := float64(time.Second) * (float64(expires) / float64(targetExpiresPerSecond))
+ // If leases are extended by n seconds, leases n seconds ahead of the
+ // base window should be extended by only one second.
+ rateDelay -= float64(remaining - baseWindow)
+ delay := time.Duration(rateDelay)
+ nextWindow = baseWindow + delay
+ l.refresh(delay + extend)
+ }
+}
+
+type leasesByExpiry []*Lease
+
+func (le leasesByExpiry) Len() int { return len(le) }
+func (le leasesByExpiry) Less(i, j int) bool { return le[i].Remaining() < le[j].Remaining() }
+func (le leasesByExpiry) Swap(i, j int) { le[i], le[j] = le[j], le[i] }
+
+func (le *lessor) Demote() {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ // set the expiries of all leases to forever
+ for _, l := range le.leaseMap {
+ l.forever()
+ }
+
+ if le.demotec != nil {
+ close(le.demotec)
+ le.demotec = nil
+ }
+}
+
+// Attach attaches items to the lease with given ID. When the lease
+// expires, the attached items will be automatically removed.
+// If the given lease does not exist, an error will be returned.
+func (le *lessor) Attach(id LeaseID, items []LeaseItem) error {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ l := le.leaseMap[id]
+ if l == nil {
+ return ErrLeaseNotFound
+ }
+
+ l.mu.Lock()
+ for _, it := range items {
+ l.itemSet[it] = struct{}{}
+ le.itemMap[it] = id
+ }
+ l.mu.Unlock()
+ return nil
+}
+
+func (le *lessor) GetLease(item LeaseItem) LeaseID {
+ le.mu.Lock()
+ id := le.itemMap[item]
+ le.mu.Unlock()
+ return id
+}
+
+// Detach detaches items from the lease with given ID.
+// If the given lease does not exist, an error will be returned.
+func (le *lessor) Detach(id LeaseID, items []LeaseItem) error {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ l := le.leaseMap[id]
+ if l == nil {
+ return ErrLeaseNotFound
+ }
+
+ l.mu.Lock()
+ for _, it := range items {
+ delete(l.itemSet, it)
+ delete(le.itemMap, it)
+ }
+ l.mu.Unlock()
+ return nil
+}
+
+func (le *lessor) Recover(b backend.Backend, rd RangeDeleter) {
+ le.mu.Lock()
+ defer le.mu.Unlock()
+
+ le.b = b
+ le.rd = rd
+ le.leaseMap = make(map[LeaseID]*Lease)
+ le.itemMap = make(map[LeaseItem]LeaseID)
+ le.initAndRecover()
+}
+
+func (le *lessor) ExpiredLeasesC() <-chan []*Lease {
+ return le.expiredC
+}
+
+func (le *lessor) Stop() {
+ close(le.stopC)
+ <-le.doneC
+}
+
+func (le *lessor) runLoop() {
+ defer close(le.doneC)
+
+ for {
+ var ls []*Lease
+
+ // rate limit
+ revokeLimit := leaseRevokeRate / 2
+
+ le.mu.Lock()
+ if le.isPrimary() {
+ ls = le.findExpiredLeases(revokeLimit)
+ }
+ le.mu.Unlock()
+
+ if len(ls) != 0 {
+ select {
+ case <-le.stopC:
+ return
+ case le.expiredC <- ls:
+ default:
+ // the receiver of expiredC is probably busy handling
+ // other stuff
+ // let's try this next time after 500ms
+ }
+ }
+
+ select {
+ case <-time.After(500 * time.Millisecond):
+ case <-le.stopC:
+ return
+ }
+ }
+}
+
+// findExpiredLeases loops leases in the leaseMap until reaching expired limit
+// and returns the expired leases that needed to be revoked.
+func (le *lessor) findExpiredLeases(limit int) []*Lease {
+ leases := make([]*Lease, 0, 16)
+
+ for _, l := range le.leaseMap {
+ // TODO: probably should change to <= 100-500 millisecond to
+ // make up committing latency.
+ if l.expired() {
+ leases = append(leases, l)
+
+ // reach expired limit
+ if len(leases) == limit {
+ break
+ }
+ }
+ }
+
+ return leases
+}
+
+func (le *lessor) initAndRecover() {
+ tx := le.b.BatchTx()
+ tx.Lock()
+
+ tx.UnsafeCreateBucket(leaseBucketName)
+ _, vs := tx.UnsafeRange(leaseBucketName, int64ToBytes(0), int64ToBytes(math.MaxInt64), 0)
+ // TODO: copy vs and do decoding outside tx lock if lock contention becomes an issue.
+ for i := range vs {
+ var lpb leasepb.Lease
+ err := lpb.Unmarshal(vs[i])
+ if err != nil {
+ tx.Unlock()
+ panic("failed to unmarshal lease proto item")
+ }
+ ID := LeaseID(lpb.ID)
+ if lpb.TTL < le.minLeaseTTL {
+ lpb.TTL = le.minLeaseTTL
+ }
+ le.leaseMap[ID] = &Lease{
+ ID: ID,
+ ttl: lpb.TTL,
+ // itemSet will be filled in when recover key-value pairs
+ // set expiry to forever, refresh when promoted
+ itemSet: make(map[LeaseItem]struct{}),
+ expiry: forever,
+ revokec: make(chan struct{}),
+ }
+ }
+ tx.Unlock()
+
+ le.b.ForceCommit()
+}
+
+type Lease struct {
+ ID LeaseID
+ ttl int64 // time to live in seconds
+ // expiryMu protects concurrent accesses to expiry
+ expiryMu sync.RWMutex
+ // expiry is time when lease should expire. no expiration when expiry.IsZero() is true
+ expiry time.Time
+
+ // mu protects concurrent accesses to itemSet
+ mu sync.RWMutex
+ itemSet map[LeaseItem]struct{}
+ revokec chan struct{}
+}
+
+func (l *Lease) expired() bool {
+ return l.Remaining() <= 0
+}
+
+func (l *Lease) persistTo(b backend.Backend) {
+ key := int64ToBytes(int64(l.ID))
+
+ lpb := leasepb.Lease{ID: int64(l.ID), TTL: int64(l.ttl)}
+ val, err := lpb.Marshal()
+ if err != nil {
+ panic("failed to marshal lease proto item")
+ }
+
+ b.BatchTx().Lock()
+ b.BatchTx().UnsafePut(leaseBucketName, key, val)
+ b.BatchTx().Unlock()
+}
+
+// TTL returns the TTL of the Lease.
+func (l *Lease) TTL() int64 {
+ return l.ttl
+}
+
+// refresh refreshes the expiry of the lease.
+func (l *Lease) refresh(extend time.Duration) {
+ newExpiry := time.Now().Add(extend + time.Duration(l.ttl)*time.Second)
+ l.expiryMu.Lock()
+ defer l.expiryMu.Unlock()
+ l.expiry = newExpiry
+}
+
+// forever sets the expiry of lease to be forever.
+func (l *Lease) forever() {
+ l.expiryMu.Lock()
+ defer l.expiryMu.Unlock()
+ l.expiry = forever
+}
+
+// Keys returns all the keys attached to the lease.
+func (l *Lease) Keys() []string {
+ l.mu.RLock()
+ keys := make([]string, 0, len(l.itemSet))
+ for k := range l.itemSet {
+ keys = append(keys, k.Key)
+ }
+ l.mu.RUnlock()
+ return keys
+}
+
+// Remaining returns the remaining time of the lease.
+func (l *Lease) Remaining() time.Duration {
+ l.expiryMu.RLock()
+ defer l.expiryMu.RUnlock()
+ if l.expiry.IsZero() {
+ return time.Duration(math.MaxInt64)
+ }
+ return time.Until(l.expiry)
+}
+
+type LeaseItem struct {
+ Key string
+}
+
+func int64ToBytes(n int64) []byte {
+ bytes := make([]byte, 8)
+ binary.BigEndian.PutUint64(bytes, uint64(n))
+ return bytes
+}
+
+// FakeLessor is a fake implementation of Lessor interface.
+// Used for testing only.
+type FakeLessor struct{}
+
+func (fl *FakeLessor) SetRangeDeleter(dr RangeDeleter) {}
+
+func (fl *FakeLessor) Grant(id LeaseID, ttl int64) (*Lease, error) { return nil, nil }
+
+func (fl *FakeLessor) Revoke(id LeaseID) error { return nil }
+
+func (fl *FakeLessor) Attach(id LeaseID, items []LeaseItem) error { return nil }
+
+func (fl *FakeLessor) GetLease(item LeaseItem) LeaseID { return 0 }
+func (fl *FakeLessor) Detach(id LeaseID, items []LeaseItem) error { return nil }
+
+func (fl *FakeLessor) Promote(extend time.Duration) {}
+
+func (fl *FakeLessor) Demote() {}
+
+func (fl *FakeLessor) Renew(id LeaseID) (int64, error) { return 10, nil }
+
+func (fl *FakeLessor) Lookup(id LeaseID) *Lease { return nil }
+
+func (fl *FakeLessor) Leases() []*Lease { return nil }
+
+func (fl *FakeLessor) ExpiredLeasesC() <-chan []*Lease { return nil }
+
+func (fl *FakeLessor) Recover(b backend.Backend, rd RangeDeleter) {}
+
+func (fl *FakeLessor) Stop() {}
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/backend.go b/vendor/github.com/coreos/etcd/mvcc/backend/backend.go
new file mode 100644
index 00000000..f7d9e60c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/backend.go
@@ -0,0 +1,464 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package backend
+
+import (
+ "fmt"
+ "hash/crc32"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ bolt "github.com/coreos/bbolt"
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ defaultBatchLimit = 10000
+ defaultBatchInterval = 100 * time.Millisecond
+
+ defragLimit = 10000
+
+ // initialMmapSize is the initial size of the mmapped region. Setting this larger than
+ // the potential max db size can prevent writer from blocking reader.
+ // This only works for linux.
+ initialMmapSize = uint64(10 * 1024 * 1024 * 1024)
+
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "mvcc/backend")
+
+ // minSnapshotWarningTimeout is the minimum threshold to trigger a long running snapshot warning.
+ minSnapshotWarningTimeout = time.Duration(30 * time.Second)
+)
+
+type Backend interface {
+ ReadTx() ReadTx
+ BatchTx() BatchTx
+
+ Snapshot() Snapshot
+ Hash(ignores map[IgnoreKey]struct{}) (uint32, error)
+ // Size returns the current size of the backend.
+ Size() int64
+ // SizeInUse returns the current size of the backend logically in use.
+ // Since the backend can manage free space in a non-byte unit such as
+ // number of pages, the returned value can be not exactly accurate in bytes.
+ SizeInUse() int64
+ Defrag() error
+ ForceCommit()
+ Close() error
+}
+
+type Snapshot interface {
+ // Size gets the size of the snapshot.
+ Size() int64
+ // WriteTo writes the snapshot into the given writer.
+ WriteTo(w io.Writer) (n int64, err error)
+ // Close closes the snapshot.
+ Close() error
+}
+
+type backend struct {
+ // size and commits are used with atomic operations so they must be
+ // 64-bit aligned, otherwise 32-bit tests will crash
+
+ // size is the number of bytes in the backend
+ size int64
+
+ // sizeInUse is the number of bytes actually used in the backend
+ sizeInUse int64
+
+ // commits counts number of commits since start
+ commits int64
+
+ mu sync.RWMutex
+ db *bolt.DB
+
+ batchInterval time.Duration
+ batchLimit int
+ batchTx *batchTxBuffered
+
+ readTx *readTx
+
+ stopc chan struct{}
+ donec chan struct{}
+}
+
+type BackendConfig struct {
+ // Path is the file path to the backend file.
+ Path string
+ // BatchInterval is the maximum time before flushing the BatchTx.
+ BatchInterval time.Duration
+ // BatchLimit is the maximum puts before flushing the BatchTx.
+ BatchLimit int
+ // MmapSize is the number of bytes to mmap for the backend.
+ MmapSize uint64
+}
+
+func DefaultBackendConfig() BackendConfig {
+ return BackendConfig{
+ BatchInterval: defaultBatchInterval,
+ BatchLimit: defaultBatchLimit,
+ MmapSize: initialMmapSize,
+ }
+}
+
+func New(bcfg BackendConfig) Backend {
+ return newBackend(bcfg)
+}
+
+func NewDefaultBackend(path string) Backend {
+ bcfg := DefaultBackendConfig()
+ bcfg.Path = path
+ return newBackend(bcfg)
+}
+
+func newBackend(bcfg BackendConfig) *backend {
+ bopts := &bolt.Options{}
+ if boltOpenOptions != nil {
+ *bopts = *boltOpenOptions
+ }
+ bopts.InitialMmapSize = bcfg.mmapSize()
+
+ db, err := bolt.Open(bcfg.Path, 0600, bopts)
+ if err != nil {
+ plog.Panicf("cannot open database at %s (%v)", bcfg.Path, err)
+ }
+
+ // In future, may want to make buffering optional for low-concurrency systems
+ // or dynamically swap between buffered/non-buffered depending on workload.
+ b := &backend{
+ db: db,
+
+ batchInterval: bcfg.BatchInterval,
+ batchLimit: bcfg.BatchLimit,
+
+ readTx: &readTx{
+ buf: txReadBuffer{
+ txBuffer: txBuffer{make(map[string]*bucketBuffer)},
+ },
+ buckets: make(map[string]*bolt.Bucket),
+ },
+
+ stopc: make(chan struct{}),
+ donec: make(chan struct{}),
+ }
+ b.batchTx = newBatchTxBuffered(b)
+ go b.run()
+ return b
+}
+
+// BatchTx returns the current batch tx in coalescer. The tx can be used for read and
+// write operations. The write result can be retrieved within the same tx immediately.
+// The write result is isolated with other txs until the current one get committed.
+func (b *backend) BatchTx() BatchTx {
+ return b.batchTx
+}
+
+func (b *backend) ReadTx() ReadTx { return b.readTx }
+
+// ForceCommit forces the current batching tx to commit.
+func (b *backend) ForceCommit() {
+ b.batchTx.Commit()
+}
+
+func (b *backend) Snapshot() Snapshot {
+ b.batchTx.Commit()
+
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ tx, err := b.db.Begin(false)
+ if err != nil {
+ plog.Fatalf("cannot begin tx (%s)", err)
+ }
+
+ stopc, donec := make(chan struct{}), make(chan struct{})
+ dbBytes := tx.Size()
+ go func() {
+ defer close(donec)
+ // sendRateBytes is based on transferring snapshot data over a 1 gigabit/s connection
+ // assuming a min tcp throughput of 100MB/s.
+ var sendRateBytes int64 = 100 * 1024 * 1014
+ warningTimeout := time.Duration(int64((float64(dbBytes) / float64(sendRateBytes)) * float64(time.Second)))
+ if warningTimeout < minSnapshotWarningTimeout {
+ warningTimeout = minSnapshotWarningTimeout
+ }
+ start := time.Now()
+ ticker := time.NewTicker(warningTimeout)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ticker.C:
+ plog.Warningf("snapshotting is taking more than %v seconds to finish transferring %v MB [started at %v]", time.Since(start).Seconds(), float64(dbBytes)/float64(1024*1014), start)
+ case <-stopc:
+ snapshotDurations.Observe(time.Since(start).Seconds())
+ return
+ }
+ }
+ }()
+
+ return &snapshot{tx, stopc, donec}
+}
+
+type IgnoreKey struct {
+ Bucket string
+ Key string
+}
+
+func (b *backend) Hash(ignores map[IgnoreKey]struct{}) (uint32, error) {
+ h := crc32.New(crc32.MakeTable(crc32.Castagnoli))
+
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ err := b.db.View(func(tx *bolt.Tx) error {
+ c := tx.Cursor()
+ for next, _ := c.First(); next != nil; next, _ = c.Next() {
+ b := tx.Bucket(next)
+ if b == nil {
+ return fmt.Errorf("cannot get hash of bucket %s", string(next))
+ }
+ h.Write(next)
+ b.ForEach(func(k, v []byte) error {
+ bk := IgnoreKey{Bucket: string(next), Key: string(k)}
+ if _, ok := ignores[bk]; !ok {
+ h.Write(k)
+ h.Write(v)
+ }
+ return nil
+ })
+ }
+ return nil
+ })
+
+ if err != nil {
+ return 0, err
+ }
+
+ return h.Sum32(), nil
+}
+
+func (b *backend) Size() int64 {
+ return atomic.LoadInt64(&b.size)
+}
+
+func (b *backend) SizeInUse() int64 {
+ return atomic.LoadInt64(&b.sizeInUse)
+}
+
+func (b *backend) run() {
+ defer close(b.donec)
+ t := time.NewTimer(b.batchInterval)
+ defer t.Stop()
+ for {
+ select {
+ case <-t.C:
+ case <-b.stopc:
+ b.batchTx.CommitAndStop()
+ return
+ }
+ b.batchTx.Commit()
+ t.Reset(b.batchInterval)
+ }
+}
+
+func (b *backend) Close() error {
+ close(b.stopc)
+ <-b.donec
+ return b.db.Close()
+}
+
+// Commits returns total number of commits since start
+func (b *backend) Commits() int64 {
+ return atomic.LoadInt64(&b.commits)
+}
+
+func (b *backend) Defrag() error {
+ return b.defrag()
+}
+
+func (b *backend) defrag() error {
+ now := time.Now()
+
+ // TODO: make this non-blocking?
+ // lock batchTx to ensure nobody is using previous tx, and then
+ // close previous ongoing tx.
+ b.batchTx.Lock()
+ defer b.batchTx.Unlock()
+
+ // lock database after lock tx to avoid deadlock.
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ // block concurrent read requests while resetting tx
+ b.readTx.mu.Lock()
+ defer b.readTx.mu.Unlock()
+
+ b.batchTx.unsafeCommit(true)
+ b.batchTx.tx = nil
+
+ tmpdb, err := bolt.Open(b.db.Path()+".tmp", 0600, boltOpenOptions)
+ if err != nil {
+ return err
+ }
+
+ err = defragdb(b.db, tmpdb, defragLimit)
+
+ if err != nil {
+ tmpdb.Close()
+ os.RemoveAll(tmpdb.Path())
+ return err
+ }
+
+ dbp := b.db.Path()
+ tdbp := tmpdb.Path()
+
+ err = b.db.Close()
+ if err != nil {
+ plog.Fatalf("cannot close database (%s)", err)
+ }
+ err = tmpdb.Close()
+ if err != nil {
+ plog.Fatalf("cannot close database (%s)", err)
+ }
+ err = os.Rename(tdbp, dbp)
+ if err != nil {
+ plog.Fatalf("cannot rename database (%s)", err)
+ }
+
+ b.db, err = bolt.Open(dbp, 0600, boltOpenOptions)
+ if err != nil {
+ plog.Panicf("cannot open database at %s (%v)", dbp, err)
+ }
+ b.batchTx.tx, err = b.db.Begin(true)
+ if err != nil {
+ plog.Fatalf("cannot begin tx (%s)", err)
+ }
+
+ b.readTx.reset()
+ b.readTx.tx = b.unsafeBegin(false)
+
+ size := b.readTx.tx.Size()
+ db := b.db
+ atomic.StoreInt64(&b.size, size)
+ atomic.StoreInt64(&b.sizeInUse, size-(int64(db.Stats().FreePageN)*int64(db.Info().PageSize)))
+
+ took := time.Since(now)
+ defragDurations.Observe(took.Seconds())
+
+ return nil
+}
+
+func defragdb(odb, tmpdb *bolt.DB, limit int) error {
+ // open a tx on tmpdb for writes
+ tmptx, err := tmpdb.Begin(true)
+ if err != nil {
+ return err
+ }
+
+ // open a tx on old db for read
+ tx, err := odb.Begin(false)
+ if err != nil {
+ return err
+ }
+ defer tx.Rollback()
+
+ c := tx.Cursor()
+
+ count := 0
+ for next, _ := c.First(); next != nil; next, _ = c.Next() {
+ b := tx.Bucket(next)
+ if b == nil {
+ return fmt.Errorf("backend: cannot defrag bucket %s", string(next))
+ }
+
+ tmpb, berr := tmptx.CreateBucketIfNotExists(next)
+ if berr != nil {
+ return berr
+ }
+ tmpb.FillPercent = 0.9 // for seq write in for each
+
+ b.ForEach(func(k, v []byte) error {
+ count++
+ if count > limit {
+ err = tmptx.Commit()
+ if err != nil {
+ return err
+ }
+ tmptx, err = tmpdb.Begin(true)
+ if err != nil {
+ return err
+ }
+ tmpb = tmptx.Bucket(next)
+ tmpb.FillPercent = 0.9 // for seq write in for each
+
+ count = 0
+ }
+ return tmpb.Put(k, v)
+ })
+ }
+
+ return tmptx.Commit()
+}
+
+func (b *backend) begin(write bool) *bolt.Tx {
+ b.mu.RLock()
+ tx := b.unsafeBegin(write)
+ b.mu.RUnlock()
+
+ size := tx.Size()
+ db := tx.DB()
+ atomic.StoreInt64(&b.size, size)
+ atomic.StoreInt64(&b.sizeInUse, size-(int64(db.Stats().FreePageN)*int64(db.Info().PageSize)))
+
+ return tx
+}
+
+func (b *backend) unsafeBegin(write bool) *bolt.Tx {
+ tx, err := b.db.Begin(write)
+ if err != nil {
+ plog.Fatalf("cannot begin tx (%s)", err)
+ }
+ return tx
+}
+
+// NewTmpBackend creates a backend implementation for testing.
+func NewTmpBackend(batchInterval time.Duration, batchLimit int) (*backend, string) {
+ dir, err := ioutil.TempDir(os.TempDir(), "etcd_backend_test")
+ if err != nil {
+ plog.Fatal(err)
+ }
+ tmpPath := filepath.Join(dir, "database")
+ bcfg := DefaultBackendConfig()
+ bcfg.Path, bcfg.BatchInterval, bcfg.BatchLimit = tmpPath, batchInterval, batchLimit
+ return newBackend(bcfg), tmpPath
+}
+
+func NewDefaultTmpBackend() (*backend, string) {
+ return NewTmpBackend(defaultBatchInterval, defaultBatchLimit)
+}
+
+type snapshot struct {
+ *bolt.Tx
+ stopc chan struct{}
+ donec chan struct{}
+}
+
+func (s *snapshot) Close() error {
+ close(s.stopc)
+ <-s.donec
+ return s.Tx.Rollback()
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/batch_tx.go b/vendor/github.com/coreos/etcd/mvcc/backend/batch_tx.go
new file mode 100644
index 00000000..aed6893e
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/batch_tx.go
@@ -0,0 +1,254 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package backend
+
+import (
+ "bytes"
+ "math"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ bolt "github.com/coreos/bbolt"
+)
+
+type BatchTx interface {
+ ReadTx
+ UnsafeCreateBucket(name []byte)
+ UnsafePut(bucketName []byte, key []byte, value []byte)
+ UnsafeSeqPut(bucketName []byte, key []byte, value []byte)
+ UnsafeDelete(bucketName []byte, key []byte)
+ // Commit commits a previous tx and begins a new writable one.
+ Commit()
+ // CommitAndStop commits the previous tx and does not create a new one.
+ CommitAndStop()
+}
+
+type batchTx struct {
+ sync.Mutex
+ tx *bolt.Tx
+ backend *backend
+
+ pending int
+}
+
+func (t *batchTx) UnsafeCreateBucket(name []byte) {
+ _, err := t.tx.CreateBucket(name)
+ if err != nil && err != bolt.ErrBucketExists {
+ plog.Fatalf("cannot create bucket %s (%v)", name, err)
+ }
+ t.pending++
+}
+
+// UnsafePut must be called holding the lock on the tx.
+func (t *batchTx) UnsafePut(bucketName []byte, key []byte, value []byte) {
+ t.unsafePut(bucketName, key, value, false)
+}
+
+// UnsafeSeqPut must be called holding the lock on the tx.
+func (t *batchTx) UnsafeSeqPut(bucketName []byte, key []byte, value []byte) {
+ t.unsafePut(bucketName, key, value, true)
+}
+
+func (t *batchTx) unsafePut(bucketName []byte, key []byte, value []byte, seq bool) {
+ bucket := t.tx.Bucket(bucketName)
+ if bucket == nil {
+ plog.Fatalf("bucket %s does not exist", bucketName)
+ }
+ if seq {
+ // it is useful to increase fill percent when the workloads are mostly append-only.
+ // this can delay the page split and reduce space usage.
+ bucket.FillPercent = 0.9
+ }
+ if err := bucket.Put(key, value); err != nil {
+ plog.Fatalf("cannot put key into bucket (%v)", err)
+ }
+ t.pending++
+}
+
+// UnsafeRange must be called holding the lock on the tx.
+func (t *batchTx) UnsafeRange(bucketName, key, endKey []byte, limit int64) ([][]byte, [][]byte) {
+ bucket := t.tx.Bucket(bucketName)
+ if bucket == nil {
+ plog.Fatalf("bucket %s does not exist", bucketName)
+ }
+ return unsafeRange(bucket.Cursor(), key, endKey, limit)
+}
+
+func unsafeRange(c *bolt.Cursor, key, endKey []byte, limit int64) (keys [][]byte, vs [][]byte) {
+ if limit <= 0 {
+ limit = math.MaxInt64
+ }
+ var isMatch func(b []byte) bool
+ if len(endKey) > 0 {
+ isMatch = func(b []byte) bool { return bytes.Compare(b, endKey) < 0 }
+ } else {
+ isMatch = func(b []byte) bool { return bytes.Equal(b, key) }
+ limit = 1
+ }
+ for ck, cv := c.Seek(key); ck != nil && isMatch(ck); ck, cv = c.Next() {
+ vs = append(vs, cv)
+ keys = append(keys, ck)
+ if limit == int64(len(keys)) {
+ break
+ }
+ }
+ return keys, vs
+}
+
+// UnsafeDelete must be called holding the lock on the tx.
+func (t *batchTx) UnsafeDelete(bucketName []byte, key []byte) {
+ bucket := t.tx.Bucket(bucketName)
+ if bucket == nil {
+ plog.Fatalf("bucket %s does not exist", bucketName)
+ }
+ err := bucket.Delete(key)
+ if err != nil {
+ plog.Fatalf("cannot delete key from bucket (%v)", err)
+ }
+ t.pending++
+}
+
+// UnsafeForEach must be called holding the lock on the tx.
+func (t *batchTx) UnsafeForEach(bucketName []byte, visitor func(k, v []byte) error) error {
+ return unsafeForEach(t.tx, bucketName, visitor)
+}
+
+func unsafeForEach(tx *bolt.Tx, bucket []byte, visitor func(k, v []byte) error) error {
+ if b := tx.Bucket(bucket); b != nil {
+ return b.ForEach(visitor)
+ }
+ return nil
+}
+
+// Commit commits a previous tx and begins a new writable one.
+func (t *batchTx) Commit() {
+ t.Lock()
+ t.commit(false)
+ t.Unlock()
+}
+
+// CommitAndStop commits the previous tx and does not create a new one.
+func (t *batchTx) CommitAndStop() {
+ t.Lock()
+ t.commit(true)
+ t.Unlock()
+}
+
+func (t *batchTx) Unlock() {
+ if t.pending >= t.backend.batchLimit {
+ t.commit(false)
+ }
+ t.Mutex.Unlock()
+}
+
+func (t *batchTx) commit(stop bool) {
+ // commit the last tx
+ if t.tx != nil {
+ if t.pending == 0 && !stop {
+ return
+ }
+
+ start := time.Now()
+
+ // gofail: var beforeCommit struct{}
+ err := t.tx.Commit()
+ // gofail: var afterCommit struct{}
+
+ commitDurations.Observe(time.Since(start).Seconds())
+ atomic.AddInt64(&t.backend.commits, 1)
+
+ t.pending = 0
+ if err != nil {
+ plog.Fatalf("cannot commit tx (%s)", err)
+ }
+ }
+ if !stop {
+ t.tx = t.backend.begin(true)
+ }
+}
+
+type batchTxBuffered struct {
+ batchTx
+ buf txWriteBuffer
+}
+
+func newBatchTxBuffered(backend *backend) *batchTxBuffered {
+ tx := &batchTxBuffered{
+ batchTx: batchTx{backend: backend},
+ buf: txWriteBuffer{
+ txBuffer: txBuffer{make(map[string]*bucketBuffer)},
+ seq: true,
+ },
+ }
+ tx.Commit()
+ return tx
+}
+
+func (t *batchTxBuffered) Unlock() {
+ if t.pending != 0 {
+ t.backend.readTx.mu.Lock()
+ t.buf.writeback(&t.backend.readTx.buf)
+ t.backend.readTx.mu.Unlock()
+ if t.pending >= t.backend.batchLimit {
+ t.commit(false)
+ }
+ }
+ t.batchTx.Unlock()
+}
+
+func (t *batchTxBuffered) Commit() {
+ t.Lock()
+ t.commit(false)
+ t.Unlock()
+}
+
+func (t *batchTxBuffered) CommitAndStop() {
+ t.Lock()
+ t.commit(true)
+ t.Unlock()
+}
+
+func (t *batchTxBuffered) commit(stop bool) {
+ // all read txs must be closed to acquire boltdb commit rwlock
+ t.backend.readTx.mu.Lock()
+ t.unsafeCommit(stop)
+ t.backend.readTx.mu.Unlock()
+}
+
+func (t *batchTxBuffered) unsafeCommit(stop bool) {
+ if t.backend.readTx.tx != nil {
+ if err := t.backend.readTx.tx.Rollback(); err != nil {
+ plog.Fatalf("cannot rollback tx (%s)", err)
+ }
+ t.backend.readTx.reset()
+ }
+
+ t.batchTx.commit(stop)
+
+ if !stop {
+ t.backend.readTx.tx = t.backend.begin(false)
+ }
+}
+
+func (t *batchTxBuffered) UnsafePut(bucketName []byte, key []byte, value []byte) {
+ t.batchTx.UnsafePut(bucketName, key, value)
+ t.buf.put(bucketName, key, value)
+}
+
+func (t *batchTxBuffered) UnsafeSeqPut(bucketName []byte, key []byte, value []byte) {
+ t.batchTx.UnsafeSeqPut(bucketName, key, value)
+ t.buf.putSeq(bucketName, key, value)
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/config_default.go b/vendor/github.com/coreos/etcd/mvcc/backend/config_default.go
new file mode 100644
index 00000000..edfed002
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/config_default.go
@@ -0,0 +1,23 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !linux,!windows
+
+package backend
+
+import bolt "github.com/coreos/bbolt"
+
+var boltOpenOptions *bolt.Options = nil
+
+func (bcfg *BackendConfig) mmapSize() int { return int(bcfg.MmapSize) }
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/config_linux.go b/vendor/github.com/coreos/etcd/mvcc/backend/config_linux.go
new file mode 100644
index 00000000..b01785f3
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/config_linux.go
@@ -0,0 +1,34 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package backend
+
+import (
+ "syscall"
+
+ bolt "github.com/coreos/bbolt"
+)
+
+// syscall.MAP_POPULATE on linux 2.6.23+ does sequential read-ahead
+// which can speed up entire-database read with boltdb. We want to
+// enable MAP_POPULATE for faster key-value store recovery in storage
+// package. If your kernel version is lower than 2.6.23
+// (https://github.com/torvalds/linux/releases/tag/v2.6.23), mmap might
+// silently ignore this flag. Please update your kernel to prevent this.
+var boltOpenOptions = &bolt.Options{
+ MmapFlags: syscall.MAP_POPULATE,
+ NoFreelistSync: true,
+}
+
+func (bcfg *BackendConfig) mmapSize() int { return int(bcfg.MmapSize) }
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/config_windows.go b/vendor/github.com/coreos/etcd/mvcc/backend/config_windows.go
new file mode 100644
index 00000000..71d02700
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/config_windows.go
@@ -0,0 +1,26 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build windows
+
+package backend
+
+import bolt "github.com/coreos/bbolt"
+
+var boltOpenOptions *bolt.Options = nil
+
+// setting mmap size != 0 on windows will allocate the entire
+// mmap size for the file, instead of growing it. So, force 0.
+
+func (bcfg *BackendConfig) mmapSize() int { return 0 }
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/doc.go b/vendor/github.com/coreos/etcd/mvcc/backend/doc.go
new file mode 100644
index 00000000..9cc42fa7
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package backend defines a standard interface for etcd's backend MVCC storage.
+package backend
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/metrics.go b/vendor/github.com/coreos/etcd/mvcc/backend/metrics.go
new file mode 100644
index 00000000..34157080
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/metrics.go
@@ -0,0 +1,59 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package backend
+
+import "github.com/prometheus/client_golang/prometheus"
+
+var (
+ commitDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "disk",
+ Name: "backend_commit_duration_seconds",
+ Help: "The latency distributions of commit called by backend.",
+
+ // lowest bucket start of upper bound 0.001 sec (1 ms) with factor 2
+ // highest bucket start of 0.001 sec * 2^13 == 8.192 sec
+ Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
+ })
+
+ defragDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "disk",
+ Name: "backend_defrag_duration_seconds",
+ Help: "The latency distribution of backend defragmentation.",
+
+ // 100 MB usually takes 1 sec, so start with 10 MB of 100 ms
+ // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2
+ // highest bucket start of 0.1 sec * 2^12 == 409.6 sec
+ Buckets: prometheus.ExponentialBuckets(.1, 2, 13),
+ })
+
+ snapshotDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "disk",
+ Name: "backend_snapshot_duration_seconds",
+ Help: "The latency distribution of backend snapshots.",
+
+ // lowest bucket start of upper bound 0.01 sec (10 ms) with factor 2
+ // highest bucket start of 0.01 sec * 2^16 == 655.36 sec
+ Buckets: prometheus.ExponentialBuckets(.01, 2, 17),
+ })
+)
+
+func init() {
+ prometheus.MustRegister(commitDurations)
+ prometheus.MustRegister(defragDurations)
+ prometheus.MustRegister(snapshotDurations)
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/read_tx.go b/vendor/github.com/coreos/etcd/mvcc/backend/read_tx.go
new file mode 100644
index 00000000..0536de70
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/read_tx.go
@@ -0,0 +1,120 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package backend
+
+import (
+ "bytes"
+ "math"
+ "sync"
+
+ bolt "github.com/coreos/bbolt"
+)
+
+// safeRangeBucket is a hack to avoid inadvertently reading duplicate keys;
+// overwrites on a bucket should only fetch with limit=1, but safeRangeBucket
+// is known to never overwrite any key so range is safe.
+var safeRangeBucket = []byte("key")
+
+type ReadTx interface {
+ Lock()
+ Unlock()
+
+ UnsafeRange(bucketName []byte, key, endKey []byte, limit int64) (keys [][]byte, vals [][]byte)
+ UnsafeForEach(bucketName []byte, visitor func(k, v []byte) error) error
+}
+
+type readTx struct {
+ // mu protects accesses to the txReadBuffer
+ mu sync.RWMutex
+ buf txReadBuffer
+
+ // txmu protects accesses to buckets and tx on Range requests.
+ txmu sync.RWMutex
+ tx *bolt.Tx
+ buckets map[string]*bolt.Bucket
+}
+
+func (rt *readTx) Lock() { rt.mu.RLock() }
+func (rt *readTx) Unlock() { rt.mu.RUnlock() }
+
+func (rt *readTx) UnsafeRange(bucketName, key, endKey []byte, limit int64) ([][]byte, [][]byte) {
+ if endKey == nil {
+ // forbid duplicates for single keys
+ limit = 1
+ }
+ if limit <= 0 {
+ limit = math.MaxInt64
+ }
+ if limit > 1 && !bytes.Equal(bucketName, safeRangeBucket) {
+ panic("do not use unsafeRange on non-keys bucket")
+ }
+ keys, vals := rt.buf.Range(bucketName, key, endKey, limit)
+ if int64(len(keys)) == limit {
+ return keys, vals
+ }
+
+ // find/cache bucket
+ bn := string(bucketName)
+ rt.txmu.RLock()
+ bucket, ok := rt.buckets[bn]
+ rt.txmu.RUnlock()
+ if !ok {
+ rt.txmu.Lock()
+ bucket = rt.tx.Bucket(bucketName)
+ rt.buckets[bn] = bucket
+ rt.txmu.Unlock()
+ }
+
+ // ignore missing bucket since may have been created in this batch
+ if bucket == nil {
+ return keys, vals
+ }
+ rt.txmu.Lock()
+ c := bucket.Cursor()
+ rt.txmu.Unlock()
+
+ k2, v2 := unsafeRange(c, key, endKey, limit-int64(len(keys)))
+ return append(k2, keys...), append(v2, vals...)
+}
+
+func (rt *readTx) UnsafeForEach(bucketName []byte, visitor func(k, v []byte) error) error {
+ dups := make(map[string]struct{})
+ getDups := func(k, v []byte) error {
+ dups[string(k)] = struct{}{}
+ return nil
+ }
+ visitNoDup := func(k, v []byte) error {
+ if _, ok := dups[string(k)]; ok {
+ return nil
+ }
+ return visitor(k, v)
+ }
+ if err := rt.buf.ForEach(bucketName, getDups); err != nil {
+ return err
+ }
+ rt.txmu.Lock()
+ err := unsafeForEach(rt.tx, bucketName, visitNoDup)
+ rt.txmu.Unlock()
+ if err != nil {
+ return err
+ }
+ return rt.buf.ForEach(bucketName, visitor)
+}
+
+func (rt *readTx) reset() {
+ rt.buf.reset()
+ rt.buckets = make(map[string]*bolt.Bucket)
+ rt.tx = nil
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/backend/tx_buffer.go b/vendor/github.com/coreos/etcd/mvcc/backend/tx_buffer.go
new file mode 100644
index 00000000..56e885db
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/backend/tx_buffer.go
@@ -0,0 +1,181 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package backend
+
+import (
+ "bytes"
+ "sort"
+)
+
+// txBuffer handles functionality shared between txWriteBuffer and txReadBuffer.
+type txBuffer struct {
+ buckets map[string]*bucketBuffer
+}
+
+func (txb *txBuffer) reset() {
+ for k, v := range txb.buckets {
+ if v.used == 0 {
+ // demote
+ delete(txb.buckets, k)
+ }
+ v.used = 0
+ }
+}
+
+// txWriteBuffer buffers writes of pending updates that have not yet committed.
+type txWriteBuffer struct {
+ txBuffer
+ seq bool
+}
+
+func (txw *txWriteBuffer) put(bucket, k, v []byte) {
+ txw.seq = false
+ txw.putSeq(bucket, k, v)
+}
+
+func (txw *txWriteBuffer) putSeq(bucket, k, v []byte) {
+ b, ok := txw.buckets[string(bucket)]
+ if !ok {
+ b = newBucketBuffer()
+ txw.buckets[string(bucket)] = b
+ }
+ b.add(k, v)
+}
+
+func (txw *txWriteBuffer) writeback(txr *txReadBuffer) {
+ for k, wb := range txw.buckets {
+ rb, ok := txr.buckets[k]
+ if !ok {
+ delete(txw.buckets, k)
+ txr.buckets[k] = wb
+ continue
+ }
+ if !txw.seq && wb.used > 1 {
+ // assume no duplicate keys
+ sort.Sort(wb)
+ }
+ rb.merge(wb)
+ }
+ txw.reset()
+}
+
+// txReadBuffer accesses buffered updates.
+type txReadBuffer struct{ txBuffer }
+
+func (txr *txReadBuffer) Range(bucketName, key, endKey []byte, limit int64) ([][]byte, [][]byte) {
+ if b := txr.buckets[string(bucketName)]; b != nil {
+ return b.Range(key, endKey, limit)
+ }
+ return nil, nil
+}
+
+func (txr *txReadBuffer) ForEach(bucketName []byte, visitor func(k, v []byte) error) error {
+ if b := txr.buckets[string(bucketName)]; b != nil {
+ return b.ForEach(visitor)
+ }
+ return nil
+}
+
+type kv struct {
+ key []byte
+ val []byte
+}
+
+// bucketBuffer buffers key-value pairs that are pending commit.
+type bucketBuffer struct {
+ buf []kv
+ // used tracks number of elements in use so buf can be reused without reallocation.
+ used int
+}
+
+func newBucketBuffer() *bucketBuffer {
+ return &bucketBuffer{buf: make([]kv, 512), used: 0}
+}
+
+func (bb *bucketBuffer) Range(key, endKey []byte, limit int64) (keys [][]byte, vals [][]byte) {
+ f := func(i int) bool { return bytes.Compare(bb.buf[i].key, key) >= 0 }
+ idx := sort.Search(bb.used, f)
+ if idx < 0 {
+ return nil, nil
+ }
+ if len(endKey) == 0 {
+ if bytes.Equal(key, bb.buf[idx].key) {
+ keys = append(keys, bb.buf[idx].key)
+ vals = append(vals, bb.buf[idx].val)
+ }
+ return keys, vals
+ }
+ if bytes.Compare(endKey, bb.buf[idx].key) <= 0 {
+ return nil, nil
+ }
+ for i := idx; i < bb.used && int64(len(keys)) < limit; i++ {
+ if bytes.Compare(endKey, bb.buf[i].key) <= 0 {
+ break
+ }
+ keys = append(keys, bb.buf[i].key)
+ vals = append(vals, bb.buf[i].val)
+ }
+ return keys, vals
+}
+
+func (bb *bucketBuffer) ForEach(visitor func(k, v []byte) error) error {
+ for i := 0; i < bb.used; i++ {
+ if err := visitor(bb.buf[i].key, bb.buf[i].val); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (bb *bucketBuffer) add(k, v []byte) {
+ bb.buf[bb.used].key, bb.buf[bb.used].val = k, v
+ bb.used++
+ if bb.used == len(bb.buf) {
+ buf := make([]kv, (3*len(bb.buf))/2)
+ copy(buf, bb.buf)
+ bb.buf = buf
+ }
+}
+
+// merge merges data from bb into bbsrc.
+func (bb *bucketBuffer) merge(bbsrc *bucketBuffer) {
+ for i := 0; i < bbsrc.used; i++ {
+ bb.add(bbsrc.buf[i].key, bbsrc.buf[i].val)
+ }
+ if bb.used == bbsrc.used {
+ return
+ }
+ if bytes.Compare(bb.buf[(bb.used-bbsrc.used)-1].key, bbsrc.buf[0].key) < 0 {
+ return
+ }
+
+ sort.Stable(bb)
+
+ // remove duplicates, using only newest update
+ widx := 0
+ for ridx := 1; ridx < bb.used; ridx++ {
+ if !bytes.Equal(bb.buf[ridx].key, bb.buf[widx].key) {
+ widx++
+ }
+ bb.buf[widx] = bb.buf[ridx]
+ }
+ bb.used = widx + 1
+}
+
+func (bb *bucketBuffer) Len() int { return bb.used }
+func (bb *bucketBuffer) Less(i, j int) bool {
+ return bytes.Compare(bb.buf[i].key, bb.buf[j].key) < 0
+}
+func (bb *bucketBuffer) Swap(i, j int) { bb.buf[i], bb.buf[j] = bb.buf[j], bb.buf[i] }
diff --git a/vendor/github.com/coreos/etcd/mvcc/doc.go b/vendor/github.com/coreos/etcd/mvcc/doc.go
new file mode 100644
index 00000000..ad5be030
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package mvcc defines etcd's stable MVCC storage.
+package mvcc
diff --git a/vendor/github.com/coreos/etcd/mvcc/index.go b/vendor/github.com/coreos/etcd/mvcc/index.go
new file mode 100644
index 00000000..b27a9e54
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/index.go
@@ -0,0 +1,251 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "sort"
+ "sync"
+
+ "github.com/google/btree"
+)
+
+type index interface {
+ Get(key []byte, atRev int64) (rev, created revision, ver int64, err error)
+ Range(key, end []byte, atRev int64) ([][]byte, []revision)
+ Revisions(key, end []byte, atRev int64) []revision
+ Put(key []byte, rev revision)
+ Tombstone(key []byte, rev revision) error
+ RangeSince(key, end []byte, rev int64) []revision
+ Compact(rev int64) map[revision]struct{}
+ Keep(rev int64) map[revision]struct{}
+ Equal(b index) bool
+
+ Insert(ki *keyIndex)
+ KeyIndex(ki *keyIndex) *keyIndex
+}
+
+type treeIndex struct {
+ sync.RWMutex
+ tree *btree.BTree
+}
+
+func newTreeIndex() index {
+ return &treeIndex{
+ tree: btree.New(32),
+ }
+}
+
+func (ti *treeIndex) Put(key []byte, rev revision) {
+ keyi := &keyIndex{key: key}
+
+ ti.Lock()
+ defer ti.Unlock()
+ item := ti.tree.Get(keyi)
+ if item == nil {
+ keyi.put(rev.main, rev.sub)
+ ti.tree.ReplaceOrInsert(keyi)
+ return
+ }
+ okeyi := item.(*keyIndex)
+ okeyi.put(rev.main, rev.sub)
+}
+
+func (ti *treeIndex) Get(key []byte, atRev int64) (modified, created revision, ver int64, err error) {
+ keyi := &keyIndex{key: key}
+ ti.RLock()
+ defer ti.RUnlock()
+ if keyi = ti.keyIndex(keyi); keyi == nil {
+ return revision{}, revision{}, 0, ErrRevisionNotFound
+ }
+ return keyi.get(atRev)
+}
+
+func (ti *treeIndex) KeyIndex(keyi *keyIndex) *keyIndex {
+ ti.RLock()
+ defer ti.RUnlock()
+ return ti.keyIndex(keyi)
+}
+
+func (ti *treeIndex) keyIndex(keyi *keyIndex) *keyIndex {
+ if item := ti.tree.Get(keyi); item != nil {
+ return item.(*keyIndex)
+ }
+ return nil
+}
+
+func (ti *treeIndex) visit(key, end []byte, f func(ki *keyIndex)) {
+ keyi, endi := &keyIndex{key: key}, &keyIndex{key: end}
+
+ ti.RLock()
+ defer ti.RUnlock()
+
+ ti.tree.AscendGreaterOrEqual(keyi, func(item btree.Item) bool {
+ if len(endi.key) > 0 && !item.Less(endi) {
+ return false
+ }
+ f(item.(*keyIndex))
+ return true
+ })
+}
+
+func (ti *treeIndex) Revisions(key, end []byte, atRev int64) (revs []revision) {
+ if end == nil {
+ rev, _, _, err := ti.Get(key, atRev)
+ if err != nil {
+ return nil
+ }
+ return []revision{rev}
+ }
+ ti.visit(key, end, func(ki *keyIndex) {
+ if rev, _, _, err := ki.get(atRev); err == nil {
+ revs = append(revs, rev)
+ }
+ })
+ return revs
+}
+
+func (ti *treeIndex) Range(key, end []byte, atRev int64) (keys [][]byte, revs []revision) {
+ if end == nil {
+ rev, _, _, err := ti.Get(key, atRev)
+ if err != nil {
+ return nil, nil
+ }
+ return [][]byte{key}, []revision{rev}
+ }
+ ti.visit(key, end, func(ki *keyIndex) {
+ if rev, _, _, err := ki.get(atRev); err == nil {
+ revs = append(revs, rev)
+ keys = append(keys, ki.key)
+ }
+ })
+ return keys, revs
+}
+
+func (ti *treeIndex) Tombstone(key []byte, rev revision) error {
+ keyi := &keyIndex{key: key}
+
+ ti.Lock()
+ defer ti.Unlock()
+ item := ti.tree.Get(keyi)
+ if item == nil {
+ return ErrRevisionNotFound
+ }
+
+ ki := item.(*keyIndex)
+ return ki.tombstone(rev.main, rev.sub)
+}
+
+// RangeSince returns all revisions from key(including) to end(excluding)
+// at or after the given rev. The returned slice is sorted in the order
+// of revision.
+func (ti *treeIndex) RangeSince(key, end []byte, rev int64) []revision {
+ keyi := &keyIndex{key: key}
+
+ ti.RLock()
+ defer ti.RUnlock()
+
+ if end == nil {
+ item := ti.tree.Get(keyi)
+ if item == nil {
+ return nil
+ }
+ keyi = item.(*keyIndex)
+ return keyi.since(rev)
+ }
+
+ endi := &keyIndex{key: end}
+ var revs []revision
+ ti.tree.AscendGreaterOrEqual(keyi, func(item btree.Item) bool {
+ if len(endi.key) > 0 && !item.Less(endi) {
+ return false
+ }
+ curKeyi := item.(*keyIndex)
+ revs = append(revs, curKeyi.since(rev)...)
+ return true
+ })
+ sort.Sort(revisions(revs))
+
+ return revs
+}
+
+func (ti *treeIndex) Compact(rev int64) map[revision]struct{} {
+ available := make(map[revision]struct{})
+ var emptyki []*keyIndex
+ plog.Printf("store.index: compact %d", rev)
+ // TODO: do not hold the lock for long time?
+ // This is probably OK. Compacting 10M keys takes O(10ms).
+ ti.Lock()
+ defer ti.Unlock()
+ ti.tree.Ascend(compactIndex(rev, available, &emptyki))
+ for _, ki := range emptyki {
+ item := ti.tree.Delete(ki)
+ if item == nil {
+ plog.Panic("store.index: unexpected delete failure during compaction")
+ }
+ }
+ return available
+}
+
+// Keep finds all revisions to be kept for a Compaction at the given rev.
+func (ti *treeIndex) Keep(rev int64) map[revision]struct{} {
+ available := make(map[revision]struct{})
+ ti.RLock()
+ defer ti.RUnlock()
+ ti.tree.Ascend(func(i btree.Item) bool {
+ keyi := i.(*keyIndex)
+ keyi.keep(rev, available)
+ return true
+ })
+ return available
+}
+
+func compactIndex(rev int64, available map[revision]struct{}, emptyki *[]*keyIndex) func(i btree.Item) bool {
+ return func(i btree.Item) bool {
+ keyi := i.(*keyIndex)
+ keyi.compact(rev, available)
+ if keyi.isEmpty() {
+ *emptyki = append(*emptyki, keyi)
+ }
+ return true
+ }
+}
+
+func (ti *treeIndex) Equal(bi index) bool {
+ b := bi.(*treeIndex)
+
+ if ti.tree.Len() != b.tree.Len() {
+ return false
+ }
+
+ equal := true
+
+ ti.tree.Ascend(func(item btree.Item) bool {
+ aki := item.(*keyIndex)
+ bki := b.tree.Get(item).(*keyIndex)
+ if !aki.equal(bki) {
+ equal = false
+ return false
+ }
+ return true
+ })
+
+ return equal
+}
+
+func (ti *treeIndex) Insert(ki *keyIndex) {
+ ti.Lock()
+ defer ti.Unlock()
+ ti.tree.ReplaceOrInsert(ki)
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/key_index.go b/vendor/github.com/coreos/etcd/mvcc/key_index.go
new file mode 100644
index 00000000..805922bf
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/key_index.go
@@ -0,0 +1,356 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+
+ "github.com/google/btree"
+)
+
+var (
+ ErrRevisionNotFound = errors.New("mvcc: revision not found")
+)
+
+// keyIndex stores the revisions of a key in the backend.
+// Each keyIndex has at least one key generation.
+// Each generation might have several key versions.
+// Tombstone on a key appends an tombstone version at the end
+// of the current generation and creates a new empty generation.
+// Each version of a key has an index pointing to the backend.
+//
+// For example: put(1.0);put(2.0);tombstone(3.0);put(4.0);tombstone(5.0) on key "foo"
+// generate a keyIndex:
+// key: "foo"
+// rev: 5
+// generations:
+// {empty}
+// {4.0, 5.0(t)}
+// {1.0, 2.0, 3.0(t)}
+//
+// Compact a keyIndex removes the versions with smaller or equal to
+// rev except the largest one. If the generation becomes empty
+// during compaction, it will be removed. if all the generations get
+// removed, the keyIndex should be removed.
+//
+// For example:
+// compact(2) on the previous example
+// generations:
+// {empty}
+// {4.0, 5.0(t)}
+// {2.0, 3.0(t)}
+//
+// compact(4)
+// generations:
+// {empty}
+// {4.0, 5.0(t)}
+//
+// compact(5):
+// generations:
+// {empty} -> key SHOULD be removed.
+//
+// compact(6):
+// generations:
+// {empty} -> key SHOULD be removed.
+type keyIndex struct {
+ key []byte
+ modified revision // the main rev of the last modification
+ generations []generation
+}
+
+// put puts a revision to the keyIndex.
+func (ki *keyIndex) put(main int64, sub int64) {
+ rev := revision{main: main, sub: sub}
+
+ if !rev.GreaterThan(ki.modified) {
+ plog.Panicf("store.keyindex: put with unexpected smaller revision [%v / %v]", rev, ki.modified)
+ }
+ if len(ki.generations) == 0 {
+ ki.generations = append(ki.generations, generation{})
+ }
+ g := &ki.generations[len(ki.generations)-1]
+ if len(g.revs) == 0 { // create a new key
+ keysGauge.Inc()
+ g.created = rev
+ }
+ g.revs = append(g.revs, rev)
+ g.ver++
+ ki.modified = rev
+}
+
+func (ki *keyIndex) restore(created, modified revision, ver int64) {
+ if len(ki.generations) != 0 {
+ plog.Panicf("store.keyindex: cannot restore non-empty keyIndex")
+ }
+
+ ki.modified = modified
+ g := generation{created: created, ver: ver, revs: []revision{modified}}
+ ki.generations = append(ki.generations, g)
+ keysGauge.Inc()
+}
+
+// tombstone puts a revision, pointing to a tombstone, to the keyIndex.
+// It also creates a new empty generation in the keyIndex.
+// It returns ErrRevisionNotFound when tombstone on an empty generation.
+func (ki *keyIndex) tombstone(main int64, sub int64) error {
+ if ki.isEmpty() {
+ plog.Panicf("store.keyindex: unexpected tombstone on empty keyIndex %s", string(ki.key))
+ }
+ if ki.generations[len(ki.generations)-1].isEmpty() {
+ return ErrRevisionNotFound
+ }
+ ki.put(main, sub)
+ ki.generations = append(ki.generations, generation{})
+ keysGauge.Dec()
+ return nil
+}
+
+// get gets the modified, created revision and version of the key that satisfies the given atRev.
+// Rev must be higher than or equal to the given atRev.
+func (ki *keyIndex) get(atRev int64) (modified, created revision, ver int64, err error) {
+ if ki.isEmpty() {
+ plog.Panicf("store.keyindex: unexpected get on empty keyIndex %s", string(ki.key))
+ }
+ g := ki.findGeneration(atRev)
+ if g.isEmpty() {
+ return revision{}, revision{}, 0, ErrRevisionNotFound
+ }
+
+ n := g.walk(func(rev revision) bool { return rev.main > atRev })
+ if n != -1 {
+ return g.revs[n], g.created, g.ver - int64(len(g.revs)-n-1), nil
+ }
+
+ return revision{}, revision{}, 0, ErrRevisionNotFound
+}
+
+// since returns revisions since the given rev. Only the revision with the
+// largest sub revision will be returned if multiple revisions have the same
+// main revision.
+func (ki *keyIndex) since(rev int64) []revision {
+ if ki.isEmpty() {
+ plog.Panicf("store.keyindex: unexpected get on empty keyIndex %s", string(ki.key))
+ }
+ since := revision{rev, 0}
+ var gi int
+ // find the generations to start checking
+ for gi = len(ki.generations) - 1; gi > 0; gi-- {
+ g := ki.generations[gi]
+ if g.isEmpty() {
+ continue
+ }
+ if since.GreaterThan(g.created) {
+ break
+ }
+ }
+
+ var revs []revision
+ var last int64
+ for ; gi < len(ki.generations); gi++ {
+ for _, r := range ki.generations[gi].revs {
+ if since.GreaterThan(r) {
+ continue
+ }
+ if r.main == last {
+ // replace the revision with a new one that has higher sub value,
+ // because the original one should not be seen by external
+ revs[len(revs)-1] = r
+ continue
+ }
+ revs = append(revs, r)
+ last = r.main
+ }
+ }
+ return revs
+}
+
+// compact compacts a keyIndex by removing the versions with smaller or equal
+// revision than the given atRev except the largest one (If the largest one is
+// a tombstone, it will not be kept).
+// If a generation becomes empty during compaction, it will be removed.
+func (ki *keyIndex) compact(atRev int64, available map[revision]struct{}) {
+ if ki.isEmpty() {
+ plog.Panicf("store.keyindex: unexpected compact on empty keyIndex %s", string(ki.key))
+ }
+
+ genIdx, revIndex := ki.doCompact(atRev, available)
+
+ g := &ki.generations[genIdx]
+ if !g.isEmpty() {
+ // remove the previous contents.
+ if revIndex != -1 {
+ g.revs = g.revs[revIndex:]
+ }
+ // remove any tombstone
+ if len(g.revs) == 1 && genIdx != len(ki.generations)-1 {
+ delete(available, g.revs[0])
+ genIdx++
+ }
+ }
+
+ // remove the previous generations.
+ ki.generations = ki.generations[genIdx:]
+}
+
+// keep finds the revision to be kept if compact is called at given atRev.
+func (ki *keyIndex) keep(atRev int64, available map[revision]struct{}) {
+ if ki.isEmpty() {
+ return
+ }
+
+ genIdx, revIndex := ki.doCompact(atRev, available)
+ g := &ki.generations[genIdx]
+ if !g.isEmpty() {
+ // remove any tombstone
+ if revIndex == len(g.revs)-1 && genIdx != len(ki.generations)-1 {
+ delete(available, g.revs[revIndex])
+ }
+ }
+}
+
+func (ki *keyIndex) doCompact(atRev int64, available map[revision]struct{}) (genIdx int, revIndex int) {
+ // walk until reaching the first revision smaller or equal to "atRev",
+ // and add the revision to the available map
+ f := func(rev revision) bool {
+ if rev.main <= atRev {
+ available[rev] = struct{}{}
+ return false
+ }
+ return true
+ }
+
+ genIdx, g := 0, &ki.generations[0]
+ // find first generation includes atRev or created after atRev
+ for genIdx < len(ki.generations)-1 {
+ if tomb := g.revs[len(g.revs)-1].main; tomb > atRev {
+ break
+ }
+ genIdx++
+ g = &ki.generations[genIdx]
+ }
+
+ revIndex = g.walk(f)
+
+ return genIdx, revIndex
+}
+
+func (ki *keyIndex) isEmpty() bool {
+ return len(ki.generations) == 1 && ki.generations[0].isEmpty()
+}
+
+// findGeneration finds out the generation of the keyIndex that the
+// given rev belongs to. If the given rev is at the gap of two generations,
+// which means that the key does not exist at the given rev, it returns nil.
+func (ki *keyIndex) findGeneration(rev int64) *generation {
+ lastg := len(ki.generations) - 1
+ cg := lastg
+
+ for cg >= 0 {
+ if len(ki.generations[cg].revs) == 0 {
+ cg--
+ continue
+ }
+ g := ki.generations[cg]
+ if cg != lastg {
+ if tomb := g.revs[len(g.revs)-1].main; tomb <= rev {
+ return nil
+ }
+ }
+ if g.revs[0].main <= rev {
+ return &ki.generations[cg]
+ }
+ cg--
+ }
+ return nil
+}
+
+func (a *keyIndex) Less(b btree.Item) bool {
+ return bytes.Compare(a.key, b.(*keyIndex).key) == -1
+}
+
+func (a *keyIndex) equal(b *keyIndex) bool {
+ if !bytes.Equal(a.key, b.key) {
+ return false
+ }
+ if a.modified != b.modified {
+ return false
+ }
+ if len(a.generations) != len(b.generations) {
+ return false
+ }
+ for i := range a.generations {
+ ag, bg := a.generations[i], b.generations[i]
+ if !ag.equal(bg) {
+ return false
+ }
+ }
+ return true
+}
+
+func (ki *keyIndex) String() string {
+ var s string
+ for _, g := range ki.generations {
+ s += g.String()
+ }
+ return s
+}
+
+// generation contains multiple revisions of a key.
+type generation struct {
+ ver int64
+ created revision // when the generation is created (put in first revision).
+ revs []revision
+}
+
+func (g *generation) isEmpty() bool { return g == nil || len(g.revs) == 0 }
+
+// walk walks through the revisions in the generation in descending order.
+// It passes the revision to the given function.
+// walk returns until: 1. it finishes walking all pairs 2. the function returns false.
+// walk returns the position at where it stopped. If it stopped after
+// finishing walking, -1 will be returned.
+func (g *generation) walk(f func(rev revision) bool) int {
+ l := len(g.revs)
+ for i := range g.revs {
+ ok := f(g.revs[l-i-1])
+ if !ok {
+ return l - i - 1
+ }
+ }
+ return -1
+}
+
+func (g *generation) String() string {
+ return fmt.Sprintf("g: created[%d] ver[%d], revs %#v\n", g.created, g.ver, g.revs)
+}
+
+func (a generation) equal(b generation) bool {
+ if a.ver != b.ver {
+ return false
+ }
+ if len(a.revs) != len(b.revs) {
+ return false
+ }
+
+ for i := range a.revs {
+ ar, br := a.revs[i], b.revs[i]
+ if ar != br {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/kv.go b/vendor/github.com/coreos/etcd/mvcc/kv.go
new file mode 100644
index 00000000..2dad3ad8
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/kv.go
@@ -0,0 +1,149 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/mvcc/mvccpb"
+)
+
+type RangeOptions struct {
+ Limit int64
+ Rev int64
+ Count bool
+}
+
+type RangeResult struct {
+ KVs []mvccpb.KeyValue
+ Rev int64
+ Count int
+}
+
+type ReadView interface {
+ // FirstRev returns the first KV revision at the time of opening the txn.
+ // After a compaction, the first revision increases to the compaction
+ // revision.
+ FirstRev() int64
+
+ // Rev returns the revision of the KV at the time of opening the txn.
+ Rev() int64
+
+ // Range gets the keys in the range at rangeRev.
+ // The returned rev is the current revision of the KV when the operation is executed.
+ // If rangeRev <=0, range gets the keys at currentRev.
+ // If `end` is nil, the request returns the key.
+ // If `end` is not nil and not empty, it gets the keys in range [key, range_end).
+ // If `end` is not nil and empty, it gets the keys greater than or equal to key.
+ // Limit limits the number of keys returned.
+ // If the required rev is compacted, ErrCompacted will be returned.
+ Range(key, end []byte, ro RangeOptions) (r *RangeResult, err error)
+}
+
+// TxnRead represents a read-only transaction with operations that will not
+// block other read transactions.
+type TxnRead interface {
+ ReadView
+ // End marks the transaction is complete and ready to commit.
+ End()
+}
+
+type WriteView interface {
+ // DeleteRange deletes the given range from the store.
+ // A deleteRange increases the rev of the store if any key in the range exists.
+ // The number of key deleted will be returned.
+ // The returned rev is the current revision of the KV when the operation is executed.
+ // It also generates one event for each key delete in the event history.
+ // if the `end` is nil, deleteRange deletes the key.
+ // if the `end` is not nil, deleteRange deletes the keys in range [key, range_end).
+ DeleteRange(key, end []byte) (n, rev int64)
+
+ // Put puts the given key, value into the store. Put also takes additional argument lease to
+ // attach a lease to a key-value pair as meta-data. KV implementation does not validate the lease
+ // id.
+ // A put also increases the rev of the store, and generates one event in the event history.
+ // The returned rev is the current revision of the KV when the operation is executed.
+ Put(key, value []byte, lease lease.LeaseID) (rev int64)
+}
+
+// TxnWrite represents a transaction that can modify the store.
+type TxnWrite interface {
+ TxnRead
+ WriteView
+ // Changes gets the changes made since opening the write txn.
+ Changes() []mvccpb.KeyValue
+}
+
+// txnReadWrite coerces a read txn to a write, panicking on any write operation.
+type txnReadWrite struct{ TxnRead }
+
+func (trw *txnReadWrite) DeleteRange(key, end []byte) (n, rev int64) { panic("unexpected DeleteRange") }
+func (trw *txnReadWrite) Put(key, value []byte, lease lease.LeaseID) (rev int64) {
+ panic("unexpected Put")
+}
+func (trw *txnReadWrite) Changes() []mvccpb.KeyValue { return nil }
+
+func NewReadOnlyTxnWrite(txn TxnRead) TxnWrite { return &txnReadWrite{txn} }
+
+type KV interface {
+ ReadView
+ WriteView
+
+ // Read creates a read transaction.
+ Read() TxnRead
+
+ // Write creates a write transaction.
+ Write() TxnWrite
+
+ // Hash computes the hash of the KV's backend.
+ Hash() (hash uint32, revision int64, err error)
+
+ // HashByRev computes the hash of all MVCC revisions up to a given revision.
+ HashByRev(rev int64) (hash uint32, revision int64, compactRev int64, err error)
+
+ // Compact frees all superseded keys with revisions less than rev.
+ Compact(rev int64) (<-chan struct{}, error)
+
+ // Commit commits outstanding txns into the underlying backend.
+ Commit()
+
+ // Restore restores the KV store from a backend.
+ Restore(b backend.Backend) error
+ Close() error
+}
+
+// WatchableKV is a KV that can be watched.
+type WatchableKV interface {
+ KV
+ Watchable
+}
+
+// Watchable is the interface that wraps the NewWatchStream function.
+type Watchable interface {
+ // NewWatchStream returns a WatchStream that can be used to
+ // watch events happened or happening on the KV.
+ NewWatchStream() WatchStream
+}
+
+// ConsistentWatchableKV is a WatchableKV that understands the consistency
+// algorithm and consistent index.
+// If the consistent index of executing entry is not larger than the
+// consistent index of ConsistentWatchableKV, all operations in
+// this entry are skipped and return empty response.
+type ConsistentWatchableKV interface {
+ WatchableKV
+ // ConsistentIndex returns the current consistent index of the KV.
+ ConsistentIndex() uint64
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/kv_view.go b/vendor/github.com/coreos/etcd/mvcc/kv_view.go
new file mode 100644
index 00000000..f40ba8ed
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/kv_view.go
@@ -0,0 +1,53 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "github.com/coreos/etcd/lease"
+)
+
+type readView struct{ kv KV }
+
+func (rv *readView) FirstRev() int64 {
+ tr := rv.kv.Read()
+ defer tr.End()
+ return tr.FirstRev()
+}
+
+func (rv *readView) Rev() int64 {
+ tr := rv.kv.Read()
+ defer tr.End()
+ return tr.Rev()
+}
+
+func (rv *readView) Range(key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
+ tr := rv.kv.Read()
+ defer tr.End()
+ return tr.Range(key, end, ro)
+}
+
+type writeView struct{ kv KV }
+
+func (wv *writeView) DeleteRange(key, end []byte) (n, rev int64) {
+ tw := wv.kv.Write()
+ defer tw.End()
+ return tw.DeleteRange(key, end)
+}
+
+func (wv *writeView) Put(key, value []byte, lease lease.LeaseID) (rev int64) {
+ tw := wv.kv.Write()
+ defer tw.End()
+ return tw.Put(key, value, lease)
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/kvstore.go b/vendor/github.com/coreos/etcd/mvcc/kvstore.go
new file mode 100644
index 00000000..dd9f04ae
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/kvstore.go
@@ -0,0 +1,510 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "context"
+ "encoding/binary"
+ "errors"
+ "hash/crc32"
+ "math"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/mvcc/mvccpb"
+ "github.com/coreos/etcd/pkg/schedule"
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ keyBucketName = []byte("key")
+ metaBucketName = []byte("meta")
+
+ consistentIndexKeyName = []byte("consistent_index")
+ scheduledCompactKeyName = []byte("scheduledCompactRev")
+ finishedCompactKeyName = []byte("finishedCompactRev")
+
+ ErrCompacted = errors.New("mvcc: required revision has been compacted")
+ ErrFutureRev = errors.New("mvcc: required revision is a future revision")
+ ErrCanceled = errors.New("mvcc: watcher is canceled")
+ ErrClosed = errors.New("mvcc: closed")
+
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "mvcc")
+)
+
+const (
+ // markedRevBytesLen is the byte length of marked revision.
+ // The first `revBytesLen` bytes represents a normal revision. The last
+ // one byte is the mark.
+ markedRevBytesLen = revBytesLen + 1
+ markBytePosition = markedRevBytesLen - 1
+ markTombstone byte = 't'
+)
+
+var restoreChunkKeys = 10000 // non-const for testing
+
+// ConsistentIndexGetter is an interface that wraps the Get method.
+// Consistent index is the offset of an entry in a consistent replicated log.
+type ConsistentIndexGetter interface {
+ // ConsistentIndex returns the consistent index of current executing entry.
+ ConsistentIndex() uint64
+}
+
+type store struct {
+ ReadView
+ WriteView
+
+ // consistentIndex caches the "consistent_index" key's value. Accessed
+ // through atomics so must be 64-bit aligned.
+ consistentIndex uint64
+
+ // mu read locks for txns and write locks for non-txn store changes.
+ mu sync.RWMutex
+
+ ig ConsistentIndexGetter
+
+ b backend.Backend
+ kvindex index
+
+ le lease.Lessor
+
+ // revMuLock protects currentRev and compactMainRev.
+ // Locked at end of write txn and released after write txn unlock lock.
+ // Locked before locking read txn and released after locking.
+ revMu sync.RWMutex
+ // currentRev is the revision of the last completed transaction.
+ currentRev int64
+ // compactMainRev is the main revision of the last compaction.
+ compactMainRev int64
+
+ // bytesBuf8 is a byte slice of length 8
+ // to avoid a repetitive allocation in saveIndex.
+ bytesBuf8 []byte
+
+ fifoSched schedule.Scheduler
+
+ stopc chan struct{}
+}
+
+// NewStore returns a new store. It is useful to create a store inside
+// mvcc pkg. It should only be used for testing externally.
+func NewStore(b backend.Backend, le lease.Lessor, ig ConsistentIndexGetter) *store {
+ s := &store{
+ b: b,
+ ig: ig,
+ kvindex: newTreeIndex(),
+
+ le: le,
+
+ currentRev: 1,
+ compactMainRev: -1,
+
+ bytesBuf8: make([]byte, 8),
+ fifoSched: schedule.NewFIFOScheduler(),
+
+ stopc: make(chan struct{}),
+ }
+ s.ReadView = &readView{s}
+ s.WriteView = &writeView{s}
+ if s.le != nil {
+ s.le.SetRangeDeleter(func() lease.TxnDelete { return s.Write() })
+ }
+
+ tx := s.b.BatchTx()
+ tx.Lock()
+ tx.UnsafeCreateBucket(keyBucketName)
+ tx.UnsafeCreateBucket(metaBucketName)
+ tx.Unlock()
+ s.b.ForceCommit()
+
+ if err := s.restore(); err != nil {
+ // TODO: return the error instead of panic here?
+ panic("failed to recover store from backend")
+ }
+
+ return s
+}
+
+func (s *store) compactBarrier(ctx context.Context, ch chan struct{}) {
+ if ctx == nil || ctx.Err() != nil {
+ s.mu.Lock()
+ select {
+ case <-s.stopc:
+ default:
+ f := func(ctx context.Context) { s.compactBarrier(ctx, ch) }
+ s.fifoSched.Schedule(f)
+ }
+ s.mu.Unlock()
+ return
+ }
+ close(ch)
+}
+
+func (s *store) Hash() (hash uint32, revision int64, err error) {
+ start := time.Now()
+
+ s.b.ForceCommit()
+ h, err := s.b.Hash(DefaultIgnores)
+
+ hashDurations.Observe(time.Since(start).Seconds())
+ return h, s.currentRev, err
+}
+
+func (s *store) HashByRev(rev int64) (hash uint32, currentRev int64, compactRev int64, err error) {
+ start := time.Now()
+
+ s.mu.RLock()
+ s.revMu.RLock()
+ compactRev, currentRev = s.compactMainRev, s.currentRev
+ s.revMu.RUnlock()
+
+ if rev > 0 && rev <= compactRev {
+ s.mu.RUnlock()
+ return 0, 0, compactRev, ErrCompacted
+ } else if rev > 0 && rev > currentRev {
+ s.mu.RUnlock()
+ return 0, currentRev, 0, ErrFutureRev
+ }
+
+ if rev == 0 {
+ rev = currentRev
+ }
+ keep := s.kvindex.Keep(rev)
+
+ tx := s.b.ReadTx()
+ tx.Lock()
+ defer tx.Unlock()
+ s.mu.RUnlock()
+
+ upper := revision{main: rev + 1}
+ lower := revision{main: compactRev + 1}
+ h := crc32.New(crc32.MakeTable(crc32.Castagnoli))
+
+ h.Write(keyBucketName)
+ err = tx.UnsafeForEach(keyBucketName, func(k, v []byte) error {
+ kr := bytesToRev(k)
+ if !upper.GreaterThan(kr) {
+ return nil
+ }
+ // skip revisions that are scheduled for deletion
+ // due to compacting; don't skip if there isn't one.
+ if lower.GreaterThan(kr) && len(keep) > 0 {
+ if _, ok := keep[kr]; !ok {
+ return nil
+ }
+ }
+ h.Write(k)
+ h.Write(v)
+ return nil
+ })
+ hash = h.Sum32()
+
+ hashRevDurations.Observe(time.Since(start).Seconds())
+ return hash, currentRev, compactRev, err
+}
+
+func (s *store) Compact(rev int64) (<-chan struct{}, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ s.revMu.Lock()
+ defer s.revMu.Unlock()
+
+ if rev <= s.compactMainRev {
+ ch := make(chan struct{})
+ f := func(ctx context.Context) { s.compactBarrier(ctx, ch) }
+ s.fifoSched.Schedule(f)
+ return ch, ErrCompacted
+ }
+ if rev > s.currentRev {
+ return nil, ErrFutureRev
+ }
+
+ start := time.Now()
+
+ s.compactMainRev = rev
+
+ rbytes := newRevBytes()
+ revToBytes(revision{main: rev}, rbytes)
+
+ tx := s.b.BatchTx()
+ tx.Lock()
+ tx.UnsafePut(metaBucketName, scheduledCompactKeyName, rbytes)
+ tx.Unlock()
+ // ensure that desired compaction is persisted
+ s.b.ForceCommit()
+
+ keep := s.kvindex.Compact(rev)
+ ch := make(chan struct{})
+ var j = func(ctx context.Context) {
+ if ctx.Err() != nil {
+ s.compactBarrier(ctx, ch)
+ return
+ }
+ if !s.scheduleCompaction(rev, keep) {
+ s.compactBarrier(nil, ch)
+ return
+ }
+ close(ch)
+ }
+
+ s.fifoSched.Schedule(j)
+
+ indexCompactionPauseDurations.Observe(float64(time.Since(start) / time.Millisecond))
+ return ch, nil
+}
+
+// DefaultIgnores is a map of keys to ignore in hash checking.
+var DefaultIgnores map[backend.IgnoreKey]struct{}
+
+func init() {
+ DefaultIgnores = map[backend.IgnoreKey]struct{}{
+ // consistent index might be changed due to v2 internal sync, which
+ // is not controllable by the user.
+ {Bucket: string(metaBucketName), Key: string(consistentIndexKeyName)}: {},
+ }
+}
+
+func (s *store) Commit() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ tx := s.b.BatchTx()
+ tx.Lock()
+ s.saveIndex(tx)
+ tx.Unlock()
+ s.b.ForceCommit()
+}
+
+func (s *store) Restore(b backend.Backend) error {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ close(s.stopc)
+ s.fifoSched.Stop()
+
+ atomic.StoreUint64(&s.consistentIndex, 0)
+ s.b = b
+ s.kvindex = newTreeIndex()
+ s.currentRev = 1
+ s.compactMainRev = -1
+ s.fifoSched = schedule.NewFIFOScheduler()
+ s.stopc = make(chan struct{})
+
+ return s.restore()
+}
+
+func (s *store) restore() error {
+ b := s.b
+
+ reportDbTotalSizeInBytesMu.Lock()
+ reportDbTotalSizeInBytes = func() float64 { return float64(b.Size()) }
+ reportDbTotalSizeInBytesMu.Unlock()
+ reportDbTotalSizeInUseInBytesMu.Lock()
+ reportDbTotalSizeInUseInBytes = func() float64 { return float64(b.SizeInUse()) }
+ reportDbTotalSizeInUseInBytesMu.Unlock()
+
+ min, max := newRevBytes(), newRevBytes()
+ revToBytes(revision{main: 1}, min)
+ revToBytes(revision{main: math.MaxInt64, sub: math.MaxInt64}, max)
+
+ keyToLease := make(map[string]lease.LeaseID)
+
+ // restore index
+ tx := s.b.BatchTx()
+ tx.Lock()
+
+ _, finishedCompactBytes := tx.UnsafeRange(metaBucketName, finishedCompactKeyName, nil, 0)
+ if len(finishedCompactBytes) != 0 {
+ s.compactMainRev = bytesToRev(finishedCompactBytes[0]).main
+ plog.Printf("restore compact to %d", s.compactMainRev)
+ }
+ _, scheduledCompactBytes := tx.UnsafeRange(metaBucketName, scheduledCompactKeyName, nil, 0)
+ scheduledCompact := int64(0)
+ if len(scheduledCompactBytes) != 0 {
+ scheduledCompact = bytesToRev(scheduledCompactBytes[0]).main
+ }
+
+ // index keys concurrently as they're loaded in from tx
+ keysGauge.Set(0)
+ rkvc, revc := restoreIntoIndex(s.kvindex)
+ for {
+ keys, vals := tx.UnsafeRange(keyBucketName, min, max, int64(restoreChunkKeys))
+ if len(keys) == 0 {
+ break
+ }
+ // rkvc blocks if the total pending keys exceeds the restore
+ // chunk size to keep keys from consuming too much memory.
+ restoreChunk(rkvc, keys, vals, keyToLease)
+ if len(keys) < restoreChunkKeys {
+ // partial set implies final set
+ break
+ }
+ // next set begins after where this one ended
+ newMin := bytesToRev(keys[len(keys)-1][:revBytesLen])
+ newMin.sub++
+ revToBytes(newMin, min)
+ }
+ close(rkvc)
+ s.currentRev = <-revc
+
+ // keys in the range [compacted revision -N, compaction] might all be deleted due to compaction.
+ // the correct revision should be set to compaction revision in the case, not the largest revision
+ // we have seen.
+ if s.currentRev < s.compactMainRev {
+ s.currentRev = s.compactMainRev
+ }
+ if scheduledCompact <= s.compactMainRev {
+ scheduledCompact = 0
+ }
+
+ for key, lid := range keyToLease {
+ if s.le == nil {
+ panic("no lessor to attach lease")
+ }
+ err := s.le.Attach(lid, []lease.LeaseItem{{Key: key}})
+ if err != nil {
+ plog.Errorf("unexpected Attach error: %v", err)
+ }
+ }
+
+ tx.Unlock()
+
+ if scheduledCompact != 0 {
+ s.Compact(scheduledCompact)
+ plog.Printf("resume scheduled compaction at %d", scheduledCompact)
+ }
+
+ return nil
+}
+
+type revKeyValue struct {
+ key []byte
+ kv mvccpb.KeyValue
+ kstr string
+}
+
+func restoreIntoIndex(idx index) (chan<- revKeyValue, <-chan int64) {
+ rkvc, revc := make(chan revKeyValue, restoreChunkKeys), make(chan int64, 1)
+ go func() {
+ currentRev := int64(1)
+ defer func() { revc <- currentRev }()
+ // restore the tree index from streaming the unordered index.
+ kiCache := make(map[string]*keyIndex, restoreChunkKeys)
+ for rkv := range rkvc {
+ ki, ok := kiCache[rkv.kstr]
+ // purge kiCache if many keys but still missing in the cache
+ if !ok && len(kiCache) >= restoreChunkKeys {
+ i := 10
+ for k := range kiCache {
+ delete(kiCache, k)
+ if i--; i == 0 {
+ break
+ }
+ }
+ }
+ // cache miss, fetch from tree index if there
+ if !ok {
+ ki = &keyIndex{key: rkv.kv.Key}
+ if idxKey := idx.KeyIndex(ki); idxKey != nil {
+ kiCache[rkv.kstr], ki = idxKey, idxKey
+ ok = true
+ }
+ }
+ rev := bytesToRev(rkv.key)
+ currentRev = rev.main
+ if ok {
+ if isTombstone(rkv.key) {
+ ki.tombstone(rev.main, rev.sub)
+ continue
+ }
+ ki.put(rev.main, rev.sub)
+ } else if !isTombstone(rkv.key) {
+ ki.restore(revision{rkv.kv.CreateRevision, 0}, rev, rkv.kv.Version)
+ idx.Insert(ki)
+ kiCache[rkv.kstr] = ki
+ }
+ }
+ }()
+ return rkvc, revc
+}
+
+func restoreChunk(kvc chan<- revKeyValue, keys, vals [][]byte, keyToLease map[string]lease.LeaseID) {
+ for i, key := range keys {
+ rkv := revKeyValue{key: key}
+ if err := rkv.kv.Unmarshal(vals[i]); err != nil {
+ plog.Fatalf("cannot unmarshal event: %v", err)
+ }
+ rkv.kstr = string(rkv.kv.Key)
+ if isTombstone(key) {
+ delete(keyToLease, rkv.kstr)
+ } else if lid := lease.LeaseID(rkv.kv.Lease); lid != lease.NoLease {
+ keyToLease[rkv.kstr] = lid
+ } else {
+ delete(keyToLease, rkv.kstr)
+ }
+ kvc <- rkv
+ }
+}
+
+func (s *store) Close() error {
+ close(s.stopc)
+ s.fifoSched.Stop()
+ return nil
+}
+
+func (s *store) saveIndex(tx backend.BatchTx) {
+ if s.ig == nil {
+ return
+ }
+ bs := s.bytesBuf8
+ ci := s.ig.ConsistentIndex()
+ binary.BigEndian.PutUint64(bs, ci)
+ // put the index into the underlying backend
+ // tx has been locked in TxnBegin, so there is no need to lock it again
+ tx.UnsafePut(metaBucketName, consistentIndexKeyName, bs)
+ atomic.StoreUint64(&s.consistentIndex, ci)
+}
+
+func (s *store) ConsistentIndex() uint64 {
+ if ci := atomic.LoadUint64(&s.consistentIndex); ci > 0 {
+ return ci
+ }
+ tx := s.b.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+ _, vs := tx.UnsafeRange(metaBucketName, consistentIndexKeyName, nil, 0)
+ if len(vs) == 0 {
+ return 0
+ }
+ v := binary.BigEndian.Uint64(vs[0])
+ atomic.StoreUint64(&s.consistentIndex, v)
+ return v
+}
+
+// appendMarkTombstone appends tombstone mark to normal revision bytes.
+func appendMarkTombstone(b []byte) []byte {
+ if len(b) != revBytesLen {
+ plog.Panicf("cannot append mark to non normal revision bytes")
+ }
+ return append(b, markTombstone)
+}
+
+// isTombstone checks whether the revision bytes is a tombstone.
+func isTombstone(b []byte) bool {
+ return len(b) == markedRevBytesLen && b[markBytePosition] == markTombstone
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/kvstore_compaction.go b/vendor/github.com/coreos/etcd/mvcc/kvstore_compaction.go
new file mode 100644
index 00000000..1726490c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/kvstore_compaction.go
@@ -0,0 +1,69 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "encoding/binary"
+ "time"
+)
+
+func (s *store) scheduleCompaction(compactMainRev int64, keep map[revision]struct{}) bool {
+ totalStart := time.Now()
+ defer dbCompactionTotalDurations.Observe(float64(time.Since(totalStart) / time.Millisecond))
+ keyCompactions := 0
+ defer func() { dbCompactionKeysCounter.Add(float64(keyCompactions)) }()
+
+ end := make([]byte, 8)
+ binary.BigEndian.PutUint64(end, uint64(compactMainRev+1))
+
+ batchsize := int64(10000)
+ last := make([]byte, 8+1+8)
+ for {
+ var rev revision
+
+ start := time.Now()
+ tx := s.b.BatchTx()
+ tx.Lock()
+
+ keys, _ := tx.UnsafeRange(keyBucketName, last, end, batchsize)
+ for _, key := range keys {
+ rev = bytesToRev(key)
+ if _, ok := keep[rev]; !ok {
+ tx.UnsafeDelete(keyBucketName, key)
+ keyCompactions++
+ }
+ }
+
+ if len(keys) < int(batchsize) {
+ rbytes := make([]byte, 8+1+8)
+ revToBytes(revision{main: compactMainRev}, rbytes)
+ tx.UnsafePut(metaBucketName, finishedCompactKeyName, rbytes)
+ tx.Unlock()
+ plog.Printf("finished scheduled compaction at %d (took %v)", compactMainRev, time.Since(totalStart))
+ return true
+ }
+
+ // update last
+ revToBytes(revision{main: rev.main, sub: rev.sub + 1}, last)
+ tx.Unlock()
+ dbCompactionPauseDurations.Observe(float64(time.Since(start) / time.Millisecond))
+
+ select {
+ case <-time.After(100 * time.Millisecond):
+ case <-s.stopc:
+ return false
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/kvstore_txn.go b/vendor/github.com/coreos/etcd/mvcc/kvstore_txn.go
new file mode 100644
index 00000000..8896fb86
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/kvstore_txn.go
@@ -0,0 +1,253 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/mvcc/mvccpb"
+)
+
+type storeTxnRead struct {
+ s *store
+ tx backend.ReadTx
+
+ firstRev int64
+ rev int64
+}
+
+func (s *store) Read() TxnRead {
+ s.mu.RLock()
+ tx := s.b.ReadTx()
+ s.revMu.RLock()
+ tx.Lock()
+ firstRev, rev := s.compactMainRev, s.currentRev
+ s.revMu.RUnlock()
+ return newMetricsTxnRead(&storeTxnRead{s, tx, firstRev, rev})
+}
+
+func (tr *storeTxnRead) FirstRev() int64 { return tr.firstRev }
+func (tr *storeTxnRead) Rev() int64 { return tr.rev }
+
+func (tr *storeTxnRead) Range(key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
+ return tr.rangeKeys(key, end, tr.Rev(), ro)
+}
+
+func (tr *storeTxnRead) End() {
+ tr.tx.Unlock()
+ tr.s.mu.RUnlock()
+}
+
+type storeTxnWrite struct {
+ storeTxnRead
+ tx backend.BatchTx
+ // beginRev is the revision where the txn begins; it will write to the next revision.
+ beginRev int64
+ changes []mvccpb.KeyValue
+}
+
+func (s *store) Write() TxnWrite {
+ s.mu.RLock()
+ tx := s.b.BatchTx()
+ tx.Lock()
+ tw := &storeTxnWrite{
+ storeTxnRead: storeTxnRead{s, tx, 0, 0},
+ tx: tx,
+ beginRev: s.currentRev,
+ changes: make([]mvccpb.KeyValue, 0, 4),
+ }
+ return newMetricsTxnWrite(tw)
+}
+
+func (tw *storeTxnWrite) Rev() int64 { return tw.beginRev }
+
+func (tw *storeTxnWrite) Range(key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
+ rev := tw.beginRev
+ if len(tw.changes) > 0 {
+ rev++
+ }
+ return tw.rangeKeys(key, end, rev, ro)
+}
+
+func (tw *storeTxnWrite) DeleteRange(key, end []byte) (int64, int64) {
+ if n := tw.deleteRange(key, end); n != 0 || len(tw.changes) > 0 {
+ return n, int64(tw.beginRev + 1)
+ }
+ return 0, int64(tw.beginRev)
+}
+
+func (tw *storeTxnWrite) Put(key, value []byte, lease lease.LeaseID) int64 {
+ tw.put(key, value, lease)
+ return int64(tw.beginRev + 1)
+}
+
+func (tw *storeTxnWrite) End() {
+ // only update index if the txn modifies the mvcc state.
+ if len(tw.changes) != 0 {
+ tw.s.saveIndex(tw.tx)
+ // hold revMu lock to prevent new read txns from opening until writeback.
+ tw.s.revMu.Lock()
+ tw.s.currentRev++
+ }
+ tw.tx.Unlock()
+ if len(tw.changes) != 0 {
+ tw.s.revMu.Unlock()
+ }
+ tw.s.mu.RUnlock()
+}
+
+func (tr *storeTxnRead) rangeKeys(key, end []byte, curRev int64, ro RangeOptions) (*RangeResult, error) {
+ rev := ro.Rev
+ if rev > curRev {
+ return &RangeResult{KVs: nil, Count: -1, Rev: curRev}, ErrFutureRev
+ }
+ if rev <= 0 {
+ rev = curRev
+ }
+ if rev < tr.s.compactMainRev {
+ return &RangeResult{KVs: nil, Count: -1, Rev: 0}, ErrCompacted
+ }
+
+ revpairs := tr.s.kvindex.Revisions(key, end, int64(rev))
+ if len(revpairs) == 0 {
+ return &RangeResult{KVs: nil, Count: 0, Rev: curRev}, nil
+ }
+ if ro.Count {
+ return &RangeResult{KVs: nil, Count: len(revpairs), Rev: curRev}, nil
+ }
+
+ limit := int(ro.Limit)
+ if limit <= 0 || limit > len(revpairs) {
+ limit = len(revpairs)
+ }
+
+ kvs := make([]mvccpb.KeyValue, limit)
+ revBytes := newRevBytes()
+ for i, revpair := range revpairs[:len(kvs)] {
+ revToBytes(revpair, revBytes)
+ _, vs := tr.tx.UnsafeRange(keyBucketName, revBytes, nil, 0)
+ if len(vs) != 1 {
+ plog.Fatalf("range cannot find rev (%d,%d)", revpair.main, revpair.sub)
+ }
+ if err := kvs[i].Unmarshal(vs[0]); err != nil {
+ plog.Fatalf("cannot unmarshal event: %v", err)
+ }
+ }
+ return &RangeResult{KVs: kvs, Count: len(revpairs), Rev: curRev}, nil
+}
+
+func (tw *storeTxnWrite) put(key, value []byte, leaseID lease.LeaseID) {
+ rev := tw.beginRev + 1
+ c := rev
+ oldLease := lease.NoLease
+
+ // if the key exists before, use its previous created and
+ // get its previous leaseID
+ _, created, ver, err := tw.s.kvindex.Get(key, rev)
+ if err == nil {
+ c = created.main
+ oldLease = tw.s.le.GetLease(lease.LeaseItem{Key: string(key)})
+ }
+
+ ibytes := newRevBytes()
+ idxRev := revision{main: rev, sub: int64(len(tw.changes))}
+ revToBytes(idxRev, ibytes)
+
+ ver = ver + 1
+ kv := mvccpb.KeyValue{
+ Key: key,
+ Value: value,
+ CreateRevision: c,
+ ModRevision: rev,
+ Version: ver,
+ Lease: int64(leaseID),
+ }
+
+ d, err := kv.Marshal()
+ if err != nil {
+ plog.Fatalf("cannot marshal event: %v", err)
+ }
+
+ tw.tx.UnsafeSeqPut(keyBucketName, ibytes, d)
+ tw.s.kvindex.Put(key, idxRev)
+ tw.changes = append(tw.changes, kv)
+
+ if oldLease != lease.NoLease {
+ if tw.s.le == nil {
+ panic("no lessor to detach lease")
+ }
+ err = tw.s.le.Detach(oldLease, []lease.LeaseItem{{Key: string(key)}})
+ if err != nil {
+ plog.Errorf("unexpected error from lease detach: %v", err)
+ }
+ }
+ if leaseID != lease.NoLease {
+ if tw.s.le == nil {
+ panic("no lessor to attach lease")
+ }
+ err = tw.s.le.Attach(leaseID, []lease.LeaseItem{{Key: string(key)}})
+ if err != nil {
+ panic("unexpected error from lease Attach")
+ }
+ }
+}
+
+func (tw *storeTxnWrite) deleteRange(key, end []byte) int64 {
+ rrev := tw.beginRev
+ if len(tw.changes) > 0 {
+ rrev += 1
+ }
+ keys, revs := tw.s.kvindex.Range(key, end, rrev)
+ if len(keys) == 0 {
+ return 0
+ }
+ for i, key := range keys {
+ tw.delete(key, revs[i])
+ }
+ return int64(len(keys))
+}
+
+func (tw *storeTxnWrite) delete(key []byte, rev revision) {
+ ibytes := newRevBytes()
+ idxRev := revision{main: tw.beginRev + 1, sub: int64(len(tw.changes))}
+ revToBytes(idxRev, ibytes)
+ ibytes = appendMarkTombstone(ibytes)
+
+ kv := mvccpb.KeyValue{Key: key}
+
+ d, err := kv.Marshal()
+ if err != nil {
+ plog.Fatalf("cannot marshal event: %v", err)
+ }
+
+ tw.tx.UnsafeSeqPut(keyBucketName, ibytes, d)
+ err = tw.s.kvindex.Tombstone(key, idxRev)
+ if err != nil {
+ plog.Fatalf("cannot tombstone an existing key (%s): %v", string(key), err)
+ }
+ tw.changes = append(tw.changes, kv)
+
+ item := lease.LeaseItem{Key: string(key)}
+ leaseID := tw.s.le.GetLease(item)
+
+ if leaseID != lease.NoLease {
+ err = tw.s.le.Detach(leaseID, []lease.LeaseItem{item})
+ if err != nil {
+ plog.Errorf("cannot detach %v", err)
+ }
+ }
+}
+
+func (tw *storeTxnWrite) Changes() []mvccpb.KeyValue { return tw.changes }
diff --git a/vendor/github.com/coreos/etcd/mvcc/metrics.go b/vendor/github.com/coreos/etcd/mvcc/metrics.go
new file mode 100644
index 00000000..b753310c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/metrics.go
@@ -0,0 +1,239 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "sync"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+var (
+ rangeCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "range_total",
+ Help: "Total number of ranges seen by this member.",
+ })
+
+ putCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "put_total",
+ Help: "Total number of puts seen by this member.",
+ })
+
+ deleteCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "delete_total",
+ Help: "Total number of deletes seen by this member.",
+ })
+
+ txnCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "txn_total",
+ Help: "Total number of txns seen by this member.",
+ })
+
+ keysGauge = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "keys_total",
+ Help: "Total number of keys.",
+ })
+
+ watchStreamGauge = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "watch_stream_total",
+ Help: "Total number of watch streams.",
+ })
+
+ watcherGauge = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "watcher_total",
+ Help: "Total number of watchers.",
+ })
+
+ slowWatcherGauge = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "slow_watcher_total",
+ Help: "Total number of unsynced slow watchers.",
+ })
+
+ totalEventsCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "events_total",
+ Help: "Total number of events sent by this member.",
+ })
+
+ pendingEventsGauge = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "pending_events_total",
+ Help: "Total number of pending events to be sent.",
+ })
+
+ indexCompactionPauseDurations = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "index_compaction_pause_duration_milliseconds",
+ Help: "Bucketed histogram of index compaction pause duration.",
+ // 0.5ms -> 1second
+ Buckets: prometheus.ExponentialBuckets(0.5, 2, 12),
+ })
+
+ dbCompactionPauseDurations = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_compaction_pause_duration_milliseconds",
+ Help: "Bucketed histogram of db compaction pause duration.",
+ // 1ms -> 4second
+ Buckets: prometheus.ExponentialBuckets(1, 2, 13),
+ })
+
+ dbCompactionTotalDurations = prometheus.NewHistogram(
+ prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_compaction_total_duration_milliseconds",
+ Help: "Bucketed histogram of db compaction total duration.",
+ // 100ms -> 800second
+ Buckets: prometheus.ExponentialBuckets(100, 2, 14),
+ })
+
+ dbCompactionKeysCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_compaction_keys_total",
+ Help: "Total number of db keys compacted.",
+ })
+
+ dbTotalSizeDebugging = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "mvcc",
+ Name: "db_total_size_in_bytes",
+ Help: "Total size of the underlying database physically allocated in bytes. Use etcd_mvcc_db_total_size_in_bytes",
+ },
+ func() float64 {
+ reportDbTotalSizeInBytesMu.RLock()
+ defer reportDbTotalSizeInBytesMu.RUnlock()
+ return reportDbTotalSizeInBytes()
+ },
+ )
+ dbTotalSize = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "mvcc",
+ Name: "db_total_size_in_bytes",
+ Help: "Total size of the underlying database physically allocated in bytes.",
+ },
+ func() float64 {
+ reportDbTotalSizeInBytesMu.RLock()
+ defer reportDbTotalSizeInBytesMu.RUnlock()
+ return reportDbTotalSizeInBytes()
+ },
+ )
+ // overridden by mvcc initialization
+ reportDbTotalSizeInBytesMu sync.RWMutex
+ reportDbTotalSizeInBytes = func() float64 { return 0 }
+
+ dbTotalSizeInUse = prometheus.NewGaugeFunc(prometheus.GaugeOpts{
+ Namespace: "etcd",
+ Subsystem: "mvcc",
+ Name: "db_total_size_in_use_in_bytes",
+ Help: "Total size of the underlying database logically in use in bytes.",
+ },
+ func() float64 {
+ reportDbTotalSizeInUseInBytesMu.RLock()
+ defer reportDbTotalSizeInUseInBytesMu.RUnlock()
+ return reportDbTotalSizeInUseInBytes()
+ },
+ )
+ // overridden by mvcc initialization
+ reportDbTotalSizeInUseInBytesMu sync.RWMutex
+ reportDbTotalSizeInUseInBytes func() float64 = func() float64 { return 0 }
+
+ hashDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "mvcc",
+ Name: "hash_duration_seconds",
+ Help: "The latency distribution of storage hash operation.",
+
+ // 100 MB usually takes 100 ms, so start with 10 MB of 10 ms
+ // lowest bucket start of upper bound 0.01 sec (10 ms) with factor 2
+ // highest bucket start of 0.01 sec * 2^14 == 163.84 sec
+ Buckets: prometheus.ExponentialBuckets(.01, 2, 15),
+ })
+
+ hashRevDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "mvcc",
+ Name: "hash_rev_duration_seconds",
+ Help: "The latency distribution of storage hash by revision operation.",
+
+ // 100 MB usually takes 100 ms, so start with 10 MB of 10 ms
+ // lowest bucket start of upper bound 0.01 sec (10 ms) with factor 2
+ // highest bucket start of 0.01 sec * 2^14 == 163.84 sec
+ Buckets: prometheus.ExponentialBuckets(.01, 2, 15),
+ })
+)
+
+func init() {
+ prometheus.MustRegister(rangeCounter)
+ prometheus.MustRegister(putCounter)
+ prometheus.MustRegister(deleteCounter)
+ prometheus.MustRegister(txnCounter)
+ prometheus.MustRegister(keysGauge)
+ prometheus.MustRegister(watchStreamGauge)
+ prometheus.MustRegister(watcherGauge)
+ prometheus.MustRegister(slowWatcherGauge)
+ prometheus.MustRegister(totalEventsCounter)
+ prometheus.MustRegister(pendingEventsGauge)
+ prometheus.MustRegister(indexCompactionPauseDurations)
+ prometheus.MustRegister(dbCompactionPauseDurations)
+ prometheus.MustRegister(dbCompactionTotalDurations)
+ prometheus.MustRegister(dbCompactionKeysCounter)
+ prometheus.MustRegister(dbTotalSizeDebugging)
+ prometheus.MustRegister(dbTotalSize)
+ prometheus.MustRegister(dbTotalSizeInUse)
+ prometheus.MustRegister(hashDurations)
+ prometheus.MustRegister(hashRevDurations)
+}
+
+// ReportEventReceived reports that an event is received.
+// This function should be called when the external systems received an
+// event from mvcc.Watcher.
+func ReportEventReceived(n int) {
+ pendingEventsGauge.Sub(float64(n))
+ totalEventsCounter.Add(float64(n))
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/metrics_txn.go b/vendor/github.com/coreos/etcd/mvcc/metrics_txn.go
new file mode 100644
index 00000000..911d6487
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/metrics_txn.go
@@ -0,0 +1,59 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "github.com/coreos/etcd/lease"
+)
+
+type metricsTxnWrite struct {
+ TxnWrite
+ ranges uint
+ puts uint
+ deletes uint
+}
+
+func newMetricsTxnRead(tr TxnRead) TxnRead {
+ return &metricsTxnWrite{&txnReadWrite{tr}, 0, 0, 0}
+}
+
+func newMetricsTxnWrite(tw TxnWrite) TxnWrite {
+ return &metricsTxnWrite{tw, 0, 0, 0}
+}
+
+func (tw *metricsTxnWrite) Range(key, end []byte, ro RangeOptions) (*RangeResult, error) {
+ tw.ranges++
+ return tw.TxnWrite.Range(key, end, ro)
+}
+
+func (tw *metricsTxnWrite) DeleteRange(key, end []byte) (n, rev int64) {
+ tw.deletes++
+ return tw.TxnWrite.DeleteRange(key, end)
+}
+
+func (tw *metricsTxnWrite) Put(key, value []byte, lease lease.LeaseID) (rev int64) {
+ tw.puts++
+ return tw.TxnWrite.Put(key, value, lease)
+}
+
+func (tw *metricsTxnWrite) End() {
+ defer tw.TxnWrite.End()
+ if sum := tw.ranges + tw.puts + tw.deletes; sum > 1 {
+ txnCounter.Inc()
+ }
+ rangeCounter.Add(float64(tw.ranges))
+ putCounter.Add(float64(tw.puts))
+ deleteCounter.Add(float64(tw.deletes))
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/mvccpb/kv.pb.go b/vendor/github.com/coreos/etcd/mvcc/mvccpb/kv.pb.go
new file mode 100644
index 00000000..23fe337a
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/mvccpb/kv.pb.go
@@ -0,0 +1,718 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: kv.proto
+
+/*
+ Package mvccpb is a generated protocol buffer package.
+
+ It is generated from these files:
+ kv.proto
+
+ It has these top-level messages:
+ KeyValue
+ Event
+*/
+package mvccpb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Event_EventType int32
+
+const (
+ PUT Event_EventType = 0
+ DELETE Event_EventType = 1
+)
+
+var Event_EventType_name = map[int32]string{
+ 0: "PUT",
+ 1: "DELETE",
+}
+var Event_EventType_value = map[string]int32{
+ "PUT": 0,
+ "DELETE": 1,
+}
+
+func (x Event_EventType) String() string {
+ return proto.EnumName(Event_EventType_name, int32(x))
+}
+func (Event_EventType) EnumDescriptor() ([]byte, []int) { return fileDescriptorKv, []int{1, 0} }
+
+type KeyValue struct {
+ // key is the key in bytes. An empty key is not allowed.
+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ // create_revision is the revision of last creation on this key.
+ CreateRevision int64 `protobuf:"varint,2,opt,name=create_revision,json=createRevision,proto3" json:"create_revision,omitempty"`
+ // mod_revision is the revision of last modification on this key.
+ ModRevision int64 `protobuf:"varint,3,opt,name=mod_revision,json=modRevision,proto3" json:"mod_revision,omitempty"`
+ // version is the version of the key. A deletion resets
+ // the version to zero and any modification of the key
+ // increases its version.
+ Version int64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"`
+ // value is the value held by the key, in bytes.
+ Value []byte `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"`
+ // lease is the ID of the lease that attached to key.
+ // When the attached lease expires, the key will be deleted.
+ // If lease is 0, then no lease is attached to the key.
+ Lease int64 `protobuf:"varint,6,opt,name=lease,proto3" json:"lease,omitempty"`
+}
+
+func (m *KeyValue) Reset() { *m = KeyValue{} }
+func (m *KeyValue) String() string { return proto.CompactTextString(m) }
+func (*KeyValue) ProtoMessage() {}
+func (*KeyValue) Descriptor() ([]byte, []int) { return fileDescriptorKv, []int{0} }
+
+type Event struct {
+ // type is the kind of event. If type is a PUT, it indicates
+ // new data has been stored to the key. If type is a DELETE,
+ // it indicates the key was deleted.
+ Type Event_EventType `protobuf:"varint,1,opt,name=type,proto3,enum=mvccpb.Event_EventType" json:"type,omitempty"`
+ // kv holds the KeyValue for the event.
+ // A PUT event contains current kv pair.
+ // A PUT event with kv.Version=1 indicates the creation of a key.
+ // A DELETE/EXPIRE event contains the deleted key with
+ // its modification revision set to the revision of deletion.
+ Kv *KeyValue `protobuf:"bytes,2,opt,name=kv" json:"kv,omitempty"`
+ // prev_kv holds the key-value pair before the event happens.
+ PrevKv *KeyValue `protobuf:"bytes,3,opt,name=prev_kv,json=prevKv" json:"prev_kv,omitempty"`
+}
+
+func (m *Event) Reset() { *m = Event{} }
+func (m *Event) String() string { return proto.CompactTextString(m) }
+func (*Event) ProtoMessage() {}
+func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorKv, []int{1} }
+
+func init() {
+ proto.RegisterType((*KeyValue)(nil), "mvccpb.KeyValue")
+ proto.RegisterType((*Event)(nil), "mvccpb.Event")
+ proto.RegisterEnum("mvccpb.Event_EventType", Event_EventType_name, Event_EventType_value)
+}
+func (m *KeyValue) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *KeyValue) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Key) > 0 {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(len(m.Key)))
+ i += copy(dAtA[i:], m.Key)
+ }
+ if m.CreateRevision != 0 {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(m.CreateRevision))
+ }
+ if m.ModRevision != 0 {
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(m.ModRevision))
+ }
+ if m.Version != 0 {
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(m.Version))
+ }
+ if len(m.Value) > 0 {
+ dAtA[i] = 0x2a
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(len(m.Value)))
+ i += copy(dAtA[i:], m.Value)
+ }
+ if m.Lease != 0 {
+ dAtA[i] = 0x30
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(m.Lease))
+ }
+ return i, nil
+}
+
+func (m *Event) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Event) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Type != 0 {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(m.Type))
+ }
+ if m.Kv != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(m.Kv.Size()))
+ n1, err := m.Kv.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ }
+ if m.PrevKv != nil {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintKv(dAtA, i, uint64(m.PrevKv.Size()))
+ n2, err := m.PrevKv.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n2
+ }
+ return i, nil
+}
+
+func encodeVarintKv(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *KeyValue) Size() (n int) {
+ var l int
+ _ = l
+ l = len(m.Key)
+ if l > 0 {
+ n += 1 + l + sovKv(uint64(l))
+ }
+ if m.CreateRevision != 0 {
+ n += 1 + sovKv(uint64(m.CreateRevision))
+ }
+ if m.ModRevision != 0 {
+ n += 1 + sovKv(uint64(m.ModRevision))
+ }
+ if m.Version != 0 {
+ n += 1 + sovKv(uint64(m.Version))
+ }
+ l = len(m.Value)
+ if l > 0 {
+ n += 1 + l + sovKv(uint64(l))
+ }
+ if m.Lease != 0 {
+ n += 1 + sovKv(uint64(m.Lease))
+ }
+ return n
+}
+
+func (m *Event) Size() (n int) {
+ var l int
+ _ = l
+ if m.Type != 0 {
+ n += 1 + sovKv(uint64(m.Type))
+ }
+ if m.Kv != nil {
+ l = m.Kv.Size()
+ n += 1 + l + sovKv(uint64(l))
+ }
+ if m.PrevKv != nil {
+ l = m.PrevKv.Size()
+ n += 1 + l + sovKv(uint64(l))
+ }
+ return n
+}
+
+func sovKv(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozKv(x uint64) (n int) {
+ return sovKv(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *KeyValue) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: KeyValue: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: KeyValue: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthKv
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
+ if m.Key == nil {
+ m.Key = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field CreateRevision", wireType)
+ }
+ m.CreateRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.CreateRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ModRevision", wireType)
+ }
+ m.ModRevision = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ModRevision |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
+ }
+ m.Version = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Version |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthKv
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
+ if m.Value == nil {
+ m.Value = []byte{}
+ }
+ iNdEx = postIndex
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Lease", wireType)
+ }
+ m.Lease = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Lease |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipKv(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthKv
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Event) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Event: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Event: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+ }
+ m.Type = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Type |= (Event_EventType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Kv", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthKv
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.Kv == nil {
+ m.Kv = &KeyValue{}
+ }
+ if err := m.Kv.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field PrevKv", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthKv
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if m.PrevKv == nil {
+ m.PrevKv = &KeyValue{}
+ }
+ if err := m.PrevKv.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipKv(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthKv
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipKv(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthKv
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowKv
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipKv(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthKv = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowKv = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("kv.proto", fileDescriptorKv) }
+
+var fileDescriptorKv = []byte{
+ // 303 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x41, 0x4e, 0xc2, 0x40,
+ 0x14, 0x86, 0x3b, 0x14, 0x0a, 0x3e, 0x08, 0x36, 0x13, 0x12, 0x27, 0x2e, 0x26, 0x95, 0x8d, 0x18,
+ 0x13, 0x4c, 0xf0, 0x06, 0xc6, 0xae, 0x70, 0x61, 0x1a, 0x74, 0x4b, 0x4a, 0x79, 0x21, 0xa4, 0x94,
+ 0x69, 0x4a, 0x9d, 0xa4, 0x37, 0x71, 0xef, 0xde, 0x73, 0xb0, 0xe4, 0x08, 0x52, 0x2f, 0x62, 0xfa,
+ 0xc6, 0xe2, 0xc6, 0xcd, 0xe4, 0xfd, 0xff, 0xff, 0x65, 0xe6, 0x7f, 0x03, 0x9d, 0x58, 0x8f, 0xd3,
+ 0x4c, 0xe5, 0x8a, 0x3b, 0x89, 0x8e, 0xa2, 0x74, 0x71, 0x39, 0x58, 0xa9, 0x95, 0x22, 0xeb, 0xae,
+ 0x9a, 0x4c, 0x3a, 0xfc, 0x64, 0xd0, 0x99, 0x62, 0xf1, 0x1a, 0x6e, 0xde, 0x90, 0xbb, 0x60, 0xc7,
+ 0x58, 0x08, 0xe6, 0xb1, 0x51, 0x2f, 0xa8, 0x46, 0x7e, 0x0d, 0xe7, 0x51, 0x86, 0x61, 0x8e, 0xf3,
+ 0x0c, 0xf5, 0x7a, 0xb7, 0x56, 0x5b, 0xd1, 0xf0, 0xd8, 0xc8, 0x0e, 0xfa, 0xc6, 0x0e, 0x7e, 0x5d,
+ 0x7e, 0x05, 0xbd, 0x44, 0x2d, 0xff, 0x28, 0x9b, 0xa8, 0x6e, 0xa2, 0x96, 0x27, 0x44, 0x40, 0x5b,
+ 0x63, 0x46, 0x69, 0x93, 0xd2, 0x5a, 0xf2, 0x01, 0xb4, 0x74, 0x55, 0x40, 0xb4, 0xe8, 0x65, 0x23,
+ 0x2a, 0x77, 0x83, 0xe1, 0x0e, 0x85, 0x43, 0xb4, 0x11, 0xc3, 0x0f, 0x06, 0x2d, 0x5f, 0xe3, 0x36,
+ 0xe7, 0xb7, 0xd0, 0xcc, 0x8b, 0x14, 0xa9, 0x6e, 0x7f, 0x72, 0x31, 0x36, 0x7b, 0x8e, 0x29, 0x34,
+ 0xe7, 0xac, 0x48, 0x31, 0x20, 0x88, 0x7b, 0xd0, 0x88, 0x35, 0x75, 0xef, 0x4e, 0xdc, 0x1a, 0xad,
+ 0x17, 0x0f, 0x1a, 0xb1, 0xe6, 0x37, 0xd0, 0x4e, 0x33, 0xd4, 0xf3, 0x58, 0x53, 0xf9, 0xff, 0x30,
+ 0xa7, 0x02, 0xa6, 0x7a, 0xe8, 0xc1, 0xd9, 0xe9, 0x7e, 0xde, 0x06, 0xfb, 0xf9, 0x65, 0xe6, 0x5a,
+ 0x1c, 0xc0, 0x79, 0xf4, 0x9f, 0xfc, 0x99, 0xef, 0xb2, 0x07, 0xb1, 0x3f, 0x4a, 0xeb, 0x70, 0x94,
+ 0xd6, 0xbe, 0x94, 0xec, 0x50, 0x4a, 0xf6, 0x55, 0x4a, 0xf6, 0xfe, 0x2d, 0xad, 0x85, 0x43, 0xff,
+ 0x7e, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xb5, 0x45, 0x92, 0x5d, 0xa1, 0x01, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/revision.go b/vendor/github.com/coreos/etcd/mvcc/revision.go
new file mode 100644
index 00000000..5fa35a1c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/revision.go
@@ -0,0 +1,67 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import "encoding/binary"
+
+// revBytesLen is the byte length of a normal revision.
+// First 8 bytes is the revision.main in big-endian format. The 9th byte
+// is a '_'. The last 8 bytes is the revision.sub in big-endian format.
+const revBytesLen = 8 + 1 + 8
+
+// A revision indicates modification of the key-value space.
+// The set of changes that share same main revision changes the key-value space atomically.
+type revision struct {
+ // main is the main revision of a set of changes that happen atomically.
+ main int64
+
+ // sub is the the sub revision of a change in a set of changes that happen
+ // atomically. Each change has different increasing sub revision in that
+ // set.
+ sub int64
+}
+
+func (a revision) GreaterThan(b revision) bool {
+ if a.main > b.main {
+ return true
+ }
+ if a.main < b.main {
+ return false
+ }
+ return a.sub > b.sub
+}
+
+func newRevBytes() []byte {
+ return make([]byte, revBytesLen, markedRevBytesLen)
+}
+
+func revToBytes(rev revision, bytes []byte) {
+ binary.BigEndian.PutUint64(bytes, uint64(rev.main))
+ bytes[8] = '_'
+ binary.BigEndian.PutUint64(bytes[9:], uint64(rev.sub))
+}
+
+func bytesToRev(bytes []byte) revision {
+ return revision{
+ main: int64(binary.BigEndian.Uint64(bytes[0:8])),
+ sub: int64(binary.BigEndian.Uint64(bytes[9:])),
+ }
+}
+
+type revisions []revision
+
+func (a revisions) Len() int { return len(a) }
+func (a revisions) Less(i, j int) bool { return a[j].GreaterThan(a[i]) }
+func (a revisions) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
diff --git a/vendor/github.com/coreos/etcd/mvcc/util.go b/vendor/github.com/coreos/etcd/mvcc/util.go
new file mode 100644
index 00000000..8a0df0bf
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/util.go
@@ -0,0 +1,56 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "encoding/binary"
+
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/mvcc/mvccpb"
+)
+
+func UpdateConsistentIndex(be backend.Backend, index uint64) {
+ tx := be.BatchTx()
+ tx.Lock()
+ defer tx.Unlock()
+
+ var oldi uint64
+ _, vs := tx.UnsafeRange(metaBucketName, consistentIndexKeyName, nil, 0)
+ if len(vs) != 0 {
+ oldi = binary.BigEndian.Uint64(vs[0])
+ }
+
+ if index <= oldi {
+ return
+ }
+
+ bs := make([]byte, 8)
+ binary.BigEndian.PutUint64(bs, index)
+ tx.UnsafePut(metaBucketName, consistentIndexKeyName, bs)
+}
+
+func WriteKV(be backend.Backend, kv mvccpb.KeyValue) {
+ ibytes := newRevBytes()
+ revToBytes(revision{main: kv.ModRevision}, ibytes)
+
+ d, err := kv.Marshal()
+ if err != nil {
+ plog.Fatalf("cannot marshal event: %v", err)
+ }
+
+ be.BatchTx().Lock()
+ be.BatchTx().UnsafePut(keyBucketName, ibytes, d)
+ be.BatchTx().Unlock()
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/watchable_store.go b/vendor/github.com/coreos/etcd/mvcc/watchable_store.go
new file mode 100644
index 00000000..78df1932
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/watchable_store.go
@@ -0,0 +1,534 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/lease"
+ "github.com/coreos/etcd/mvcc/backend"
+ "github.com/coreos/etcd/mvcc/mvccpb"
+)
+
+// non-const so modifiable by tests
+var (
+ // chanBufLen is the length of the buffered chan
+ // for sending out watched events.
+ // TODO: find a good buf value. 1024 is just a random one that
+ // seems to be reasonable.
+ chanBufLen = 1024
+
+ // maxWatchersPerSync is the number of watchers to sync in a single batch
+ maxWatchersPerSync = 512
+)
+
+type watchable interface {
+ watch(key, end []byte, startRev int64, id WatchID, ch chan<- WatchResponse, fcs ...FilterFunc) (*watcher, cancelFunc)
+ progress(w *watcher)
+ rev() int64
+}
+
+type watchableStore struct {
+ *store
+
+ // mu protects watcher groups and batches. It should never be locked
+ // before locking store.mu to avoid deadlock.
+ mu sync.RWMutex
+
+ // victims are watcher batches that were blocked on the watch channel
+ victims []watcherBatch
+ victimc chan struct{}
+
+ // contains all unsynced watchers that needs to sync with events that have happened
+ unsynced watcherGroup
+
+ // contains all synced watchers that are in sync with the progress of the store.
+ // The key of the map is the key that the watcher watches on.
+ synced watcherGroup
+
+ stopc chan struct{}
+ wg sync.WaitGroup
+}
+
+// cancelFunc updates unsynced and synced maps when running
+// cancel operations.
+type cancelFunc func()
+
+func New(b backend.Backend, le lease.Lessor, ig ConsistentIndexGetter) ConsistentWatchableKV {
+ return newWatchableStore(b, le, ig)
+}
+
+func newWatchableStore(b backend.Backend, le lease.Lessor, ig ConsistentIndexGetter) *watchableStore {
+ s := &watchableStore{
+ store: NewStore(b, le, ig),
+ victimc: make(chan struct{}, 1),
+ unsynced: newWatcherGroup(),
+ synced: newWatcherGroup(),
+ stopc: make(chan struct{}),
+ }
+ s.store.ReadView = &readView{s}
+ s.store.WriteView = &writeView{s}
+ if s.le != nil {
+ // use this store as the deleter so revokes trigger watch events
+ s.le.SetRangeDeleter(func() lease.TxnDelete { return s.Write() })
+ }
+ s.wg.Add(2)
+ go s.syncWatchersLoop()
+ go s.syncVictimsLoop()
+ return s
+}
+
+func (s *watchableStore) Close() error {
+ close(s.stopc)
+ s.wg.Wait()
+ return s.store.Close()
+}
+
+func (s *watchableStore) NewWatchStream() WatchStream {
+ watchStreamGauge.Inc()
+ return &watchStream{
+ watchable: s,
+ ch: make(chan WatchResponse, chanBufLen),
+ cancels: make(map[WatchID]cancelFunc),
+ watchers: make(map[WatchID]*watcher),
+ }
+}
+
+func (s *watchableStore) watch(key, end []byte, startRev int64, id WatchID, ch chan<- WatchResponse, fcs ...FilterFunc) (*watcher, cancelFunc) {
+ wa := &watcher{
+ key: key,
+ end: end,
+ minRev: startRev,
+ id: id,
+ ch: ch,
+ fcs: fcs,
+ }
+
+ s.mu.Lock()
+ s.revMu.RLock()
+ synced := startRev > s.store.currentRev || startRev == 0
+ if synced {
+ wa.minRev = s.store.currentRev + 1
+ if startRev > wa.minRev {
+ wa.minRev = startRev
+ }
+ }
+ if synced {
+ s.synced.add(wa)
+ } else {
+ slowWatcherGauge.Inc()
+ s.unsynced.add(wa)
+ }
+ s.revMu.RUnlock()
+ s.mu.Unlock()
+
+ watcherGauge.Inc()
+
+ return wa, func() { s.cancelWatcher(wa) }
+}
+
+// cancelWatcher removes references of the watcher from the watchableStore
+func (s *watchableStore) cancelWatcher(wa *watcher) {
+ for {
+ s.mu.Lock()
+ if s.unsynced.delete(wa) {
+ slowWatcherGauge.Dec()
+ break
+ } else if s.synced.delete(wa) {
+ break
+ } else if wa.compacted {
+ break
+ } else if wa.ch == nil {
+ // already canceled (e.g., cancel/close race)
+ break
+ }
+
+ if !wa.victim {
+ panic("watcher not victim but not in watch groups")
+ }
+
+ var victimBatch watcherBatch
+ for _, wb := range s.victims {
+ if wb[wa] != nil {
+ victimBatch = wb
+ break
+ }
+ }
+ if victimBatch != nil {
+ slowWatcherGauge.Dec()
+ delete(victimBatch, wa)
+ break
+ }
+
+ // victim being processed so not accessible; retry
+ s.mu.Unlock()
+ time.Sleep(time.Millisecond)
+ }
+
+ watcherGauge.Dec()
+ wa.ch = nil
+ s.mu.Unlock()
+}
+
+func (s *watchableStore) Restore(b backend.Backend) error {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ err := s.store.Restore(b)
+ if err != nil {
+ return err
+ }
+
+ for wa := range s.synced.watchers {
+ wa.restore = true
+ s.unsynced.add(wa)
+ }
+ s.synced = newWatcherGroup()
+ return nil
+}
+
+// syncWatchersLoop syncs the watcher in the unsynced map every 100ms.
+func (s *watchableStore) syncWatchersLoop() {
+ defer s.wg.Done()
+
+ for {
+ s.mu.RLock()
+ st := time.Now()
+ lastUnsyncedWatchers := s.unsynced.size()
+ s.mu.RUnlock()
+
+ unsyncedWatchers := 0
+ if lastUnsyncedWatchers > 0 {
+ unsyncedWatchers = s.syncWatchers()
+ }
+ syncDuration := time.Since(st)
+
+ waitDuration := 100 * time.Millisecond
+ // more work pending?
+ if unsyncedWatchers != 0 && lastUnsyncedWatchers > unsyncedWatchers {
+ // be fair to other store operations by yielding time taken
+ waitDuration = syncDuration
+ }
+
+ select {
+ case <-time.After(waitDuration):
+ case <-s.stopc:
+ return
+ }
+ }
+}
+
+// syncVictimsLoop tries to write precomputed watcher responses to
+// watchers that had a blocked watcher channel
+func (s *watchableStore) syncVictimsLoop() {
+ defer s.wg.Done()
+
+ for {
+ for s.moveVictims() != 0 {
+ // try to update all victim watchers
+ }
+ s.mu.RLock()
+ isEmpty := len(s.victims) == 0
+ s.mu.RUnlock()
+
+ var tickc <-chan time.Time
+ if !isEmpty {
+ tickc = time.After(10 * time.Millisecond)
+ }
+
+ select {
+ case <-tickc:
+ case <-s.victimc:
+ case <-s.stopc:
+ return
+ }
+ }
+}
+
+// moveVictims tries to update watches with already pending event data
+func (s *watchableStore) moveVictims() (moved int) {
+ s.mu.Lock()
+ victims := s.victims
+ s.victims = nil
+ s.mu.Unlock()
+
+ var newVictim watcherBatch
+ for _, wb := range victims {
+ // try to send responses again
+ for w, eb := range wb {
+ // watcher has observed the store up to, but not including, w.minRev
+ rev := w.minRev - 1
+ if w.send(WatchResponse{WatchID: w.id, Events: eb.evs, Revision: rev}) {
+ pendingEventsGauge.Add(float64(len(eb.evs)))
+ } else {
+ if newVictim == nil {
+ newVictim = make(watcherBatch)
+ }
+ newVictim[w] = eb
+ continue
+ }
+ moved++
+ }
+
+ // assign completed victim watchers to unsync/sync
+ s.mu.Lock()
+ s.store.revMu.RLock()
+ curRev := s.store.currentRev
+ for w, eb := range wb {
+ if newVictim != nil && newVictim[w] != nil {
+ // couldn't send watch response; stays victim
+ continue
+ }
+ w.victim = false
+ if eb.moreRev != 0 {
+ w.minRev = eb.moreRev
+ }
+ if w.minRev <= curRev {
+ s.unsynced.add(w)
+ } else {
+ slowWatcherGauge.Dec()
+ s.synced.add(w)
+ }
+ }
+ s.store.revMu.RUnlock()
+ s.mu.Unlock()
+ }
+
+ if len(newVictim) > 0 {
+ s.mu.Lock()
+ s.victims = append(s.victims, newVictim)
+ s.mu.Unlock()
+ }
+
+ return moved
+}
+
+// syncWatchers syncs unsynced watchers by:
+// 1. choose a set of watchers from the unsynced watcher group
+// 2. iterate over the set to get the minimum revision and remove compacted watchers
+// 3. use minimum revision to get all key-value pairs and send those events to watchers
+// 4. remove synced watchers in set from unsynced group and move to synced group
+func (s *watchableStore) syncWatchers() int {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+
+ if s.unsynced.size() == 0 {
+ return 0
+ }
+
+ s.store.revMu.RLock()
+ defer s.store.revMu.RUnlock()
+
+ // in order to find key-value pairs from unsynced watchers, we need to
+ // find min revision index, and these revisions can be used to
+ // query the backend store of key-value pairs
+ curRev := s.store.currentRev
+ compactionRev := s.store.compactMainRev
+
+ wg, minRev := s.unsynced.choose(maxWatchersPerSync, curRev, compactionRev)
+ minBytes, maxBytes := newRevBytes(), newRevBytes()
+ revToBytes(revision{main: minRev}, minBytes)
+ revToBytes(revision{main: curRev + 1}, maxBytes)
+
+ // UnsafeRange returns keys and values. And in boltdb, keys are revisions.
+ // values are actual key-value pairs in backend.
+ tx := s.store.b.ReadTx()
+ tx.Lock()
+ revs, vs := tx.UnsafeRange(keyBucketName, minBytes, maxBytes, 0)
+ evs := kvsToEvents(wg, revs, vs)
+ tx.Unlock()
+
+ var victims watcherBatch
+ wb := newWatcherBatch(wg, evs)
+ for w := range wg.watchers {
+ w.minRev = curRev + 1
+
+ eb, ok := wb[w]
+ if !ok {
+ // bring un-notified watcher to synced
+ s.synced.add(w)
+ s.unsynced.delete(w)
+ continue
+ }
+
+ if eb.moreRev != 0 {
+ w.minRev = eb.moreRev
+ }
+
+ if w.send(WatchResponse{WatchID: w.id, Events: eb.evs, Revision: curRev}) {
+ pendingEventsGauge.Add(float64(len(eb.evs)))
+ } else {
+ if victims == nil {
+ victims = make(watcherBatch)
+ }
+ w.victim = true
+ }
+
+ if w.victim {
+ victims[w] = eb
+ } else {
+ if eb.moreRev != 0 {
+ // stay unsynced; more to read
+ continue
+ }
+ s.synced.add(w)
+ }
+ s.unsynced.delete(w)
+ }
+ s.addVictim(victims)
+
+ vsz := 0
+ for _, v := range s.victims {
+ vsz += len(v)
+ }
+ slowWatcherGauge.Set(float64(s.unsynced.size() + vsz))
+
+ return s.unsynced.size()
+}
+
+// kvsToEvents gets all events for the watchers from all key-value pairs
+func kvsToEvents(wg *watcherGroup, revs, vals [][]byte) (evs []mvccpb.Event) {
+ for i, v := range vals {
+ var kv mvccpb.KeyValue
+ if err := kv.Unmarshal(v); err != nil {
+ plog.Panicf("cannot unmarshal event: %v", err)
+ }
+
+ if !wg.contains(string(kv.Key)) {
+ continue
+ }
+
+ ty := mvccpb.PUT
+ if isTombstone(revs[i]) {
+ ty = mvccpb.DELETE
+ // patch in mod revision so watchers won't skip
+ kv.ModRevision = bytesToRev(revs[i]).main
+ }
+ evs = append(evs, mvccpb.Event{Kv: &kv, Type: ty})
+ }
+ return evs
+}
+
+// notify notifies the fact that given event at the given rev just happened to
+// watchers that watch on the key of the event.
+func (s *watchableStore) notify(rev int64, evs []mvccpb.Event) {
+ var victim watcherBatch
+ for w, eb := range newWatcherBatch(&s.synced, evs) {
+ if eb.revs != 1 {
+ plog.Panicf("unexpected multiple revisions in notification")
+ }
+ if w.send(WatchResponse{WatchID: w.id, Events: eb.evs, Revision: rev}) {
+ pendingEventsGauge.Add(float64(len(eb.evs)))
+ } else {
+ // move slow watcher to victims
+ w.minRev = rev + 1
+ if victim == nil {
+ victim = make(watcherBatch)
+ }
+ w.victim = true
+ victim[w] = eb
+ s.synced.delete(w)
+ slowWatcherGauge.Inc()
+ }
+ }
+ s.addVictim(victim)
+}
+
+func (s *watchableStore) addVictim(victim watcherBatch) {
+ if victim == nil {
+ return
+ }
+ s.victims = append(s.victims, victim)
+ select {
+ case s.victimc <- struct{}{}:
+ default:
+ }
+}
+
+func (s *watchableStore) rev() int64 { return s.store.Rev() }
+
+func (s *watchableStore) progress(w *watcher) {
+ s.mu.RLock()
+ defer s.mu.RUnlock()
+
+ if _, ok := s.synced.watchers[w]; ok {
+ w.send(WatchResponse{WatchID: w.id, Revision: s.rev()})
+ // If the ch is full, this watcher is receiving events.
+ // We do not need to send progress at all.
+ }
+}
+
+type watcher struct {
+ // the watcher key
+ key []byte
+ // end indicates the end of the range to watch.
+ // If end is set, the watcher is on a range.
+ end []byte
+
+ // victim is set when ch is blocked and undergoing victim processing
+ victim bool
+
+ // compacted is set when the watcher is removed because of compaction
+ compacted bool
+
+ // restore is true when the watcher is being restored from leader snapshot
+ // which means that this watcher has just been moved from "synced" to "unsynced"
+ // watcher group, possibly with a future revision when it was first added
+ // to the synced watcher
+ // "unsynced" watcher revision must always be <= current revision,
+ // except when the watcher were to be moved from "synced" watcher group
+ restore bool
+
+ // minRev is the minimum revision update the watcher will accept
+ minRev int64
+ id WatchID
+
+ fcs []FilterFunc
+ // a chan to send out the watch response.
+ // The chan might be shared with other watchers.
+ ch chan<- WatchResponse
+}
+
+func (w *watcher) send(wr WatchResponse) bool {
+ progressEvent := len(wr.Events) == 0
+
+ if len(w.fcs) != 0 {
+ ne := make([]mvccpb.Event, 0, len(wr.Events))
+ for i := range wr.Events {
+ filtered := false
+ for _, filter := range w.fcs {
+ if filter(wr.Events[i]) {
+ filtered = true
+ break
+ }
+ }
+ if !filtered {
+ ne = append(ne, wr.Events[i])
+ }
+ }
+ wr.Events = ne
+ }
+
+ // if all events are filtered out, we should send nothing.
+ if !progressEvent && len(wr.Events) == 0 {
+ return true
+ }
+ select {
+ case w.ch <- wr:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/watchable_store_txn.go b/vendor/github.com/coreos/etcd/mvcc/watchable_store_txn.go
new file mode 100644
index 00000000..5c5bfda1
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/watchable_store_txn.go
@@ -0,0 +1,53 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "github.com/coreos/etcd/mvcc/mvccpb"
+)
+
+func (tw *watchableStoreTxnWrite) End() {
+ changes := tw.Changes()
+ if len(changes) == 0 {
+ tw.TxnWrite.End()
+ return
+ }
+
+ rev := tw.Rev() + 1
+ evs := make([]mvccpb.Event, len(changes))
+ for i, change := range changes {
+ evs[i].Kv = &changes[i]
+ if change.CreateRevision == 0 {
+ evs[i].Type = mvccpb.DELETE
+ evs[i].Kv.ModRevision = rev
+ } else {
+ evs[i].Type = mvccpb.PUT
+ }
+ }
+
+ // end write txn under watchable store lock so the updates are visible
+ // when asynchronous event posting checks the current store revision
+ tw.s.mu.Lock()
+ tw.s.notify(rev, evs)
+ tw.TxnWrite.End()
+ tw.s.mu.Unlock()
+}
+
+type watchableStoreTxnWrite struct {
+ TxnWrite
+ s *watchableStore
+}
+
+func (s *watchableStore) Write() TxnWrite { return &watchableStoreTxnWrite{s.store.Write(), s} }
diff --git a/vendor/github.com/coreos/etcd/mvcc/watcher.go b/vendor/github.com/coreos/etcd/mvcc/watcher.go
new file mode 100644
index 00000000..bc0c6322
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/watcher.go
@@ -0,0 +1,180 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "bytes"
+ "errors"
+ "sync"
+
+ "github.com/coreos/etcd/mvcc/mvccpb"
+)
+
+var (
+ ErrWatcherNotExist = errors.New("mvcc: watcher does not exist")
+)
+
+type WatchID int64
+
+// FilterFunc returns true if the given event should be filtered out.
+type FilterFunc func(e mvccpb.Event) bool
+
+type WatchStream interface {
+ // Watch creates a watcher. The watcher watches the events happening or
+ // happened on the given key or range [key, end) from the given startRev.
+ //
+ // The whole event history can be watched unless compacted.
+ // If `startRev` <=0, watch observes events after currentRev.
+ //
+ // The returned `id` is the ID of this watcher. It appears as WatchID
+ // in events that are sent to the created watcher through stream channel.
+ //
+ Watch(key, end []byte, startRev int64, fcs ...FilterFunc) WatchID
+
+ // Chan returns a chan. All watch response will be sent to the returned chan.
+ Chan() <-chan WatchResponse
+
+ // RequestProgress requests the progress of the watcher with given ID. The response
+ // will only be sent if the watcher is currently synced.
+ // The responses will be sent through the WatchRespone Chan attached
+ // with this stream to ensure correct ordering.
+ // The responses contains no events. The revision in the response is the progress
+ // of the watchers since the watcher is currently synced.
+ RequestProgress(id WatchID)
+
+ // Cancel cancels a watcher by giving its ID. If watcher does not exist, an error will be
+ // returned.
+ Cancel(id WatchID) error
+
+ // Close closes Chan and release all related resources.
+ Close()
+
+ // Rev returns the current revision of the KV the stream watches on.
+ Rev() int64
+}
+
+type WatchResponse struct {
+ // WatchID is the WatchID of the watcher this response sent to.
+ WatchID WatchID
+
+ // Events contains all the events that needs to send.
+ Events []mvccpb.Event
+
+ // Revision is the revision of the KV when the watchResponse is created.
+ // For a normal response, the revision should be the same as the last
+ // modified revision inside Events. For a delayed response to a unsynced
+ // watcher, the revision is greater than the last modified revision
+ // inside Events.
+ Revision int64
+
+ // CompactRevision is set when the watcher is cancelled due to compaction.
+ CompactRevision int64
+}
+
+// watchStream contains a collection of watchers that share
+// one streaming chan to send out watched events and other control events.
+type watchStream struct {
+ watchable watchable
+ ch chan WatchResponse
+
+ mu sync.Mutex // guards fields below it
+ // nextID is the ID pre-allocated for next new watcher in this stream
+ nextID WatchID
+ closed bool
+ cancels map[WatchID]cancelFunc
+ watchers map[WatchID]*watcher
+}
+
+// Watch creates a new watcher in the stream and returns its WatchID.
+// TODO: return error if ws is closed?
+func (ws *watchStream) Watch(key, end []byte, startRev int64, fcs ...FilterFunc) WatchID {
+ // prevent wrong range where key >= end lexicographically
+ // watch request with 'WithFromKey' has empty-byte range end
+ if len(end) != 0 && bytes.Compare(key, end) != -1 {
+ return -1
+ }
+
+ ws.mu.Lock()
+ defer ws.mu.Unlock()
+ if ws.closed {
+ return -1
+ }
+
+ id := ws.nextID
+ ws.nextID++
+
+ w, c := ws.watchable.watch(key, end, startRev, id, ws.ch, fcs...)
+
+ ws.cancels[id] = c
+ ws.watchers[id] = w
+ return id
+}
+
+func (ws *watchStream) Chan() <-chan WatchResponse {
+ return ws.ch
+}
+
+func (ws *watchStream) Cancel(id WatchID) error {
+ ws.mu.Lock()
+ cancel, ok := ws.cancels[id]
+ w := ws.watchers[id]
+ ok = ok && !ws.closed
+ ws.mu.Unlock()
+
+ if !ok {
+ return ErrWatcherNotExist
+ }
+ cancel()
+
+ ws.mu.Lock()
+ // The watch isn't removed until cancel so that if Close() is called,
+ // it will wait for the cancel. Otherwise, Close() could close the
+ // watch channel while the store is still posting events.
+ if ww := ws.watchers[id]; ww == w {
+ delete(ws.cancels, id)
+ delete(ws.watchers, id)
+ }
+ ws.mu.Unlock()
+
+ return nil
+}
+
+func (ws *watchStream) Close() {
+ ws.mu.Lock()
+ defer ws.mu.Unlock()
+
+ for _, cancel := range ws.cancels {
+ cancel()
+ }
+ ws.closed = true
+ close(ws.ch)
+ watchStreamGauge.Dec()
+}
+
+func (ws *watchStream) Rev() int64 {
+ ws.mu.Lock()
+ defer ws.mu.Unlock()
+ return ws.watchable.rev()
+}
+
+func (ws *watchStream) RequestProgress(id WatchID) {
+ ws.mu.Lock()
+ w, ok := ws.watchers[id]
+ ws.mu.Unlock()
+ if !ok {
+ return
+ }
+ ws.watchable.progress(w)
+}
diff --git a/vendor/github.com/coreos/etcd/mvcc/watcher_group.go b/vendor/github.com/coreos/etcd/mvcc/watcher_group.go
new file mode 100644
index 00000000..b65c7bc5
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/mvcc/watcher_group.go
@@ -0,0 +1,292 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mvcc
+
+import (
+ "fmt"
+ "math"
+
+ "github.com/coreos/etcd/mvcc/mvccpb"
+ "github.com/coreos/etcd/pkg/adt"
+)
+
+var (
+ // watchBatchMaxRevs is the maximum distinct revisions that
+ // may be sent to an unsynced watcher at a time. Declared as
+ // var instead of const for testing purposes.
+ watchBatchMaxRevs = 1000
+)
+
+type eventBatch struct {
+ // evs is a batch of revision-ordered events
+ evs []mvccpb.Event
+ // revs is the minimum unique revisions observed for this batch
+ revs int
+ // moreRev is first revision with more events following this batch
+ moreRev int64
+}
+
+func (eb *eventBatch) add(ev mvccpb.Event) {
+ if eb.revs > watchBatchMaxRevs {
+ // maxed out batch size
+ return
+ }
+
+ if len(eb.evs) == 0 {
+ // base case
+ eb.revs = 1
+ eb.evs = append(eb.evs, ev)
+ return
+ }
+
+ // revision accounting
+ ebRev := eb.evs[len(eb.evs)-1].Kv.ModRevision
+ evRev := ev.Kv.ModRevision
+ if evRev > ebRev {
+ eb.revs++
+ if eb.revs > watchBatchMaxRevs {
+ eb.moreRev = evRev
+ return
+ }
+ }
+
+ eb.evs = append(eb.evs, ev)
+}
+
+type watcherBatch map[*watcher]*eventBatch
+
+func (wb watcherBatch) add(w *watcher, ev mvccpb.Event) {
+ eb := wb[w]
+ if eb == nil {
+ eb = &eventBatch{}
+ wb[w] = eb
+ }
+ eb.add(ev)
+}
+
+// newWatcherBatch maps watchers to their matched events. It enables quick
+// events look up by watcher.
+func newWatcherBatch(wg *watcherGroup, evs []mvccpb.Event) watcherBatch {
+ if len(wg.watchers) == 0 {
+ return nil
+ }
+
+ wb := make(watcherBatch)
+ for _, ev := range evs {
+ for w := range wg.watcherSetByKey(string(ev.Kv.Key)) {
+ if ev.Kv.ModRevision >= w.minRev {
+ // don't double notify
+ wb.add(w, ev)
+ }
+ }
+ }
+ return wb
+}
+
+type watcherSet map[*watcher]struct{}
+
+func (w watcherSet) add(wa *watcher) {
+ if _, ok := w[wa]; ok {
+ panic("add watcher twice!")
+ }
+ w[wa] = struct{}{}
+}
+
+func (w watcherSet) union(ws watcherSet) {
+ for wa := range ws {
+ w.add(wa)
+ }
+}
+
+func (w watcherSet) delete(wa *watcher) {
+ if _, ok := w[wa]; !ok {
+ panic("removing missing watcher!")
+ }
+ delete(w, wa)
+}
+
+type watcherSetByKey map[string]watcherSet
+
+func (w watcherSetByKey) add(wa *watcher) {
+ set := w[string(wa.key)]
+ if set == nil {
+ set = make(watcherSet)
+ w[string(wa.key)] = set
+ }
+ set.add(wa)
+}
+
+func (w watcherSetByKey) delete(wa *watcher) bool {
+ k := string(wa.key)
+ if v, ok := w[k]; ok {
+ if _, ok := v[wa]; ok {
+ delete(v, wa)
+ if len(v) == 0 {
+ // remove the set; nothing left
+ delete(w, k)
+ }
+ return true
+ }
+ }
+ return false
+}
+
+// watcherGroup is a collection of watchers organized by their ranges
+type watcherGroup struct {
+ // keyWatchers has the watchers that watch on a single key
+ keyWatchers watcherSetByKey
+ // ranges has the watchers that watch a range; it is sorted by interval
+ ranges adt.IntervalTree
+ // watchers is the set of all watchers
+ watchers watcherSet
+}
+
+func newWatcherGroup() watcherGroup {
+ return watcherGroup{
+ keyWatchers: make(watcherSetByKey),
+ watchers: make(watcherSet),
+ }
+}
+
+// add puts a watcher in the group.
+func (wg *watcherGroup) add(wa *watcher) {
+ wg.watchers.add(wa)
+ if wa.end == nil {
+ wg.keyWatchers.add(wa)
+ return
+ }
+
+ // interval already registered?
+ ivl := adt.NewStringAffineInterval(string(wa.key), string(wa.end))
+ if iv := wg.ranges.Find(ivl); iv != nil {
+ iv.Val.(watcherSet).add(wa)
+ return
+ }
+
+ // not registered, put in interval tree
+ ws := make(watcherSet)
+ ws.add(wa)
+ wg.ranges.Insert(ivl, ws)
+}
+
+// contains is whether the given key has a watcher in the group.
+func (wg *watcherGroup) contains(key string) bool {
+ _, ok := wg.keyWatchers[key]
+ return ok || wg.ranges.Intersects(adt.NewStringAffinePoint(key))
+}
+
+// size gives the number of unique watchers in the group.
+func (wg *watcherGroup) size() int { return len(wg.watchers) }
+
+// delete removes a watcher from the group.
+func (wg *watcherGroup) delete(wa *watcher) bool {
+ if _, ok := wg.watchers[wa]; !ok {
+ return false
+ }
+ wg.watchers.delete(wa)
+ if wa.end == nil {
+ wg.keyWatchers.delete(wa)
+ return true
+ }
+
+ ivl := adt.NewStringAffineInterval(string(wa.key), string(wa.end))
+ iv := wg.ranges.Find(ivl)
+ if iv == nil {
+ return false
+ }
+
+ ws := iv.Val.(watcherSet)
+ delete(ws, wa)
+ if len(ws) == 0 {
+ // remove interval missing watchers
+ if ok := wg.ranges.Delete(ivl); !ok {
+ panic("could not remove watcher from interval tree")
+ }
+ }
+
+ return true
+}
+
+// choose selects watchers from the watcher group to update
+func (wg *watcherGroup) choose(maxWatchers int, curRev, compactRev int64) (*watcherGroup, int64) {
+ if len(wg.watchers) < maxWatchers {
+ return wg, wg.chooseAll(curRev, compactRev)
+ }
+ ret := newWatcherGroup()
+ for w := range wg.watchers {
+ if maxWatchers <= 0 {
+ break
+ }
+ maxWatchers--
+ ret.add(w)
+ }
+ return &ret, ret.chooseAll(curRev, compactRev)
+}
+
+func (wg *watcherGroup) chooseAll(curRev, compactRev int64) int64 {
+ minRev := int64(math.MaxInt64)
+ for w := range wg.watchers {
+ if w.minRev > curRev {
+ // after network partition, possibly choosing future revision watcher from restore operation
+ // with watch key "proxy-namespace__lostleader" and revision "math.MaxInt64 - 2"
+ // do not panic when such watcher had been moved from "synced" watcher during restore operation
+ if !w.restore {
+ panic(fmt.Errorf("watcher minimum revision %d should not exceed current revision %d", w.minRev, curRev))
+ }
+
+ // mark 'restore' done, since it's chosen
+ w.restore = false
+ }
+ if w.minRev < compactRev {
+ select {
+ case w.ch <- WatchResponse{WatchID: w.id, CompactRevision: compactRev}:
+ w.compacted = true
+ wg.delete(w)
+ default:
+ // retry next time
+ }
+ continue
+ }
+ if minRev > w.minRev {
+ minRev = w.minRev
+ }
+ }
+ return minRev
+}
+
+// watcherSetByKey gets the set of watchers that receive events on the given key.
+func (wg *watcherGroup) watcherSetByKey(key string) watcherSet {
+ wkeys := wg.keyWatchers[key]
+ wranges := wg.ranges.Stab(adt.NewStringAffinePoint(key))
+
+ // zero-copy cases
+ switch {
+ case len(wranges) == 0:
+ // no need to merge ranges or copy; reuse single-key set
+ return wkeys
+ case len(wranges) == 0 && len(wkeys) == 0:
+ return nil
+ case len(wranges) == 1 && len(wkeys) == 0:
+ return wranges[0].Val.(watcherSet)
+ }
+
+ // copy case
+ ret := make(watcherSet)
+ ret.union(wg.keyWatchers[key])
+ for _, item := range wranges {
+ ret.union(item.Val.(watcherSet))
+ }
+ return ret
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/adt/doc.go b/vendor/github.com/coreos/etcd/pkg/adt/doc.go
new file mode 100644
index 00000000..1a955914
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/adt/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package adt implements useful abstract data types.
+package adt
diff --git a/vendor/github.com/coreos/etcd/pkg/adt/interval_tree.go b/vendor/github.com/coreos/etcd/pkg/adt/interval_tree.go
new file mode 100644
index 00000000..ec302e4a
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/adt/interval_tree.go
@@ -0,0 +1,599 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package adt
+
+import (
+ "bytes"
+ "math"
+)
+
+// Comparable is an interface for trichotomic comparisons.
+type Comparable interface {
+ // Compare gives the result of a 3-way comparison
+ // a.Compare(b) = 1 => a > b
+ // a.Compare(b) = 0 => a == b
+ // a.Compare(b) = -1 => a < b
+ Compare(c Comparable) int
+}
+
+type rbcolor int
+
+const (
+ black rbcolor = iota
+ red
+)
+
+// Interval implements a Comparable interval [begin, end)
+// TODO: support different sorts of intervals: (a,b), [a,b], (a, b]
+type Interval struct {
+ Begin Comparable
+ End Comparable
+}
+
+// Compare on an interval gives == if the interval overlaps.
+func (ivl *Interval) Compare(c Comparable) int {
+ ivl2 := c.(*Interval)
+ ivbCmpBegin := ivl.Begin.Compare(ivl2.Begin)
+ ivbCmpEnd := ivl.Begin.Compare(ivl2.End)
+ iveCmpBegin := ivl.End.Compare(ivl2.Begin)
+
+ // ivl is left of ivl2
+ if ivbCmpBegin < 0 && iveCmpBegin <= 0 {
+ return -1
+ }
+
+ // iv is right of iv2
+ if ivbCmpEnd >= 0 {
+ return 1
+ }
+
+ return 0
+}
+
+type intervalNode struct {
+ // iv is the interval-value pair entry.
+ iv IntervalValue
+ // max endpoint of all descendent nodes.
+ max Comparable
+ // left and right are sorted by low endpoint of key interval
+ left, right *intervalNode
+ // parent is the direct ancestor of the node
+ parent *intervalNode
+ c rbcolor
+}
+
+func (x *intervalNode) color() rbcolor {
+ if x == nil {
+ return black
+ }
+ return x.c
+}
+
+func (n *intervalNode) height() int {
+ if n == nil {
+ return 0
+ }
+ ld := n.left.height()
+ rd := n.right.height()
+ if ld < rd {
+ return rd + 1
+ }
+ return ld + 1
+}
+
+func (x *intervalNode) min() *intervalNode {
+ for x.left != nil {
+ x = x.left
+ }
+ return x
+}
+
+// successor is the next in-order node in the tree
+func (x *intervalNode) successor() *intervalNode {
+ if x.right != nil {
+ return x.right.min()
+ }
+ y := x.parent
+ for y != nil && x == y.right {
+ x = y
+ y = y.parent
+ }
+ return y
+}
+
+// updateMax updates the maximum values for a node and its ancestors
+func (x *intervalNode) updateMax() {
+ for x != nil {
+ oldmax := x.max
+ max := x.iv.Ivl.End
+ if x.left != nil && x.left.max.Compare(max) > 0 {
+ max = x.left.max
+ }
+ if x.right != nil && x.right.max.Compare(max) > 0 {
+ max = x.right.max
+ }
+ if oldmax.Compare(max) == 0 {
+ break
+ }
+ x.max = max
+ x = x.parent
+ }
+}
+
+type nodeVisitor func(n *intervalNode) bool
+
+// visit will call a node visitor on each node that overlaps the given interval
+func (x *intervalNode) visit(iv *Interval, nv nodeVisitor) bool {
+ if x == nil {
+ return true
+ }
+ v := iv.Compare(&x.iv.Ivl)
+ switch {
+ case v < 0:
+ if !x.left.visit(iv, nv) {
+ return false
+ }
+ case v > 0:
+ maxiv := Interval{x.iv.Ivl.Begin, x.max}
+ if maxiv.Compare(iv) == 0 {
+ if !x.left.visit(iv, nv) || !x.right.visit(iv, nv) {
+ return false
+ }
+ }
+ default:
+ if !x.left.visit(iv, nv) || !nv(x) || !x.right.visit(iv, nv) {
+ return false
+ }
+ }
+ return true
+}
+
+type IntervalValue struct {
+ Ivl Interval
+ Val interface{}
+}
+
+// IntervalTree represents a (mostly) textbook implementation of the
+// "Introduction to Algorithms" (Cormen et al, 2nd ed.) chapter 13 red-black tree
+// and chapter 14.3 interval tree with search supporting "stabbing queries".
+type IntervalTree struct {
+ root *intervalNode
+ count int
+}
+
+// Delete removes the node with the given interval from the tree, returning
+// true if a node is in fact removed.
+func (ivt *IntervalTree) Delete(ivl Interval) bool {
+ z := ivt.find(ivl)
+ if z == nil {
+ return false
+ }
+
+ y := z
+ if z.left != nil && z.right != nil {
+ y = z.successor()
+ }
+
+ x := y.left
+ if x == nil {
+ x = y.right
+ }
+ if x != nil {
+ x.parent = y.parent
+ }
+
+ if y.parent == nil {
+ ivt.root = x
+ } else {
+ if y == y.parent.left {
+ y.parent.left = x
+ } else {
+ y.parent.right = x
+ }
+ y.parent.updateMax()
+ }
+ if y != z {
+ z.iv = y.iv
+ z.updateMax()
+ }
+
+ if y.color() == black && x != nil {
+ ivt.deleteFixup(x)
+ }
+
+ ivt.count--
+ return true
+}
+
+func (ivt *IntervalTree) deleteFixup(x *intervalNode) {
+ for x != ivt.root && x.color() == black && x.parent != nil {
+ if x == x.parent.left {
+ w := x.parent.right
+ if w.color() == red {
+ w.c = black
+ x.parent.c = red
+ ivt.rotateLeft(x.parent)
+ w = x.parent.right
+ }
+ if w == nil {
+ break
+ }
+ if w.left.color() == black && w.right.color() == black {
+ w.c = red
+ x = x.parent
+ } else {
+ if w.right.color() == black {
+ w.left.c = black
+ w.c = red
+ ivt.rotateRight(w)
+ w = x.parent.right
+ }
+ w.c = x.parent.color()
+ x.parent.c = black
+ w.right.c = black
+ ivt.rotateLeft(x.parent)
+ x = ivt.root
+ }
+ } else {
+ // same as above but with left and right exchanged
+ w := x.parent.left
+ if w.color() == red {
+ w.c = black
+ x.parent.c = red
+ ivt.rotateRight(x.parent)
+ w = x.parent.left
+ }
+ if w == nil {
+ break
+ }
+ if w.left.color() == black && w.right.color() == black {
+ w.c = red
+ x = x.parent
+ } else {
+ if w.left.color() == black {
+ w.right.c = black
+ w.c = red
+ ivt.rotateLeft(w)
+ w = x.parent.left
+ }
+ w.c = x.parent.color()
+ x.parent.c = black
+ w.left.c = black
+ ivt.rotateRight(x.parent)
+ x = ivt.root
+ }
+ }
+ }
+ if x != nil {
+ x.c = black
+ }
+}
+
+// Insert adds a node with the given interval into the tree.
+func (ivt *IntervalTree) Insert(ivl Interval, val interface{}) {
+ var y *intervalNode
+ z := &intervalNode{iv: IntervalValue{ivl, val}, max: ivl.End, c: red}
+ x := ivt.root
+ for x != nil {
+ y = x
+ if z.iv.Ivl.Begin.Compare(x.iv.Ivl.Begin) < 0 {
+ x = x.left
+ } else {
+ x = x.right
+ }
+ }
+
+ z.parent = y
+ if y == nil {
+ ivt.root = z
+ } else {
+ if z.iv.Ivl.Begin.Compare(y.iv.Ivl.Begin) < 0 {
+ y.left = z
+ } else {
+ y.right = z
+ }
+ y.updateMax()
+ }
+ z.c = red
+ ivt.insertFixup(z)
+ ivt.count++
+}
+
+func (ivt *IntervalTree) insertFixup(z *intervalNode) {
+ for z.parent != nil && z.parent.parent != nil && z.parent.color() == red {
+ if z.parent == z.parent.parent.left {
+ y := z.parent.parent.right
+ if y.color() == red {
+ y.c = black
+ z.parent.c = black
+ z.parent.parent.c = red
+ z = z.parent.parent
+ } else {
+ if z == z.parent.right {
+ z = z.parent
+ ivt.rotateLeft(z)
+ }
+ z.parent.c = black
+ z.parent.parent.c = red
+ ivt.rotateRight(z.parent.parent)
+ }
+ } else {
+ // same as then with left/right exchanged
+ y := z.parent.parent.left
+ if y.color() == red {
+ y.c = black
+ z.parent.c = black
+ z.parent.parent.c = red
+ z = z.parent.parent
+ } else {
+ if z == z.parent.left {
+ z = z.parent
+ ivt.rotateRight(z)
+ }
+ z.parent.c = black
+ z.parent.parent.c = red
+ ivt.rotateLeft(z.parent.parent)
+ }
+ }
+ }
+ ivt.root.c = black
+}
+
+// rotateLeft moves x so it is left of its right child
+func (ivt *IntervalTree) rotateLeft(x *intervalNode) {
+ y := x.right
+ x.right = y.left
+ if y.left != nil {
+ y.left.parent = x
+ }
+ x.updateMax()
+ ivt.replaceParent(x, y)
+ y.left = x
+ y.updateMax()
+}
+
+// rotateLeft moves x so it is right of its left child
+func (ivt *IntervalTree) rotateRight(x *intervalNode) {
+ if x == nil {
+ return
+ }
+ y := x.left
+ x.left = y.right
+ if y.right != nil {
+ y.right.parent = x
+ }
+ x.updateMax()
+ ivt.replaceParent(x, y)
+ y.right = x
+ y.updateMax()
+}
+
+// replaceParent replaces x's parent with y
+func (ivt *IntervalTree) replaceParent(x *intervalNode, y *intervalNode) {
+ y.parent = x.parent
+ if x.parent == nil {
+ ivt.root = y
+ } else {
+ if x == x.parent.left {
+ x.parent.left = y
+ } else {
+ x.parent.right = y
+ }
+ x.parent.updateMax()
+ }
+ x.parent = y
+}
+
+// Len gives the number of elements in the tree
+func (ivt *IntervalTree) Len() int { return ivt.count }
+
+// Height is the number of levels in the tree; one node has height 1.
+func (ivt *IntervalTree) Height() int { return ivt.root.height() }
+
+// MaxHeight is the expected maximum tree height given the number of nodes
+func (ivt *IntervalTree) MaxHeight() int {
+ return int((2 * math.Log2(float64(ivt.Len()+1))) + 0.5)
+}
+
+// IntervalVisitor is used on tree searches; return false to stop searching.
+type IntervalVisitor func(n *IntervalValue) bool
+
+// Visit calls a visitor function on every tree node intersecting the given interval.
+// It will visit each interval [x, y) in ascending order sorted on x.
+func (ivt *IntervalTree) Visit(ivl Interval, ivv IntervalVisitor) {
+ ivt.root.visit(&ivl, func(n *intervalNode) bool { return ivv(&n.iv) })
+}
+
+// find the exact node for a given interval
+func (ivt *IntervalTree) find(ivl Interval) (ret *intervalNode) {
+ f := func(n *intervalNode) bool {
+ if n.iv.Ivl != ivl {
+ return true
+ }
+ ret = n
+ return false
+ }
+ ivt.root.visit(&ivl, f)
+ return ret
+}
+
+// Find gets the IntervalValue for the node matching the given interval
+func (ivt *IntervalTree) Find(ivl Interval) (ret *IntervalValue) {
+ n := ivt.find(ivl)
+ if n == nil {
+ return nil
+ }
+ return &n.iv
+}
+
+// Intersects returns true if there is some tree node intersecting the given interval.
+func (ivt *IntervalTree) Intersects(iv Interval) bool {
+ x := ivt.root
+ for x != nil && iv.Compare(&x.iv.Ivl) != 0 {
+ if x.left != nil && x.left.max.Compare(iv.Begin) > 0 {
+ x = x.left
+ } else {
+ x = x.right
+ }
+ }
+ return x != nil
+}
+
+// Contains returns true if the interval tree's keys cover the entire given interval.
+func (ivt *IntervalTree) Contains(ivl Interval) bool {
+ var maxEnd, minBegin Comparable
+
+ isContiguous := true
+ ivt.Visit(ivl, func(n *IntervalValue) bool {
+ if minBegin == nil {
+ minBegin = n.Ivl.Begin
+ maxEnd = n.Ivl.End
+ return true
+ }
+ if maxEnd.Compare(n.Ivl.Begin) < 0 {
+ isContiguous = false
+ return false
+ }
+ if n.Ivl.End.Compare(maxEnd) > 0 {
+ maxEnd = n.Ivl.End
+ }
+ return true
+ })
+
+ return isContiguous && minBegin != nil && maxEnd.Compare(ivl.End) >= 0 && minBegin.Compare(ivl.Begin) <= 0
+}
+
+// Stab returns a slice with all elements in the tree intersecting the interval.
+func (ivt *IntervalTree) Stab(iv Interval) (ivs []*IntervalValue) {
+ if ivt.count == 0 {
+ return nil
+ }
+ f := func(n *IntervalValue) bool { ivs = append(ivs, n); return true }
+ ivt.Visit(iv, f)
+ return ivs
+}
+
+// Union merges a given interval tree into the receiver.
+func (ivt *IntervalTree) Union(inIvt IntervalTree, ivl Interval) {
+ f := func(n *IntervalValue) bool {
+ ivt.Insert(n.Ivl, n.Val)
+ return true
+ }
+ inIvt.Visit(ivl, f)
+}
+
+type StringComparable string
+
+func (s StringComparable) Compare(c Comparable) int {
+ sc := c.(StringComparable)
+ if s < sc {
+ return -1
+ }
+ if s > sc {
+ return 1
+ }
+ return 0
+}
+
+func NewStringInterval(begin, end string) Interval {
+ return Interval{StringComparable(begin), StringComparable(end)}
+}
+
+func NewStringPoint(s string) Interval {
+ return Interval{StringComparable(s), StringComparable(s + "\x00")}
+}
+
+// StringAffineComparable treats "" as > all other strings
+type StringAffineComparable string
+
+func (s StringAffineComparable) Compare(c Comparable) int {
+ sc := c.(StringAffineComparable)
+
+ if len(s) == 0 {
+ if len(sc) == 0 {
+ return 0
+ }
+ return 1
+ }
+ if len(sc) == 0 {
+ return -1
+ }
+
+ if s < sc {
+ return -1
+ }
+ if s > sc {
+ return 1
+ }
+ return 0
+}
+
+func NewStringAffineInterval(begin, end string) Interval {
+ return Interval{StringAffineComparable(begin), StringAffineComparable(end)}
+}
+func NewStringAffinePoint(s string) Interval {
+ return NewStringAffineInterval(s, s+"\x00")
+}
+
+func NewInt64Interval(a int64, b int64) Interval {
+ return Interval{Int64Comparable(a), Int64Comparable(b)}
+}
+
+func NewInt64Point(a int64) Interval {
+ return Interval{Int64Comparable(a), Int64Comparable(a + 1)}
+}
+
+type Int64Comparable int64
+
+func (v Int64Comparable) Compare(c Comparable) int {
+ vc := c.(Int64Comparable)
+ cmp := v - vc
+ if cmp < 0 {
+ return -1
+ }
+ if cmp > 0 {
+ return 1
+ }
+ return 0
+}
+
+// BytesAffineComparable treats empty byte arrays as > all other byte arrays
+type BytesAffineComparable []byte
+
+func (b BytesAffineComparable) Compare(c Comparable) int {
+ bc := c.(BytesAffineComparable)
+
+ if len(b) == 0 {
+ if len(bc) == 0 {
+ return 0
+ }
+ return 1
+ }
+ if len(bc) == 0 {
+ return -1
+ }
+
+ return bytes.Compare(b, bc)
+}
+
+func NewBytesAffineInterval(begin, end []byte) Interval {
+ return Interval{BytesAffineComparable(begin), BytesAffineComparable(end)}
+}
+func NewBytesAffinePoint(b []byte) Interval {
+ be := make([]byte, len(b)+1)
+ copy(be, b)
+ be[len(b)] = 0
+ return NewBytesAffineInterval(b, be)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/contention/contention.go b/vendor/github.com/coreos/etcd/pkg/contention/contention.go
new file mode 100644
index 00000000..26ce9a2f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/contention/contention.go
@@ -0,0 +1,69 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package contention
+
+import (
+ "sync"
+ "time"
+)
+
+// TimeoutDetector detects routine starvations by
+// observing the actual time duration to finish an action
+// or between two events that should happen in a fixed
+// interval. If the observed duration is longer than
+// the expectation, the detector will report the result.
+type TimeoutDetector struct {
+ mu sync.Mutex // protects all
+ maxDuration time.Duration
+ // map from event to time
+ // time is the last seen time of the event.
+ records map[uint64]time.Time
+}
+
+// NewTimeoutDetector creates the TimeoutDetector.
+func NewTimeoutDetector(maxDuration time.Duration) *TimeoutDetector {
+ return &TimeoutDetector{
+ maxDuration: maxDuration,
+ records: make(map[uint64]time.Time),
+ }
+}
+
+// Reset resets the NewTimeoutDetector.
+func (td *TimeoutDetector) Reset() {
+ td.mu.Lock()
+ defer td.mu.Unlock()
+
+ td.records = make(map[uint64]time.Time)
+}
+
+// Observe observes an event for given id. It returns false and exceeded duration
+// if the interval is longer than the expectation.
+func (td *TimeoutDetector) Observe(which uint64) (bool, time.Duration) {
+ td.mu.Lock()
+ defer td.mu.Unlock()
+
+ ok := true
+ now := time.Now()
+ exceed := time.Duration(0)
+
+ if pt, found := td.records[which]; found {
+ exceed = now.Sub(pt) - td.maxDuration
+ if exceed > 0 {
+ ok = false
+ }
+ }
+ td.records[which] = now
+ return ok, exceed
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/contention/doc.go b/vendor/github.com/coreos/etcd/pkg/contention/doc.go
new file mode 100644
index 00000000..daf45221
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/contention/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package contention provides facilities for detecting system contention.
+package contention
diff --git a/vendor/github.com/coreos/etcd/pkg/cpuutil/doc.go b/vendor/github.com/coreos/etcd/pkg/cpuutil/doc.go
new file mode 100644
index 00000000..0323b2d3
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/cpuutil/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package cpuutil provides facilities for detecting cpu-specific features.
+package cpuutil
diff --git a/vendor/github.com/coreos/etcd/pkg/cpuutil/endian.go b/vendor/github.com/coreos/etcd/pkg/cpuutil/endian.go
new file mode 100644
index 00000000..6ab898d4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/cpuutil/endian.go
@@ -0,0 +1,36 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cpuutil
+
+import (
+ "encoding/binary"
+ "unsafe"
+)
+
+const intWidth int = int(unsafe.Sizeof(0))
+
+var byteOrder binary.ByteOrder
+
+// ByteOrder returns the byte order for the CPU's native endianness.
+func ByteOrder() binary.ByteOrder { return byteOrder }
+
+func init() {
+ var i int = 0x1
+ if v := (*[intWidth]byte)(unsafe.Pointer(&i)); v[0] == 0 {
+ byteOrder = binary.BigEndian
+ } else {
+ byteOrder = binary.LittleEndian
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/crc/crc.go b/vendor/github.com/coreos/etcd/pkg/crc/crc.go
new file mode 100644
index 00000000..4b998a48
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/crc/crc.go
@@ -0,0 +1,43 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package crc provides utility function for cyclic redundancy check
+// algorithms.
+package crc
+
+import (
+ "hash"
+ "hash/crc32"
+)
+
+// The size of a CRC-32 checksum in bytes.
+const Size = 4
+
+type digest struct {
+ crc uint32
+ tab *crc32.Table
+}
+
+// New creates a new hash.Hash32 computing the CRC-32 checksum
+// using the polynomial represented by the Table.
+// Modified by xiangli to take a prevcrc.
+func New(prev uint32, tab *crc32.Table) hash.Hash32 { return &digest{prev, tab} }
+
+func (d *digest) Size() int { return Size }
+
+func (d *digest) BlockSize() int { return 1 }
+
+func (d *digest) Reset() { d.crc = 0 }
+
+func (d *digest) Write(p []byte) (n int, err error) {
+ d.crc = crc32.Update(d.crc, d.tab, p)
+ return len(p), nil
+}
+
+func (d *digest) Sum32() uint32 { return d.crc }
+
+func (d *digest) Sum(in []byte) []byte {
+ s := d.Sum32()
+ return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/dir_unix.go b/vendor/github.com/coreos/etcd/pkg/fileutil/dir_unix.go
new file mode 100644
index 00000000..58a77dfc
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/dir_unix.go
@@ -0,0 +1,22 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !windows
+
+package fileutil
+
+import "os"
+
+// OpenDir opens a directory for syncing.
+func OpenDir(path string) (*os.File, error) { return os.Open(path) }
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/dir_windows.go b/vendor/github.com/coreos/etcd/pkg/fileutil/dir_windows.go
new file mode 100644
index 00000000..c123395c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/dir_windows.go
@@ -0,0 +1,46 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build windows
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+)
+
+// OpenDir opens a directory in windows with write access for syncing.
+func OpenDir(path string) (*os.File, error) {
+ fd, err := openDir(path)
+ if err != nil {
+ return nil, err
+ }
+ return os.NewFile(uintptr(fd), path), nil
+}
+
+func openDir(path string) (fd syscall.Handle, err error) {
+ if len(path) == 0 {
+ return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND
+ }
+ pathp, err := syscall.UTF16PtrFromString(path)
+ if err != nil {
+ return syscall.InvalidHandle, err
+ }
+ access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE)
+ sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE)
+ createmode := uint32(syscall.OPEN_EXISTING)
+ fl := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)
+ return syscall.CreateFile(pathp, access, sharemode, nil, createmode, fl, 0)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/fileutil.go b/vendor/github.com/coreos/etcd/pkg/fileutil/fileutil.go
new file mode 100644
index 00000000..fce5126c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/fileutil.go
@@ -0,0 +1,122 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package fileutil implements utility functions related to files and paths.
+package fileutil
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+
+ "github.com/coreos/pkg/capnslog"
+)
+
+const (
+ // PrivateFileMode grants owner to read/write a file.
+ PrivateFileMode = 0600
+ // PrivateDirMode grants owner to make/remove files inside the directory.
+ PrivateDirMode = 0700
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "pkg/fileutil")
+)
+
+// IsDirWriteable checks if dir is writable by writing and removing a file
+// to dir. It returns nil if dir is writable.
+func IsDirWriteable(dir string) error {
+ f := filepath.Join(dir, ".touch")
+ if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil {
+ return err
+ }
+ return os.Remove(f)
+}
+
+// ReadDir returns the filenames in the given directory in sorted order.
+func ReadDir(dirpath string) ([]string, error) {
+ dir, err := os.Open(dirpath)
+ if err != nil {
+ return nil, err
+ }
+ defer dir.Close()
+ names, err := dir.Readdirnames(-1)
+ if err != nil {
+ return nil, err
+ }
+ sort.Strings(names)
+ return names, nil
+}
+
+// TouchDirAll is similar to os.MkdirAll. It creates directories with 0700 permission if any directory
+// does not exists. TouchDirAll also ensures the given directory is writable.
+func TouchDirAll(dir string) error {
+ // If path is already a directory, MkdirAll does nothing
+ // and returns nil.
+ err := os.MkdirAll(dir, PrivateDirMode)
+ if err != nil {
+ // if mkdirAll("a/text") and "text" is not
+ // a directory, this will return syscall.ENOTDIR
+ return err
+ }
+ return IsDirWriteable(dir)
+}
+
+// CreateDirAll is similar to TouchDirAll but returns error
+// if the deepest directory was not empty.
+func CreateDirAll(dir string) error {
+ err := TouchDirAll(dir)
+ if err == nil {
+ var ns []string
+ ns, err = ReadDir(dir)
+ if err != nil {
+ return err
+ }
+ if len(ns) != 0 {
+ err = fmt.Errorf("expected %q to be empty, got %q", dir, ns)
+ }
+ }
+ return err
+}
+
+func Exist(name string) bool {
+ _, err := os.Stat(name)
+ return err == nil
+}
+
+// ZeroToEnd zeros a file starting from SEEK_CUR to its SEEK_END. May temporarily
+// shorten the length of the file.
+func ZeroToEnd(f *os.File) error {
+ // TODO: support FALLOC_FL_ZERO_RANGE
+ off, err := f.Seek(0, io.SeekCurrent)
+ if err != nil {
+ return err
+ }
+ lenf, lerr := f.Seek(0, io.SeekEnd)
+ if lerr != nil {
+ return lerr
+ }
+ if err = f.Truncate(off); err != nil {
+ return err
+ }
+ // make sure blocks remain allocated
+ if err = Preallocate(f, lenf, true); err != nil {
+ return err
+ }
+ _, err = f.Seek(off, io.SeekStart)
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/lock.go b/vendor/github.com/coreos/etcd/pkg/fileutil/lock.go
new file mode 100644
index 00000000..338627f4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/lock.go
@@ -0,0 +1,26 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package fileutil
+
+import (
+ "errors"
+ "os"
+)
+
+var (
+ ErrLocked = errors.New("fileutil: file already locked")
+)
+
+type LockedFile struct{ *os.File }
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/lock_flock.go b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_flock.go
new file mode 100644
index 00000000..542550bc
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_flock.go
@@ -0,0 +1,49 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !windows,!plan9,!solaris
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+)
+
+func flockTryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ f, err := os.OpenFile(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ if err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
+ f.Close()
+ if err == syscall.EWOULDBLOCK {
+ err = ErrLocked
+ }
+ return nil, err
+ }
+ return &LockedFile{f}, nil
+}
+
+func flockLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ f, err := os.OpenFile(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ if err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX); err != nil {
+ f.Close()
+ return nil, err
+ }
+ return &LockedFile{f}, err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/lock_linux.go b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_linux.go
new file mode 100644
index 00000000..939fea62
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_linux.go
@@ -0,0 +1,97 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build linux
+
+package fileutil
+
+import (
+ "io"
+ "os"
+ "syscall"
+)
+
+// This used to call syscall.Flock() but that call fails with EBADF on NFS.
+// An alternative is lockf() which works on NFS but that call lets a process lock
+// the same file twice. Instead, use Linux's non-standard open file descriptor
+// locks which will block if the process already holds the file lock.
+//
+// constants from /usr/include/bits/fcntl-linux.h
+const (
+ F_OFD_GETLK = 37
+ F_OFD_SETLK = 37
+ F_OFD_SETLKW = 38
+)
+
+var (
+ wrlck = syscall.Flock_t{
+ Type: syscall.F_WRLCK,
+ Whence: int16(io.SeekStart),
+ Start: 0,
+ Len: 0,
+ }
+
+ linuxTryLockFile = flockTryLockFile
+ linuxLockFile = flockLockFile
+)
+
+func init() {
+ // use open file descriptor locks if the system supports it
+ getlk := syscall.Flock_t{Type: syscall.F_RDLCK}
+ if err := syscall.FcntlFlock(0, F_OFD_GETLK, &getlk); err == nil {
+ linuxTryLockFile = ofdTryLockFile
+ linuxLockFile = ofdLockFile
+ }
+}
+
+func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ return linuxTryLockFile(path, flag, perm)
+}
+
+func ofdTryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ f, err := os.OpenFile(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+
+ flock := wrlck
+ if err = syscall.FcntlFlock(f.Fd(), F_OFD_SETLK, &flock); err != nil {
+ f.Close()
+ if err == syscall.EWOULDBLOCK {
+ err = ErrLocked
+ }
+ return nil, err
+ }
+ return &LockedFile{f}, nil
+}
+
+func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ return linuxLockFile(path, flag, perm)
+}
+
+func ofdLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ f, err := os.OpenFile(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+
+ flock := wrlck
+ err = syscall.FcntlFlock(f.Fd(), F_OFD_SETLKW, &flock)
+
+ if err != nil {
+ f.Close()
+ return nil, err
+ }
+ return &LockedFile{f}, err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/lock_plan9.go b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_plan9.go
new file mode 100644
index 00000000..fee6a7c8
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_plan9.go
@@ -0,0 +1,45 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+ "time"
+)
+
+func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ if err := os.Chmod(path, syscall.DMEXCL|PrivateFileMode); err != nil {
+ return nil, err
+ }
+ f, err := os.Open(path, flag, perm)
+ if err != nil {
+ return nil, ErrLocked
+ }
+ return &LockedFile{f}, nil
+}
+
+func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ if err := os.Chmod(path, syscall.DMEXCL|PrivateFileMode); err != nil {
+ return nil, err
+ }
+ for {
+ f, err := os.OpenFile(path, flag, perm)
+ if err == nil {
+ return &LockedFile{f}, nil
+ }
+ time.Sleep(10 * time.Millisecond)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/lock_solaris.go b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_solaris.go
new file mode 100644
index 00000000..352ca559
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_solaris.go
@@ -0,0 +1,62 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build solaris
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+)
+
+func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ var lock syscall.Flock_t
+ lock.Start = 0
+ lock.Len = 0
+ lock.Pid = 0
+ lock.Type = syscall.F_WRLCK
+ lock.Whence = 0
+ lock.Pid = 0
+ f, err := os.OpenFile(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ if err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &lock); err != nil {
+ f.Close()
+ if err == syscall.EAGAIN {
+ err = ErrLocked
+ }
+ return nil, err
+ }
+ return &LockedFile{f}, nil
+}
+
+func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ var lock syscall.Flock_t
+ lock.Start = 0
+ lock.Len = 0
+ lock.Pid = 0
+ lock.Type = syscall.F_WRLCK
+ lock.Whence = 0
+ f, err := os.OpenFile(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ if err = syscall.FcntlFlock(f.Fd(), syscall.F_SETLKW, &lock); err != nil {
+ f.Close()
+ return nil, err
+ }
+ return &LockedFile{f}, nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/lock_unix.go b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_unix.go
new file mode 100644
index 00000000..ed01164d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_unix.go
@@ -0,0 +1,29 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !windows,!plan9,!solaris,!linux
+
+package fileutil
+
+import (
+ "os"
+)
+
+func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ return flockTryLockFile(path, flag, perm)
+}
+
+func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ return flockLockFile(path, flag, perm)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/lock_windows.go b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_windows.go
new file mode 100644
index 00000000..b1817230
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/lock_windows.go
@@ -0,0 +1,125 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build windows
+
+package fileutil
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+var (
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+ procLockFileEx = modkernel32.NewProc("LockFileEx")
+
+ errLocked = errors.New("The process cannot access the file because another process has locked a portion of the file.")
+)
+
+const (
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
+ LOCKFILE_EXCLUSIVE_LOCK = 2
+ LOCKFILE_FAIL_IMMEDIATELY = 1
+
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
+ errLockViolation syscall.Errno = 0x21
+)
+
+func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ f, err := open(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ if err := lockFile(syscall.Handle(f.Fd()), LOCKFILE_FAIL_IMMEDIATELY); err != nil {
+ f.Close()
+ return nil, err
+ }
+ return &LockedFile{f}, nil
+}
+
+func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
+ f, err := open(path, flag, perm)
+ if err != nil {
+ return nil, err
+ }
+ if err := lockFile(syscall.Handle(f.Fd()), 0); err != nil {
+ f.Close()
+ return nil, err
+ }
+ return &LockedFile{f}, nil
+}
+
+func open(path string, flag int, perm os.FileMode) (*os.File, error) {
+ if path == "" {
+ return nil, fmt.Errorf("cannot open empty filename")
+ }
+ var access uint32
+ switch flag {
+ case syscall.O_RDONLY:
+ access = syscall.GENERIC_READ
+ case syscall.O_WRONLY:
+ access = syscall.GENERIC_WRITE
+ case syscall.O_RDWR:
+ access = syscall.GENERIC_READ | syscall.GENERIC_WRITE
+ case syscall.O_WRONLY | syscall.O_CREAT:
+ access = syscall.GENERIC_ALL
+ default:
+ panic(fmt.Errorf("flag %v is not supported", flag))
+ }
+ fd, err := syscall.CreateFile(&(syscall.StringToUTF16(path)[0]),
+ access,
+ syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
+ nil,
+ syscall.OPEN_ALWAYS,
+ syscall.FILE_ATTRIBUTE_NORMAL,
+ 0)
+ if err != nil {
+ return nil, err
+ }
+ return os.NewFile(uintptr(fd), path), nil
+}
+
+func lockFile(fd syscall.Handle, flags uint32) error {
+ var flag uint32 = LOCKFILE_EXCLUSIVE_LOCK
+ flag |= flags
+ if fd == syscall.InvalidHandle {
+ return nil
+ }
+ err := lockFileEx(fd, flag, 1, 0, &syscall.Overlapped{})
+ if err == nil {
+ return nil
+ } else if err.Error() == errLocked.Error() {
+ return ErrLocked
+ } else if err != errLockViolation {
+ return err
+ }
+ return nil
+}
+
+func lockFileEx(h syscall.Handle, flags, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
+ var reserved uint32 = 0
+ r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate.go b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate.go
new file mode 100644
index 00000000..c747b7cf
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate.go
@@ -0,0 +1,54 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package fileutil
+
+import (
+ "io"
+ "os"
+)
+
+// Preallocate tries to allocate the space for given
+// file. This operation is only supported on linux by a
+// few filesystems (btrfs, ext4, etc.).
+// If the operation is unsupported, no error will be returned.
+// Otherwise, the error encountered will be returned.
+func Preallocate(f *os.File, sizeInBytes int64, extendFile bool) error {
+ if sizeInBytes == 0 {
+ // fallocate will return EINVAL if length is 0; skip
+ return nil
+ }
+ if extendFile {
+ return preallocExtend(f, sizeInBytes)
+ }
+ return preallocFixed(f, sizeInBytes)
+}
+
+func preallocExtendTrunc(f *os.File, sizeInBytes int64) error {
+ curOff, err := f.Seek(0, io.SeekCurrent)
+ if err != nil {
+ return err
+ }
+ size, err := f.Seek(sizeInBytes, io.SeekEnd)
+ if err != nil {
+ return err
+ }
+ if _, err = f.Seek(curOff, io.SeekStart); err != nil {
+ return err
+ }
+ if sizeInBytes > size {
+ return nil
+ }
+ return f.Truncate(sizeInBytes)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_darwin.go b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_darwin.go
new file mode 100644
index 00000000..5a6dccfa
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_darwin.go
@@ -0,0 +1,65 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build darwin
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+func preallocExtend(f *os.File, sizeInBytes int64) error {
+ if err := preallocFixed(f, sizeInBytes); err != nil {
+ return err
+ }
+ return preallocExtendTrunc(f, sizeInBytes)
+}
+
+func preallocFixed(f *os.File, sizeInBytes int64) error {
+ // allocate all requested space or no space at all
+ // TODO: allocate contiguous space on disk with F_ALLOCATECONTIG flag
+ fstore := &syscall.Fstore_t{
+ Flags: syscall.F_ALLOCATEALL,
+ Posmode: syscall.F_PEOFPOSMODE,
+ Length: sizeInBytes}
+ p := unsafe.Pointer(fstore)
+ _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), uintptr(syscall.F_PREALLOCATE), uintptr(p))
+ if errno == 0 || errno == syscall.ENOTSUP {
+ return nil
+ }
+
+ // wrong argument to fallocate syscall
+ if errno == syscall.EINVAL {
+ // filesystem "st_blocks" are allocated in the units of
+ // "Allocation Block Size" (run "diskutil info /" command)
+ var stat syscall.Stat_t
+ syscall.Fstat(int(f.Fd()), &stat)
+
+ // syscall.Statfs_t.Bsize is "optimal transfer block size"
+ // and contains matching 4096 value when latest OS X kernel
+ // supports 4,096 KB filesystem block size
+ var statfs syscall.Statfs_t
+ syscall.Fstatfs(int(f.Fd()), &statfs)
+ blockSize := int64(statfs.Bsize)
+
+ if stat.Blocks*blockSize >= sizeInBytes {
+ // enough blocks are already allocated
+ return nil
+ }
+ }
+ return errno
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_unix.go b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_unix.go
new file mode 100644
index 00000000..50bd84f0
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_unix.go
@@ -0,0 +1,49 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build linux
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+)
+
+func preallocExtend(f *os.File, sizeInBytes int64) error {
+ // use mode = 0 to change size
+ err := syscall.Fallocate(int(f.Fd()), 0, 0, sizeInBytes)
+ if err != nil {
+ errno, ok := err.(syscall.Errno)
+ // not supported; fallback
+ // fallocate EINTRs frequently in some environments; fallback
+ if ok && (errno == syscall.ENOTSUP || errno == syscall.EINTR) {
+ return preallocExtendTrunc(f, sizeInBytes)
+ }
+ }
+ return err
+}
+
+func preallocFixed(f *os.File, sizeInBytes int64) error {
+ // use mode = 1 to keep size; see FALLOC_FL_KEEP_SIZE
+ err := syscall.Fallocate(int(f.Fd()), 1, 0, sizeInBytes)
+ if err != nil {
+ errno, ok := err.(syscall.Errno)
+ // treat not supported as nil error
+ if ok && errno == syscall.ENOTSUP {
+ return nil
+ }
+ }
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_unsupported.go b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_unsupported.go
new file mode 100644
index 00000000..162fbc5f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/preallocate_unsupported.go
@@ -0,0 +1,25 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !linux,!darwin
+
+package fileutil
+
+import "os"
+
+func preallocExtend(f *os.File, sizeInBytes int64) error {
+ return preallocExtendTrunc(f, sizeInBytes)
+}
+
+func preallocFixed(f *os.File, sizeInBytes int64) error { return nil }
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/purge.go b/vendor/github.com/coreos/etcd/pkg/fileutil/purge.go
new file mode 100644
index 00000000..92fceab0
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/purge.go
@@ -0,0 +1,78 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package fileutil
+
+import (
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+)
+
+func PurgeFile(dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}) <-chan error {
+ return purgeFile(dirname, suffix, max, interval, stop, nil)
+}
+
+// purgeFile is the internal implementation for PurgeFile which can post purged files to purgec if non-nil.
+func purgeFile(dirname string, suffix string, max uint, interval time.Duration, stop <-chan struct{}, purgec chan<- string) <-chan error {
+ errC := make(chan error, 1)
+ go func() {
+ for {
+ fnames, err := ReadDir(dirname)
+ if err != nil {
+ errC <- err
+ return
+ }
+ newfnames := make([]string, 0)
+ for _, fname := range fnames {
+ if strings.HasSuffix(fname, suffix) {
+ newfnames = append(newfnames, fname)
+ }
+ }
+ sort.Strings(newfnames)
+ fnames = newfnames
+ for len(newfnames) > int(max) {
+ f := filepath.Join(dirname, newfnames[0])
+ l, err := TryLockFile(f, os.O_WRONLY, PrivateFileMode)
+ if err != nil {
+ break
+ }
+ if err = os.Remove(f); err != nil {
+ errC <- err
+ return
+ }
+ if err = l.Close(); err != nil {
+ plog.Errorf("error unlocking %s when purging file (%v)", l.Name(), err)
+ errC <- err
+ return
+ }
+ plog.Infof("purged file %s successfully", f)
+ newfnames = newfnames[1:]
+ }
+ if purgec != nil {
+ for i := 0; i < len(fnames)-len(newfnames); i++ {
+ purgec <- fnames[i]
+ }
+ }
+ select {
+ case <-time.After(interval):
+ case <-stop:
+ return
+ }
+ }
+ }()
+ return errC
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/sync.go b/vendor/github.com/coreos/etcd/pkg/fileutil/sync.go
new file mode 100644
index 00000000..54dd41f4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/sync.go
@@ -0,0 +1,29 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !linux,!darwin
+
+package fileutil
+
+import "os"
+
+// Fsync is a wrapper around file.Sync(). Special handling is needed on darwin platform.
+func Fsync(f *os.File) error {
+ return f.Sync()
+}
+
+// Fdatasync is a wrapper around file.Sync(). Special handling is needed on linux platform.
+func Fdatasync(f *os.File) error {
+ return f.Sync()
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/sync_darwin.go b/vendor/github.com/coreos/etcd/pkg/fileutil/sync_darwin.go
new file mode 100644
index 00000000..c2f39bf2
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/sync_darwin.go
@@ -0,0 +1,40 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build darwin
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+)
+
+// Fsync on HFS/OSX flushes the data on to the physical drive but the drive
+// may not write it to the persistent media for quite sometime and it may be
+// written in out-of-order sequence. Using F_FULLFSYNC ensures that the
+// physical drive's buffer will also get flushed to the media.
+func Fsync(f *os.File) error {
+ _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.Fd(), uintptr(syscall.F_FULLFSYNC), uintptr(0))
+ if errno == 0 {
+ return nil
+ }
+ return errno
+}
+
+// Fdatasync on darwin platform invokes fcntl(F_FULLFSYNC) for actual persistence
+// on physical drive media.
+func Fdatasync(f *os.File) error {
+ return Fsync(f)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/fileutil/sync_linux.go b/vendor/github.com/coreos/etcd/pkg/fileutil/sync_linux.go
new file mode 100644
index 00000000..1bbced91
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/fileutil/sync_linux.go
@@ -0,0 +1,34 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build linux
+
+package fileutil
+
+import (
+ "os"
+ "syscall"
+)
+
+// Fsync is a wrapper around file.Sync(). Special handling is needed on darwin platform.
+func Fsync(f *os.File) error {
+ return f.Sync()
+}
+
+// Fdatasync is similar to fsync(), but does not flush modified metadata
+// unless that metadata is needed in order to allow a subsequent data retrieval
+// to be correctly handled.
+func Fdatasync(f *os.File) error {
+ return syscall.Fdatasync(int(f.Fd()))
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/httputil/httputil.go b/vendor/github.com/coreos/etcd/pkg/httputil/httputil.go
new file mode 100644
index 00000000..09f44e7c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/httputil/httputil.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// borrowed from golang/net/context/ctxhttp/cancelreq.go
+
+// Package httputil provides HTTP utility functions.
+package httputil
+
+import (
+ "io"
+ "io/ioutil"
+ "net/http"
+)
+
+// GracefulClose drains http.Response.Body until it hits EOF
+// and closes it. This prevents TCP/TLS connections from closing,
+// therefore available for reuse.
+func GracefulClose(resp *http.Response) {
+ io.Copy(ioutil.Discard, resp.Body)
+ resp.Body.Close()
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/idutil/id.go b/vendor/github.com/coreos/etcd/pkg/idutil/id.go
new file mode 100644
index 00000000..2da21062
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/idutil/id.go
@@ -0,0 +1,78 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package idutil implements utility functions for generating unique,
+// randomized ids.
+package idutil
+
+import (
+ "math"
+ "sync"
+ "time"
+)
+
+const (
+ tsLen = 5 * 8
+ cntLen = 8
+ suffixLen = tsLen + cntLen
+)
+
+// Generator generates unique identifiers based on counters, timestamps, and
+// a node member ID.
+//
+// The initial id is in this format:
+// High order 2 bytes are from memberID, next 5 bytes are from timestamp,
+// and low order one byte is a counter.
+// | prefix | suffix |
+// | 2 bytes | 5 bytes | 1 byte |
+// | memberID | timestamp | cnt |
+//
+// The timestamp 5 bytes is different when the machine is restart
+// after 1 ms and before 35 years.
+//
+// It increases suffix to generate the next id.
+// The count field may overflow to timestamp field, which is intentional.
+// It helps to extend the event window to 2^56. This doesn't break that
+// id generated after restart is unique because etcd throughput is <<
+// 256req/ms(250k reqs/second).
+type Generator struct {
+ mu sync.Mutex
+ // high order 2 bytes
+ prefix uint64
+ // low order 6 bytes
+ suffix uint64
+}
+
+func NewGenerator(memberID uint16, now time.Time) *Generator {
+ prefix := uint64(memberID) << suffixLen
+ unixMilli := uint64(now.UnixNano()) / uint64(time.Millisecond/time.Nanosecond)
+ suffix := lowbit(unixMilli, tsLen) << cntLen
+ return &Generator{
+ prefix: prefix,
+ suffix: suffix,
+ }
+}
+
+// Next generates a id that is unique.
+func (g *Generator) Next() uint64 {
+ g.mu.Lock()
+ defer g.mu.Unlock()
+ g.suffix++
+ id := g.prefix | lowbit(g.suffix, suffixLen)
+ return id
+}
+
+func lowbit(x uint64, n uint) uint64 {
+ return x & (math.MaxUint64 >> (64 - n))
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/ioutil/pagewriter.go b/vendor/github.com/coreos/etcd/pkg/ioutil/pagewriter.go
new file mode 100644
index 00000000..72de1593
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/ioutil/pagewriter.go
@@ -0,0 +1,106 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ioutil
+
+import (
+ "io"
+)
+
+var defaultBufferBytes = 128 * 1024
+
+// PageWriter implements the io.Writer interface so that writes will
+// either be in page chunks or from flushing.
+type PageWriter struct {
+ w io.Writer
+ // pageOffset tracks the page offset of the base of the buffer
+ pageOffset int
+ // pageBytes is the number of bytes per page
+ pageBytes int
+ // bufferedBytes counts the number of bytes pending for write in the buffer
+ bufferedBytes int
+ // buf holds the write buffer
+ buf []byte
+ // bufWatermarkBytes is the number of bytes the buffer can hold before it needs
+ // to be flushed. It is less than len(buf) so there is space for slack writes
+ // to bring the writer to page alignment.
+ bufWatermarkBytes int
+}
+
+// NewPageWriter creates a new PageWriter. pageBytes is the number of bytes
+// to write per page. pageOffset is the starting offset of io.Writer.
+func NewPageWriter(w io.Writer, pageBytes, pageOffset int) *PageWriter {
+ return &PageWriter{
+ w: w,
+ pageOffset: pageOffset,
+ pageBytes: pageBytes,
+ buf: make([]byte, defaultBufferBytes+pageBytes),
+ bufWatermarkBytes: defaultBufferBytes,
+ }
+}
+
+func (pw *PageWriter) Write(p []byte) (n int, err error) {
+ if len(p)+pw.bufferedBytes <= pw.bufWatermarkBytes {
+ // no overflow
+ copy(pw.buf[pw.bufferedBytes:], p)
+ pw.bufferedBytes += len(p)
+ return len(p), nil
+ }
+ // complete the slack page in the buffer if unaligned
+ slack := pw.pageBytes - ((pw.pageOffset + pw.bufferedBytes) % pw.pageBytes)
+ if slack != pw.pageBytes {
+ partial := slack > len(p)
+ if partial {
+ // not enough data to complete the slack page
+ slack = len(p)
+ }
+ // special case: writing to slack page in buffer
+ copy(pw.buf[pw.bufferedBytes:], p[:slack])
+ pw.bufferedBytes += slack
+ n = slack
+ p = p[slack:]
+ if partial {
+ // avoid forcing an unaligned flush
+ return n, nil
+ }
+ }
+ // buffer contents are now page-aligned; clear out
+ if err = pw.Flush(); err != nil {
+ return n, err
+ }
+ // directly write all complete pages without copying
+ if len(p) > pw.pageBytes {
+ pages := len(p) / pw.pageBytes
+ c, werr := pw.w.Write(p[:pages*pw.pageBytes])
+ n += c
+ if werr != nil {
+ return n, werr
+ }
+ p = p[pages*pw.pageBytes:]
+ }
+ // write remaining tail to buffer
+ c, werr := pw.Write(p)
+ n += c
+ return n, werr
+}
+
+func (pw *PageWriter) Flush() error {
+ if pw.bufferedBytes == 0 {
+ return nil
+ }
+ _, err := pw.w.Write(pw.buf[:pw.bufferedBytes])
+ pw.pageOffset = (pw.pageOffset + pw.bufferedBytes) % pw.pageBytes
+ pw.bufferedBytes = 0
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/ioutil/readcloser.go b/vendor/github.com/coreos/etcd/pkg/ioutil/readcloser.go
new file mode 100644
index 00000000..d3efcfe3
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/ioutil/readcloser.go
@@ -0,0 +1,66 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ioutil
+
+import (
+ "fmt"
+ "io"
+)
+
+// ReaderAndCloser implements io.ReadCloser interface by combining
+// reader and closer together.
+type ReaderAndCloser struct {
+ io.Reader
+ io.Closer
+}
+
+var (
+ ErrShortRead = fmt.Errorf("ioutil: short read")
+ ErrExpectEOF = fmt.Errorf("ioutil: expect EOF")
+)
+
+// NewExactReadCloser returns a ReadCloser that returns errors if the underlying
+// reader does not read back exactly the requested number of bytes.
+func NewExactReadCloser(rc io.ReadCloser, totalBytes int64) io.ReadCloser {
+ return &exactReadCloser{rc: rc, totalBytes: totalBytes}
+}
+
+type exactReadCloser struct {
+ rc io.ReadCloser
+ br int64
+ totalBytes int64
+}
+
+func (e *exactReadCloser) Read(p []byte) (int, error) {
+ n, err := e.rc.Read(p)
+ e.br += int64(n)
+ if e.br > e.totalBytes {
+ return 0, ErrExpectEOF
+ }
+ if e.br < e.totalBytes && n == 0 {
+ return 0, ErrShortRead
+ }
+ return n, err
+}
+
+func (e *exactReadCloser) Close() error {
+ if err := e.rc.Close(); err != nil {
+ return err
+ }
+ if e.br < e.totalBytes {
+ return ErrShortRead
+ }
+ return nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/ioutil/reader.go b/vendor/github.com/coreos/etcd/pkg/ioutil/reader.go
new file mode 100644
index 00000000..0703ed47
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/ioutil/reader.go
@@ -0,0 +1,40 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package ioutil implements I/O utility functions.
+package ioutil
+
+import "io"
+
+// NewLimitedBufferReader returns a reader that reads from the given reader
+// but limits the amount of data returned to at most n bytes.
+func NewLimitedBufferReader(r io.Reader, n int) io.Reader {
+ return &limitedBufferReader{
+ r: r,
+ n: n,
+ }
+}
+
+type limitedBufferReader struct {
+ r io.Reader
+ n int
+}
+
+func (r *limitedBufferReader) Read(p []byte) (n int, err error) {
+ np := p
+ if len(np) > r.n {
+ np = np[:r.n]
+ }
+ return r.r.Read(np)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/ioutil/util.go b/vendor/github.com/coreos/etcd/pkg/ioutil/util.go
new file mode 100644
index 00000000..192ad888
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/ioutil/util.go
@@ -0,0 +1,43 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ioutil
+
+import (
+ "io"
+ "os"
+
+ "github.com/coreos/etcd/pkg/fileutil"
+)
+
+// WriteAndSyncFile behaves just like ioutil.WriteFile in the standard library,
+// but calls Sync before closing the file. WriteAndSyncFile guarantees the data
+// is synced if there is no error returned.
+func WriteAndSyncFile(filename string, data []byte, perm os.FileMode) error {
+ f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+ if err != nil {
+ return err
+ }
+ n, err := f.Write(data)
+ if err == nil && n < len(data) {
+ err = io.ErrShortWrite
+ }
+ if err == nil {
+ err = fileutil.Fsync(f)
+ }
+ if err1 := f.Close(); err == nil {
+ err = err1
+ }
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/logutil/merge_logger.go b/vendor/github.com/coreos/etcd/pkg/logutil/merge_logger.go
new file mode 100644
index 00000000..cc750f4d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/logutil/merge_logger.go
@@ -0,0 +1,195 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package logutil includes utilities to facilitate logging.
+package logutil
+
+import (
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ defaultMergePeriod = time.Second
+ defaultTimeOutputScale = 10 * time.Millisecond
+
+ outputInterval = time.Second
+)
+
+// line represents a log line that can be printed out
+// through capnslog.PackageLogger.
+type line struct {
+ level capnslog.LogLevel
+ str string
+}
+
+func (l line) append(s string) line {
+ return line{
+ level: l.level,
+ str: l.str + " " + s,
+ }
+}
+
+// status represents the merge status of a line.
+type status struct {
+ period time.Duration
+
+ start time.Time // start time of latest merge period
+ count int // number of merged lines from starting
+}
+
+func (s *status) isInMergePeriod(now time.Time) bool {
+ return s.period == 0 || s.start.Add(s.period).After(now)
+}
+
+func (s *status) isEmpty() bool { return s.count == 0 }
+
+func (s *status) summary(now time.Time) string {
+ ts := s.start.Round(defaultTimeOutputScale)
+ took := now.Round(defaultTimeOutputScale).Sub(ts)
+ return fmt.Sprintf("[merged %d repeated lines in %s]", s.count, took)
+}
+
+func (s *status) reset(now time.Time) {
+ s.start = now
+ s.count = 0
+}
+
+// MergeLogger supports merge logging, which merges repeated log lines
+// and prints summary log lines instead.
+//
+// For merge logging, MergeLogger prints out the line when the line appears
+// at the first time. MergeLogger holds the same log line printed within
+// defaultMergePeriod, and prints out summary log line at the end of defaultMergePeriod.
+// It stops merging when the line doesn't appear within the
+// defaultMergePeriod.
+type MergeLogger struct {
+ *capnslog.PackageLogger
+
+ mu sync.Mutex // protect statusm
+ statusm map[line]*status
+}
+
+func NewMergeLogger(logger *capnslog.PackageLogger) *MergeLogger {
+ l := &MergeLogger{
+ PackageLogger: logger,
+ statusm: make(map[line]*status),
+ }
+ go l.outputLoop()
+ return l
+}
+
+func (l *MergeLogger) MergeInfo(entries ...interface{}) {
+ l.merge(line{
+ level: capnslog.INFO,
+ str: fmt.Sprint(entries...),
+ })
+}
+
+func (l *MergeLogger) MergeInfof(format string, args ...interface{}) {
+ l.merge(line{
+ level: capnslog.INFO,
+ str: fmt.Sprintf(format, args...),
+ })
+}
+
+func (l *MergeLogger) MergeNotice(entries ...interface{}) {
+ l.merge(line{
+ level: capnslog.NOTICE,
+ str: fmt.Sprint(entries...),
+ })
+}
+
+func (l *MergeLogger) MergeNoticef(format string, args ...interface{}) {
+ l.merge(line{
+ level: capnslog.NOTICE,
+ str: fmt.Sprintf(format, args...),
+ })
+}
+
+func (l *MergeLogger) MergeWarning(entries ...interface{}) {
+ l.merge(line{
+ level: capnslog.WARNING,
+ str: fmt.Sprint(entries...),
+ })
+}
+
+func (l *MergeLogger) MergeWarningf(format string, args ...interface{}) {
+ l.merge(line{
+ level: capnslog.WARNING,
+ str: fmt.Sprintf(format, args...),
+ })
+}
+
+func (l *MergeLogger) MergeError(entries ...interface{}) {
+ l.merge(line{
+ level: capnslog.ERROR,
+ str: fmt.Sprint(entries...),
+ })
+}
+
+func (l *MergeLogger) MergeErrorf(format string, args ...interface{}) {
+ l.merge(line{
+ level: capnslog.ERROR,
+ str: fmt.Sprintf(format, args...),
+ })
+}
+
+func (l *MergeLogger) merge(ln line) {
+ l.mu.Lock()
+
+ // increase count if the logger is merging the line
+ if status, ok := l.statusm[ln]; ok {
+ status.count++
+ l.mu.Unlock()
+ return
+ }
+
+ // initialize status of the line
+ l.statusm[ln] = &status{
+ period: defaultMergePeriod,
+ start: time.Now(),
+ }
+ // release the lock before IO operation
+ l.mu.Unlock()
+ // print out the line at its first time
+ l.PackageLogger.Logf(ln.level, ln.str)
+}
+
+func (l *MergeLogger) outputLoop() {
+ for now := range time.Tick(outputInterval) {
+ var outputs []line
+
+ l.mu.Lock()
+ for ln, status := range l.statusm {
+ if status.isInMergePeriod(now) {
+ continue
+ }
+ if status.isEmpty() {
+ delete(l.statusm, ln)
+ continue
+ }
+ outputs = append(outputs, ln.append(status.summary(now)))
+ status.reset(now)
+ }
+ l.mu.Unlock()
+
+ for _, o := range outputs {
+ l.PackageLogger.Logf(o.level, o.str)
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/netutil/isolate_linux.go b/vendor/github.com/coreos/etcd/pkg/netutil/isolate_linux.go
new file mode 100644
index 00000000..418580ac
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/netutil/isolate_linux.go
@@ -0,0 +1,82 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package netutil
+
+import (
+ "fmt"
+ "os/exec"
+)
+
+// DropPort drops all tcp packets that are received from the given port and sent to the given port.
+func DropPort(port int) error {
+ cmdStr := fmt.Sprintf("sudo iptables -A OUTPUT -p tcp --destination-port %d -j DROP", port)
+ if _, err := exec.Command("/bin/sh", "-c", cmdStr).Output(); err != nil {
+ return err
+ }
+ cmdStr = fmt.Sprintf("sudo iptables -A INPUT -p tcp --destination-port %d -j DROP", port)
+ _, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
+ return err
+}
+
+// RecoverPort stops dropping tcp packets at given port.
+func RecoverPort(port int) error {
+ cmdStr := fmt.Sprintf("sudo iptables -D OUTPUT -p tcp --destination-port %d -j DROP", port)
+ if _, err := exec.Command("/bin/sh", "-c", cmdStr).Output(); err != nil {
+ return err
+ }
+ cmdStr = fmt.Sprintf("sudo iptables -D INPUT -p tcp --destination-port %d -j DROP", port)
+ _, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
+ return err
+}
+
+// SetLatency adds latency in millisecond scale with random variations.
+func SetLatency(ms, rv int) error {
+ ifces, err := GetDefaultInterfaces()
+ if err != nil {
+ return err
+ }
+
+ if rv > ms {
+ rv = 1
+ }
+ for ifce := range ifces {
+ cmdStr := fmt.Sprintf("sudo tc qdisc add dev %s root netem delay %dms %dms distribution normal", ifce, ms, rv)
+ _, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
+ if err != nil {
+ // the rule has already been added. Overwrite it.
+ cmdStr = fmt.Sprintf("sudo tc qdisc change dev %s root netem delay %dms %dms distribution normal", ifce, ms, rv)
+ _, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// RemoveLatency resets latency configurations.
+func RemoveLatency() error {
+ ifces, err := GetDefaultInterfaces()
+ if err != nil {
+ return err
+ }
+ for ifce := range ifces {
+ _, err = exec.Command("/bin/sh", "-c", fmt.Sprintf("sudo tc qdisc del dev %s root netem", ifce)).Output()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/netutil/isolate_stub.go b/vendor/github.com/coreos/etcd/pkg/netutil/isolate_stub.go
new file mode 100644
index 00000000..7f4c3e67
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/netutil/isolate_stub.go
@@ -0,0 +1,25 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !linux
+
+package netutil
+
+func DropPort(port int) error { return nil }
+
+func RecoverPort(port int) error { return nil }
+
+func SetLatency(ms, rv int) error { return nil }
+
+func RemoveLatency() error { return nil }
diff --git a/vendor/github.com/coreos/etcd/pkg/netutil/netutil.go b/vendor/github.com/coreos/etcd/pkg/netutil/netutil.go
new file mode 100644
index 00000000..e3db8c50
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/netutil/netutil.go
@@ -0,0 +1,187 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package netutil implements network-related utility functions.
+package netutil
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "net/url"
+ "reflect"
+ "sort"
+ "time"
+
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/pkg/capnslog"
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "pkg/netutil")
+
+ // indirection for testing
+ resolveTCPAddr = resolveTCPAddrDefault
+)
+
+const retryInterval = time.Second
+
+// taken from go's ResolveTCP code but uses configurable ctx
+func resolveTCPAddrDefault(ctx context.Context, addr string) (*net.TCPAddr, error) {
+ host, port, serr := net.SplitHostPort(addr)
+ if serr != nil {
+ return nil, serr
+ }
+ portnum, perr := net.DefaultResolver.LookupPort(ctx, "tcp", port)
+ if perr != nil {
+ return nil, perr
+ }
+
+ var ips []net.IPAddr
+ if ip := net.ParseIP(host); ip != nil {
+ ips = []net.IPAddr{{IP: ip}}
+ } else {
+ // Try as a DNS name.
+ ipss, err := net.DefaultResolver.LookupIPAddr(ctx, host)
+ if err != nil {
+ return nil, err
+ }
+ ips = ipss
+ }
+ // randomize?
+ ip := ips[0]
+ return &net.TCPAddr{IP: ip.IP, Port: portnum, Zone: ip.Zone}, nil
+}
+
+// resolveTCPAddrs is a convenience wrapper for net.ResolveTCPAddr.
+// resolveTCPAddrs return a new set of url.URLs, in which all DNS hostnames
+// are resolved.
+func resolveTCPAddrs(ctx context.Context, urls [][]url.URL) ([][]url.URL, error) {
+ newurls := make([][]url.URL, 0)
+ for _, us := range urls {
+ nus := make([]url.URL, len(us))
+ for i, u := range us {
+ nu, err := url.Parse(u.String())
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse %q (%v)", u.String(), err)
+ }
+ nus[i] = *nu
+ }
+ for i, u := range nus {
+ h, err := resolveURL(ctx, u)
+ if err != nil {
+ return nil, fmt.Errorf("failed to resolve %q (%v)", u.String(), err)
+ }
+ if h != "" {
+ nus[i].Host = h
+ }
+ }
+ newurls = append(newurls, nus)
+ }
+ return newurls, nil
+}
+
+func resolveURL(ctx context.Context, u url.URL) (string, error) {
+ if u.Scheme == "unix" || u.Scheme == "unixs" {
+ // unix sockets don't resolve over TCP
+ return "", nil
+ }
+ host, _, err := net.SplitHostPort(u.Host)
+ if err != nil {
+ plog.Errorf("could not parse url %s during tcp resolving", u.Host)
+ return "", err
+ }
+ if host == "localhost" || net.ParseIP(host) != nil {
+ return "", nil
+ }
+ for ctx.Err() == nil {
+ tcpAddr, err := resolveTCPAddr(ctx, u.Host)
+ if err == nil {
+ plog.Infof("resolving %s to %s", u.Host, tcpAddr.String())
+ return tcpAddr.String(), nil
+ }
+ plog.Warningf("failed resolving host %s (%v); retrying in %v", u.Host, err, retryInterval)
+ select {
+ case <-ctx.Done():
+ plog.Errorf("could not resolve host %s", u.Host)
+ return "", err
+ case <-time.After(retryInterval):
+ }
+ }
+ return "", ctx.Err()
+}
+
+// urlsEqual checks equality of url.URLS between two arrays.
+// This check pass even if an URL is in hostname and opposite is in IP address.
+func urlsEqual(ctx context.Context, a []url.URL, b []url.URL) (bool, error) {
+ if len(a) != len(b) {
+ return false, fmt.Errorf("len(%q) != len(%q)", urlsToStrings(a), urlsToStrings(b))
+ }
+ urls, err := resolveTCPAddrs(ctx, [][]url.URL{a, b})
+ if err != nil {
+ return false, err
+ }
+ preva, prevb := a, b
+ a, b = urls[0], urls[1]
+ sort.Sort(types.URLs(a))
+ sort.Sort(types.URLs(b))
+ for i := range a {
+ if !reflect.DeepEqual(a[i], b[i]) {
+ return false, fmt.Errorf("%q(resolved from %q) != %q(resolved from %q)",
+ a[i].String(), preva[i].String(),
+ b[i].String(), prevb[i].String(),
+ )
+ }
+ }
+ return true, nil
+}
+
+// URLStringsEqual returns "true" if given URLs are valid
+// and resolved to same IP addresses. Otherwise, return "false"
+// and error, if any.
+func URLStringsEqual(ctx context.Context, a []string, b []string) (bool, error) {
+ if len(a) != len(b) {
+ return false, fmt.Errorf("len(%q) != len(%q)", a, b)
+ }
+ urlsA := make([]url.URL, 0)
+ for _, str := range a {
+ u, err := url.Parse(str)
+ if err != nil {
+ return false, fmt.Errorf("failed to parse %q", str)
+ }
+ urlsA = append(urlsA, *u)
+ }
+ urlsB := make([]url.URL, 0)
+ for _, str := range b {
+ u, err := url.Parse(str)
+ if err != nil {
+ return false, fmt.Errorf("failed to parse %q", str)
+ }
+ urlsB = append(urlsB, *u)
+ }
+ return urlsEqual(ctx, urlsA, urlsB)
+}
+
+func urlsToStrings(us []url.URL) []string {
+ rs := make([]string, len(us))
+ for i := range us {
+ rs[i] = us[i].String()
+ }
+ return rs
+}
+
+func IsNetworkTimeoutError(err error) bool {
+ nerr, ok := err.(net.Error)
+ return ok && nerr.Timeout()
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/netutil/routes.go b/vendor/github.com/coreos/etcd/pkg/netutil/routes.go
new file mode 100644
index 00000000..3eb6a19e
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/netutil/routes.go
@@ -0,0 +1,33 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !linux
+
+package netutil
+
+import (
+ "fmt"
+ "runtime"
+)
+
+// GetDefaultHost fetches the a resolvable name that corresponds
+// to the machine's default routable interface
+func GetDefaultHost() (string, error) {
+ return "", fmt.Errorf("default host not supported on %s_%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// GetDefaultInterfaces fetches the device name of default routable interface.
+func GetDefaultInterfaces() (map[string]uint8, error) {
+ return nil, fmt.Errorf("default host not supported on %s_%s", runtime.GOOS, runtime.GOARCH)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/netutil/routes_linux.go b/vendor/github.com/coreos/etcd/pkg/netutil/routes_linux.go
new file mode 100644
index 00000000..797baeb4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/netutil/routes_linux.go
@@ -0,0 +1,250 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build linux
+
+package netutil
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "net"
+ "sort"
+ "syscall"
+
+ "github.com/coreos/etcd/pkg/cpuutil"
+)
+
+var errNoDefaultRoute = fmt.Errorf("could not find default route")
+var errNoDefaultHost = fmt.Errorf("could not find default host")
+var errNoDefaultInterface = fmt.Errorf("could not find default interface")
+
+// GetDefaultHost obtains the first IP address of machine from the routing table and returns the IP address as string.
+// An IPv4 address is preferred to an IPv6 address for backward compatibility.
+func GetDefaultHost() (string, error) {
+ rmsgs, rerr := getDefaultRoutes()
+ if rerr != nil {
+ return "", rerr
+ }
+
+ // prioritize IPv4
+ if rmsg, ok := rmsgs[syscall.AF_INET]; ok {
+ if host, err := chooseHost(syscall.AF_INET, rmsg); host != "" || err != nil {
+ return host, err
+ }
+ delete(rmsgs, syscall.AF_INET)
+ }
+
+ // sort so choice is deterministic
+ var families []int
+ for family := range rmsgs {
+ families = append(families, int(family))
+ }
+ sort.Ints(families)
+
+ for _, f := range families {
+ family := uint8(f)
+ if host, err := chooseHost(family, rmsgs[family]); host != "" || err != nil {
+ return host, err
+ }
+ }
+
+ return "", errNoDefaultHost
+}
+
+func chooseHost(family uint8, rmsg *syscall.NetlinkMessage) (string, error) {
+ host, oif, err := parsePREFSRC(rmsg)
+ if host != "" || err != nil {
+ return host, err
+ }
+
+ // prefsrc not detected, fall back to getting address from iface
+ ifmsg, ierr := getIfaceAddr(oif, family)
+ if ierr != nil {
+ return "", ierr
+ }
+
+ attrs, aerr := syscall.ParseNetlinkRouteAttr(ifmsg)
+ if aerr != nil {
+ return "", aerr
+ }
+
+ for _, attr := range attrs {
+ // search for RTA_DST because ipv6 doesn't have RTA_SRC
+ if attr.Attr.Type == syscall.RTA_DST {
+ return net.IP(attr.Value).String(), nil
+ }
+ }
+
+ return "", nil
+}
+
+func getDefaultRoutes() (map[uint8]*syscall.NetlinkMessage, error) {
+ dat, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_UNSPEC)
+ if err != nil {
+ return nil, err
+ }
+
+ msgs, msgErr := syscall.ParseNetlinkMessage(dat)
+ if msgErr != nil {
+ return nil, msgErr
+ }
+
+ routes := make(map[uint8]*syscall.NetlinkMessage)
+ rtmsg := syscall.RtMsg{}
+ for _, m := range msgs {
+ if m.Header.Type != syscall.RTM_NEWROUTE {
+ continue
+ }
+ buf := bytes.NewBuffer(m.Data[:syscall.SizeofRtMsg])
+ if rerr := binary.Read(buf, cpuutil.ByteOrder(), &rtmsg); rerr != nil {
+ continue
+ }
+ if rtmsg.Dst_len == 0 && rtmsg.Table == syscall.RT_TABLE_MAIN {
+ // zero-length Dst_len implies default route
+ msg := m
+ routes[rtmsg.Family] = &msg
+ }
+ }
+
+ if len(routes) > 0 {
+ return routes, nil
+ }
+
+ return nil, errNoDefaultRoute
+}
+
+// Used to get an address of interface.
+func getIfaceAddr(idx uint32, family uint8) (*syscall.NetlinkMessage, error) {
+ dat, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, int(family))
+ if err != nil {
+ return nil, err
+ }
+
+ msgs, msgErr := syscall.ParseNetlinkMessage(dat)
+ if msgErr != nil {
+ return nil, msgErr
+ }
+
+ ifaddrmsg := syscall.IfAddrmsg{}
+ for _, m := range msgs {
+ if m.Header.Type != syscall.RTM_NEWADDR {
+ continue
+ }
+ buf := bytes.NewBuffer(m.Data[:syscall.SizeofIfAddrmsg])
+ if rerr := binary.Read(buf, cpuutil.ByteOrder(), &ifaddrmsg); rerr != nil {
+ continue
+ }
+ if ifaddrmsg.Index == idx {
+ return &m, nil
+ }
+ }
+
+ return nil, fmt.Errorf("could not find address for interface index %v", idx)
+
+}
+
+// Used to get a name of interface.
+func getIfaceLink(idx uint32) (*syscall.NetlinkMessage, error) {
+ dat, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
+ if err != nil {
+ return nil, err
+ }
+
+ msgs, msgErr := syscall.ParseNetlinkMessage(dat)
+ if msgErr != nil {
+ return nil, msgErr
+ }
+
+ ifinfomsg := syscall.IfInfomsg{}
+ for _, m := range msgs {
+ if m.Header.Type != syscall.RTM_NEWLINK {
+ continue
+ }
+ buf := bytes.NewBuffer(m.Data[:syscall.SizeofIfInfomsg])
+ if rerr := binary.Read(buf, cpuutil.ByteOrder(), &ifinfomsg); rerr != nil {
+ continue
+ }
+ if ifinfomsg.Index == int32(idx) {
+ return &m, nil
+ }
+ }
+
+ return nil, fmt.Errorf("could not find link for interface index %v", idx)
+}
+
+// GetDefaultInterfaces gets names of interfaces and returns a map[interface]families.
+func GetDefaultInterfaces() (map[string]uint8, error) {
+ interfaces := make(map[string]uint8)
+ rmsgs, rerr := getDefaultRoutes()
+ if rerr != nil {
+ return interfaces, rerr
+ }
+
+ for family, rmsg := range rmsgs {
+ _, oif, err := parsePREFSRC(rmsg)
+ if err != nil {
+ return interfaces, err
+ }
+
+ ifmsg, ierr := getIfaceLink(oif)
+ if ierr != nil {
+ return interfaces, ierr
+ }
+
+ attrs, aerr := syscall.ParseNetlinkRouteAttr(ifmsg)
+ if aerr != nil {
+ return interfaces, aerr
+ }
+
+ for _, attr := range attrs {
+ if attr.Attr.Type == syscall.IFLA_IFNAME {
+ // key is an interface name
+ // possible values: 2 - AF_INET, 10 - AF_INET6, 12 - dualstack
+ interfaces[string(attr.Value[:len(attr.Value)-1])] += family
+ }
+ }
+ }
+ if len(interfaces) > 0 {
+ return interfaces, nil
+ }
+ return interfaces, errNoDefaultInterface
+}
+
+// parsePREFSRC returns preferred source address and output interface index (RTA_OIF).
+func parsePREFSRC(m *syscall.NetlinkMessage) (host string, oif uint32, err error) {
+ var attrs []syscall.NetlinkRouteAttr
+ attrs, err = syscall.ParseNetlinkRouteAttr(m)
+ if err != nil {
+ return "", 0, err
+ }
+
+ for _, attr := range attrs {
+ if attr.Attr.Type == syscall.RTA_PREFSRC {
+ host = net.IP(attr.Value).String()
+ }
+ if attr.Attr.Type == syscall.RTA_OIF {
+ oif = cpuutil.ByteOrder().Uint32(attr.Value)
+ }
+ if host != "" && oif != uint32(0) {
+ break
+ }
+ }
+
+ if oif == 0 {
+ err = errNoDefaultRoute
+ }
+ return host, oif, err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/pathutil/path.go b/vendor/github.com/coreos/etcd/pkg/pathutil/path.go
new file mode 100644
index 00000000..f26254ba
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/pathutil/path.go
@@ -0,0 +1,31 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package pathutil implements utility functions for handling slash-separated
+// paths.
+package pathutil
+
+import "path"
+
+// CanonicalURLPath returns the canonical url path for p, which follows the rules:
+// 1. the path always starts with "/"
+// 2. replace multiple slashes with a single slash
+// 3. replace each '.' '..' path name element with equivalent one
+// 4. keep the trailing slash
+// The function is borrowed from stdlib http.cleanPath in server.go.
+func CanonicalURLPath(p string) string {
+ if p == "" {
+ return "/"
+ }
+ if p[0] != '/' {
+ p = "/" + p
+ }
+ np := path.Clean(p)
+ // path.Clean removes trailing slash except for root,
+ // put the trailing slash back if necessary.
+ if p[len(p)-1] == '/' && np != "/" {
+ np += "/"
+ }
+ return np
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/pbutil/pbutil.go b/vendor/github.com/coreos/etcd/pkg/pbutil/pbutil.go
new file mode 100644
index 00000000..d70f98dd
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/pbutil/pbutil.go
@@ -0,0 +1,60 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package pbutil defines interfaces for handling Protocol Buffer objects.
+package pbutil
+
+import "github.com/coreos/pkg/capnslog"
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "pkg/pbutil")
+)
+
+type Marshaler interface {
+ Marshal() (data []byte, err error)
+}
+
+type Unmarshaler interface {
+ Unmarshal(data []byte) error
+}
+
+func MustMarshal(m Marshaler) []byte {
+ d, err := m.Marshal()
+ if err != nil {
+ plog.Panicf("marshal should never fail (%v)", err)
+ }
+ return d
+}
+
+func MustUnmarshal(um Unmarshaler, data []byte) {
+ if err := um.Unmarshal(data); err != nil {
+ plog.Panicf("unmarshal should never fail (%v)", err)
+ }
+}
+
+func MaybeUnmarshal(um Unmarshaler, data []byte) bool {
+ if err := um.Unmarshal(data); err != nil {
+ return false
+ }
+ return true
+}
+
+func GetBool(v *bool) (vv bool, set bool) {
+ if v == nil {
+ return false, false
+ }
+ return *v, true
+}
+
+func Boolp(b bool) *bool { return &b }
diff --git a/vendor/github.com/coreos/etcd/pkg/runtime/fds_linux.go b/vendor/github.com/coreos/etcd/pkg/runtime/fds_linux.go
new file mode 100644
index 00000000..8e9359db
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/runtime/fds_linux.go
@@ -0,0 +1,37 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package runtime implements utility functions for runtime systems.
+package runtime
+
+import (
+ "io/ioutil"
+ "syscall"
+)
+
+func FDLimit() (uint64, error) {
+ var rlimit syscall.Rlimit
+ if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
+ return 0, err
+ }
+ return rlimit.Cur, nil
+}
+
+func FDUsage() (uint64, error) {
+ fds, err := ioutil.ReadDir("/proc/self/fd")
+ if err != nil {
+ return 0, err
+ }
+ return uint64(len(fds)), nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/runtime/fds_other.go b/vendor/github.com/coreos/etcd/pkg/runtime/fds_other.go
new file mode 100644
index 00000000..0cbdb88c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/runtime/fds_other.go
@@ -0,0 +1,30 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !linux
+
+package runtime
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func FDLimit() (uint64, error) {
+ return 0, fmt.Errorf("cannot get FDLimit on %s", runtime.GOOS)
+}
+
+func FDUsage() (uint64, error) {
+ return 0, fmt.Errorf("cannot get FDUsage on %s", runtime.GOOS)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/schedule/doc.go b/vendor/github.com/coreos/etcd/pkg/schedule/doc.go
new file mode 100644
index 00000000..cca2c75f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/schedule/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package schedule provides mechanisms and policies for scheduling units of work.
+package schedule
diff --git a/vendor/github.com/coreos/etcd/pkg/schedule/schedule.go b/vendor/github.com/coreos/etcd/pkg/schedule/schedule.go
new file mode 100644
index 00000000..234d0198
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/schedule/schedule.go
@@ -0,0 +1,165 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package schedule
+
+import (
+ "context"
+ "sync"
+)
+
+type Job func(context.Context)
+
+// Scheduler can schedule jobs.
+type Scheduler interface {
+ // Schedule asks the scheduler to schedule a job defined by the given func.
+ // Schedule to a stopped scheduler might panic.
+ Schedule(j Job)
+
+ // Pending returns number of pending jobs
+ Pending() int
+
+ // Scheduled returns the number of scheduled jobs (excluding pending jobs)
+ Scheduled() int
+
+ // Finished returns the number of finished jobs
+ Finished() int
+
+ // WaitFinish waits until at least n job are finished and all pending jobs are finished.
+ WaitFinish(n int)
+
+ // Stop stops the scheduler.
+ Stop()
+}
+
+type fifo struct {
+ mu sync.Mutex
+
+ resume chan struct{}
+ scheduled int
+ finished int
+ pendings []Job
+
+ ctx context.Context
+ cancel context.CancelFunc
+
+ finishCond *sync.Cond
+ donec chan struct{}
+}
+
+// NewFIFOScheduler returns a Scheduler that schedules jobs in FIFO
+// order sequentially
+func NewFIFOScheduler() Scheduler {
+ f := &fifo{
+ resume: make(chan struct{}, 1),
+ donec: make(chan struct{}, 1),
+ }
+ f.finishCond = sync.NewCond(&f.mu)
+ f.ctx, f.cancel = context.WithCancel(context.Background())
+ go f.run()
+ return f
+}
+
+// Schedule schedules a job that will be ran in FIFO order sequentially.
+func (f *fifo) Schedule(j Job) {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+
+ if f.cancel == nil {
+ panic("schedule: schedule to stopped scheduler")
+ }
+
+ if len(f.pendings) == 0 {
+ select {
+ case f.resume <- struct{}{}:
+ default:
+ }
+ }
+ f.pendings = append(f.pendings, j)
+}
+
+func (f *fifo) Pending() int {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ return len(f.pendings)
+}
+
+func (f *fifo) Scheduled() int {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ return f.scheduled
+}
+
+func (f *fifo) Finished() int {
+ f.finishCond.L.Lock()
+ defer f.finishCond.L.Unlock()
+ return f.finished
+}
+
+func (f *fifo) WaitFinish(n int) {
+ f.finishCond.L.Lock()
+ for f.finished < n || len(f.pendings) != 0 {
+ f.finishCond.Wait()
+ }
+ f.finishCond.L.Unlock()
+}
+
+// Stop stops the scheduler and cancels all pending jobs.
+func (f *fifo) Stop() {
+ f.mu.Lock()
+ f.cancel()
+ f.cancel = nil
+ f.mu.Unlock()
+ <-f.donec
+}
+
+func (f *fifo) run() {
+ // TODO: recover from job panic?
+ defer func() {
+ close(f.donec)
+ close(f.resume)
+ }()
+
+ for {
+ var todo Job
+ f.mu.Lock()
+ if len(f.pendings) != 0 {
+ f.scheduled++
+ todo = f.pendings[0]
+ }
+ f.mu.Unlock()
+ if todo == nil {
+ select {
+ case <-f.resume:
+ case <-f.ctx.Done():
+ f.mu.Lock()
+ pendings := f.pendings
+ f.pendings = nil
+ f.mu.Unlock()
+ // clean up pending jobs
+ for _, todo := range pendings {
+ todo(f.ctx)
+ }
+ return
+ }
+ } else {
+ todo(f.ctx)
+ f.finishCond.L.Lock()
+ f.finished++
+ f.pendings = f.pendings[1:]
+ f.finishCond.Broadcast()
+ f.finishCond.L.Unlock()
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/srv/srv.go b/vendor/github.com/coreos/etcd/pkg/srv/srv.go
new file mode 100644
index 00000000..600061ce
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/srv/srv.go
@@ -0,0 +1,141 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package srv looks up DNS SRV records.
+package srv
+
+import (
+ "fmt"
+ "net"
+ "net/url"
+ "strings"
+
+ "github.com/coreos/etcd/pkg/types"
+)
+
+var (
+ // indirection for testing
+ lookupSRV = net.LookupSRV // net.DefaultResolver.LookupSRV when ctxs don't conflict
+ resolveTCPAddr = net.ResolveTCPAddr
+)
+
+// GetCluster gets the cluster information via DNS discovery.
+// Also sees each entry as a separate instance.
+func GetCluster(service, name, dns string, apurls types.URLs) ([]string, error) {
+ tempName := int(0)
+ tcp2ap := make(map[string]url.URL)
+
+ // First, resolve the apurls
+ for _, url := range apurls {
+ tcpAddr, err := resolveTCPAddr("tcp", url.Host)
+ if err != nil {
+ return nil, err
+ }
+ tcp2ap[tcpAddr.String()] = url
+ }
+
+ stringParts := []string{}
+ updateNodeMap := func(service, scheme string) error {
+ _, addrs, err := lookupSRV(service, "tcp", dns)
+ if err != nil {
+ return err
+ }
+ for _, srv := range addrs {
+ port := fmt.Sprintf("%d", srv.Port)
+ host := net.JoinHostPort(srv.Target, port)
+ tcpAddr, terr := resolveTCPAddr("tcp", host)
+ if terr != nil {
+ err = terr
+ continue
+ }
+ n := ""
+ url, ok := tcp2ap[tcpAddr.String()]
+ if ok {
+ n = name
+ }
+ if n == "" {
+ n = fmt.Sprintf("%d", tempName)
+ tempName++
+ }
+ // SRV records have a trailing dot but URL shouldn't.
+ shortHost := strings.TrimSuffix(srv.Target, ".")
+ urlHost := net.JoinHostPort(shortHost, port)
+ if ok && url.Scheme != scheme {
+ err = fmt.Errorf("bootstrap at %s from DNS for %s has scheme mismatch with expected peer %s", scheme+"://"+urlHost, service, url.String())
+ } else {
+ stringParts = append(stringParts, fmt.Sprintf("%s=%s://%s", n, scheme, urlHost))
+ }
+ }
+ if len(stringParts) == 0 {
+ return err
+ }
+ return nil
+ }
+
+ failCount := 0
+ err := updateNodeMap(service+"-ssl", "https")
+ srvErr := make([]string, 2)
+ if err != nil {
+ srvErr[0] = fmt.Sprintf("error querying DNS SRV records for _%s-ssl %s", service, err)
+ failCount++
+ }
+ err = updateNodeMap(service, "http")
+ if err != nil {
+ srvErr[1] = fmt.Sprintf("error querying DNS SRV records for _%s %s", service, err)
+ failCount++
+ }
+ if failCount == 2 {
+ return nil, fmt.Errorf("srv: too many errors querying DNS SRV records (%q, %q)", srvErr[0], srvErr[1])
+ }
+ return stringParts, nil
+}
+
+type SRVClients struct {
+ Endpoints []string
+ SRVs []*net.SRV
+}
+
+// GetClient looks up the client endpoints for a service and domain.
+func GetClient(service, domain string) (*SRVClients, error) {
+ var urls []*url.URL
+ var srvs []*net.SRV
+
+ updateURLs := func(service, scheme string) error {
+ _, addrs, err := lookupSRV(service, "tcp", domain)
+ if err != nil {
+ return err
+ }
+ for _, srv := range addrs {
+ urls = append(urls, &url.URL{
+ Scheme: scheme,
+ Host: net.JoinHostPort(srv.Target, fmt.Sprintf("%d", srv.Port)),
+ })
+ }
+ srvs = append(srvs, addrs...)
+ return nil
+ }
+
+ errHTTPS := updateURLs(service+"-ssl", "https")
+ errHTTP := updateURLs(service, "http")
+
+ if errHTTPS != nil && errHTTP != nil {
+ return nil, fmt.Errorf("dns lookup errors: %s and %s", errHTTPS, errHTTP)
+ }
+
+ endpoints := make([]string, len(urls))
+ for i := range urls {
+ endpoints[i] = urls[i].String()
+ }
+ return &SRVClients{Endpoints: endpoints, SRVs: srvs}, nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/tlsutil/cipher_suites.go b/vendor/github.com/coreos/etcd/pkg/tlsutil/cipher_suites.go
new file mode 100644
index 00000000..b5916bb5
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/tlsutil/cipher_suites.go
@@ -0,0 +1,51 @@
+// Copyright 2018 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tlsutil
+
+import "crypto/tls"
+
+// cipher suites implemented by Go
+// https://github.com/golang/go/blob/dev.boringcrypto.go1.10/src/crypto/tls/cipher_suites.go
+var cipherSuites = map[string]uint16{
+ "TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA,
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ "TLS_RSA_WITH_AES_128_CBC_SHA": tls.TLS_RSA_WITH_AES_128_CBC_SHA,
+ "TLS_RSA_WITH_AES_256_CBC_SHA": tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+ "TLS_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
+ "TLS_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
+ "TLS_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
+ "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ "TLS_ECDHE_RSA_WITH_RC4_128_SHA": tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+}
+
+// GetCipherSuite returns the corresponding cipher suite,
+// and boolean value if it is supported.
+func GetCipherSuite(s string) (uint16, bool) {
+ v, ok := cipherSuites[s]
+ return v, ok
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/tlsutil/doc.go b/vendor/github.com/coreos/etcd/pkg/tlsutil/doc.go
new file mode 100644
index 00000000..3b6aa670
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/tlsutil/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package tlsutil provides utility functions for handling TLS.
+package tlsutil
diff --git a/vendor/github.com/coreos/etcd/pkg/tlsutil/tlsutil.go b/vendor/github.com/coreos/etcd/pkg/tlsutil/tlsutil.go
new file mode 100644
index 00000000..79b1f632
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/tlsutil/tlsutil.go
@@ -0,0 +1,72 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tlsutil
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/pem"
+ "io/ioutil"
+)
+
+// NewCertPool creates x509 certPool with provided CA files.
+func NewCertPool(CAFiles []string) (*x509.CertPool, error) {
+ certPool := x509.NewCertPool()
+
+ for _, CAFile := range CAFiles {
+ pemByte, err := ioutil.ReadFile(CAFile)
+ if err != nil {
+ return nil, err
+ }
+
+ for {
+ var block *pem.Block
+ block, pemByte = pem.Decode(pemByte)
+ if block == nil {
+ break
+ }
+ cert, err := x509.ParseCertificate(block.Bytes)
+ if err != nil {
+ return nil, err
+ }
+ certPool.AddCert(cert)
+ }
+ }
+
+ return certPool, nil
+}
+
+// NewCert generates TLS cert by using the given cert,key and parse function.
+func NewCert(certfile, keyfile string, parseFunc func([]byte, []byte) (tls.Certificate, error)) (*tls.Certificate, error) {
+ cert, err := ioutil.ReadFile(certfile)
+ if err != nil {
+ return nil, err
+ }
+
+ key, err := ioutil.ReadFile(keyfile)
+ if err != nil {
+ return nil, err
+ }
+
+ if parseFunc == nil {
+ parseFunc = tls.X509KeyPair
+ }
+
+ tlsCert, err := parseFunc(cert, key)
+ if err != nil {
+ return nil, err
+ }
+ return &tlsCert, nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/doc.go b/vendor/github.com/coreos/etcd/pkg/transport/doc.go
new file mode 100644
index 00000000..37658ce5
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/doc.go
@@ -0,0 +1,17 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package transport implements various HTTP transport utilities based on Go
+// net package.
+package transport
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/keepalive_listener.go b/vendor/github.com/coreos/etcd/pkg/transport/keepalive_listener.go
new file mode 100644
index 00000000..4ff8e7f0
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/keepalive_listener.go
@@ -0,0 +1,94 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "crypto/tls"
+ "fmt"
+ "net"
+ "time"
+)
+
+type keepAliveConn interface {
+ SetKeepAlive(bool) error
+ SetKeepAlivePeriod(d time.Duration) error
+}
+
+// NewKeepAliveListener returns a listener that listens on the given address.
+// Be careful when wrap around KeepAliveListener with another Listener if TLSInfo is not nil.
+// Some pkgs (like go/http) might expect Listener to return TLSConn type to start TLS handshake.
+// http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
+func NewKeepAliveListener(l net.Listener, scheme string, tlscfg *tls.Config) (net.Listener, error) {
+ if scheme == "https" {
+ if tlscfg == nil {
+ return nil, fmt.Errorf("cannot listen on TLS for given listener: KeyFile and CertFile are not presented")
+ }
+ return newTLSKeepaliveListener(l, tlscfg), nil
+ }
+
+ return &keepaliveListener{
+ Listener: l,
+ }, nil
+}
+
+type keepaliveListener struct{ net.Listener }
+
+func (kln *keepaliveListener) Accept() (net.Conn, error) {
+ c, err := kln.Listener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ kac := c.(keepAliveConn)
+ // detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl
+ // default on linux: 30 + 8 * 30
+ // default on osx: 30 + 8 * 75
+ kac.SetKeepAlive(true)
+ kac.SetKeepAlivePeriod(30 * time.Second)
+ return c, nil
+}
+
+// A tlsKeepaliveListener implements a network listener (net.Listener) for TLS connections.
+type tlsKeepaliveListener struct {
+ net.Listener
+ config *tls.Config
+}
+
+// Accept waits for and returns the next incoming TLS connection.
+// The returned connection c is a *tls.Conn.
+func (l *tlsKeepaliveListener) Accept() (c net.Conn, err error) {
+ c, err = l.Listener.Accept()
+ if err != nil {
+ return
+ }
+ kac := c.(keepAliveConn)
+ // detection time: tcp_keepalive_time + tcp_keepalive_probes + tcp_keepalive_intvl
+ // default on linux: 30 + 8 * 30
+ // default on osx: 30 + 8 * 75
+ kac.SetKeepAlive(true)
+ kac.SetKeepAlivePeriod(30 * time.Second)
+ c = tls.Server(c, l.config)
+ return c, nil
+}
+
+// NewListener creates a Listener which accepts connections from an inner
+// Listener and wraps each connection with Server.
+// The configuration config must be non-nil and must have
+// at least one certificate.
+func newTLSKeepaliveListener(inner net.Listener, config *tls.Config) net.Listener {
+ l := &tlsKeepaliveListener{}
+ l.Listener = inner
+ l.config = config
+ return l
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/limit_listen.go b/vendor/github.com/coreos/etcd/pkg/transport/limit_listen.go
new file mode 100644
index 00000000..930c5420
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/limit_listen.go
@@ -0,0 +1,80 @@
+// Copyright 2013 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package transport provides network utility functions, complementing the more
+// common ones in the net package.
+package transport
+
+import (
+ "errors"
+ "net"
+ "sync"
+ "time"
+)
+
+var (
+ ErrNotTCP = errors.New("only tcp connections have keepalive")
+)
+
+// LimitListener returns a Listener that accepts at most n simultaneous
+// connections from the provided Listener.
+func LimitListener(l net.Listener, n int) net.Listener {
+ return &limitListener{l, make(chan struct{}, n)}
+}
+
+type limitListener struct {
+ net.Listener
+ sem chan struct{}
+}
+
+func (l *limitListener) acquire() { l.sem <- struct{}{} }
+func (l *limitListener) release() { <-l.sem }
+
+func (l *limitListener) Accept() (net.Conn, error) {
+ l.acquire()
+ c, err := l.Listener.Accept()
+ if err != nil {
+ l.release()
+ return nil, err
+ }
+ return &limitListenerConn{Conn: c, release: l.release}, nil
+}
+
+type limitListenerConn struct {
+ net.Conn
+ releaseOnce sync.Once
+ release func()
+}
+
+func (l *limitListenerConn) Close() error {
+ err := l.Conn.Close()
+ l.releaseOnce.Do(l.release)
+ return err
+}
+
+func (l *limitListenerConn) SetKeepAlive(doKeepAlive bool) error {
+ tcpc, ok := l.Conn.(*net.TCPConn)
+ if !ok {
+ return ErrNotTCP
+ }
+ return tcpc.SetKeepAlive(doKeepAlive)
+}
+
+func (l *limitListenerConn) SetKeepAlivePeriod(d time.Duration) error {
+ tcpc, ok := l.Conn.(*net.TCPConn)
+ if !ok {
+ return ErrNotTCP
+ }
+ return tcpc.SetKeepAlivePeriod(d)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/listener.go b/vendor/github.com/coreos/etcd/pkg/transport/listener.go
new file mode 100644
index 00000000..48655063
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/listener.go
@@ -0,0 +1,289 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "math/big"
+ "net"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/coreos/etcd/pkg/tlsutil"
+)
+
+func NewListener(addr, scheme string, tlsinfo *TLSInfo) (l net.Listener, err error) {
+ if l, err = newListener(addr, scheme); err != nil {
+ return nil, err
+ }
+ return wrapTLS(addr, scheme, tlsinfo, l)
+}
+
+func newListener(addr string, scheme string) (net.Listener, error) {
+ if scheme == "unix" || scheme == "unixs" {
+ // unix sockets via unix://laddr
+ return NewUnixListener(addr)
+ }
+ return net.Listen("tcp", addr)
+}
+
+func wrapTLS(addr, scheme string, tlsinfo *TLSInfo, l net.Listener) (net.Listener, error) {
+ if scheme != "https" && scheme != "unixs" {
+ return l, nil
+ }
+ return newTLSListener(l, tlsinfo, checkSAN)
+}
+
+type TLSInfo struct {
+ CertFile string
+ KeyFile string
+ CAFile string // TODO: deprecate this in v4
+ TrustedCAFile string
+ ClientCertAuth bool
+ CRLFile string
+ InsecureSkipVerify bool
+
+ // ServerName ensures the cert matches the given host in case of discovery / virtual hosting
+ ServerName string
+
+ // HandshakeFailure is optionally called when a connection fails to handshake. The
+ // connection will be closed immediately afterwards.
+ HandshakeFailure func(*tls.Conn, error)
+
+ // CipherSuites is a list of supported cipher suites.
+ // If empty, Go auto-populates it by default.
+ // Note that cipher suites are prioritized in the given order.
+ CipherSuites []uint16
+
+ selfCert bool
+
+ // parseFunc exists to simplify testing. Typically, parseFunc
+ // should be left nil. In that case, tls.X509KeyPair will be used.
+ parseFunc func([]byte, []byte) (tls.Certificate, error)
+
+ // AllowedCN is a CN which must be provided by a client.
+ AllowedCN string
+}
+
+func (info TLSInfo) String() string {
+ return fmt.Sprintf("cert = %s, key = %s, ca = %s, trusted-ca = %s, client-cert-auth = %v, crl-file = %s", info.CertFile, info.KeyFile, info.CAFile, info.TrustedCAFile, info.ClientCertAuth, info.CRLFile)
+}
+
+func (info TLSInfo) Empty() bool {
+ return info.CertFile == "" && info.KeyFile == ""
+}
+
+func SelfCert(dirpath string, hosts []string) (info TLSInfo, err error) {
+ if err = os.MkdirAll(dirpath, 0700); err != nil {
+ return
+ }
+
+ certPath := filepath.Join(dirpath, "cert.pem")
+ keyPath := filepath.Join(dirpath, "key.pem")
+ _, errcert := os.Stat(certPath)
+ _, errkey := os.Stat(keyPath)
+ if errcert == nil && errkey == nil {
+ info.CertFile = certPath
+ info.KeyFile = keyPath
+ info.selfCert = true
+ return
+ }
+
+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+ serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+ if err != nil {
+ return
+ }
+
+ tmpl := x509.Certificate{
+ SerialNumber: serialNumber,
+ Subject: pkix.Name{Organization: []string{"etcd"}},
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(365 * (24 * time.Hour)),
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ }
+
+ for _, host := range hosts {
+ h, _, _ := net.SplitHostPort(host)
+ if ip := net.ParseIP(h); ip != nil {
+ tmpl.IPAddresses = append(tmpl.IPAddresses, ip)
+ } else {
+ tmpl.DNSNames = append(tmpl.DNSNames, h)
+ }
+ }
+
+ priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+ if err != nil {
+ return
+ }
+
+ derBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, &priv.PublicKey, priv)
+ if err != nil {
+ return
+ }
+
+ certOut, err := os.Create(certPath)
+ if err != nil {
+ return
+ }
+ pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
+ certOut.Close()
+
+ b, err := x509.MarshalECPrivateKey(priv)
+ if err != nil {
+ return
+ }
+ keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+ if err != nil {
+ return
+ }
+ pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
+ keyOut.Close()
+
+ return SelfCert(dirpath, hosts)
+}
+
+func (info TLSInfo) baseConfig() (*tls.Config, error) {
+ if info.KeyFile == "" || info.CertFile == "" {
+ return nil, fmt.Errorf("KeyFile and CertFile must both be present[key: %v, cert: %v]", info.KeyFile, info.CertFile)
+ }
+
+ _, err := tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc)
+ if err != nil {
+ return nil, err
+ }
+
+ cfg := &tls.Config{
+ MinVersion: tls.VersionTLS12,
+ ServerName: info.ServerName,
+ }
+
+ if len(info.CipherSuites) > 0 {
+ cfg.CipherSuites = info.CipherSuites
+ }
+
+ if info.AllowedCN != "" {
+ cfg.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
+ for _, chains := range verifiedChains {
+ if len(chains) != 0 {
+ if info.AllowedCN == chains[0].Subject.CommonName {
+ return nil
+ }
+ }
+ }
+ return errors.New("CommonName authentication failed")
+ }
+ }
+
+ // this only reloads certs when there's a client request
+ // TODO: support server-side refresh (e.g. inotify, SIGHUP), caching
+ cfg.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ return tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc)
+ }
+ cfg.GetClientCertificate = func(unused *tls.CertificateRequestInfo) (*tls.Certificate, error) {
+ return tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc)
+ }
+ return cfg, nil
+}
+
+// cafiles returns a list of CA file paths.
+func (info TLSInfo) cafiles() []string {
+ cs := make([]string, 0)
+ if info.CAFile != "" {
+ cs = append(cs, info.CAFile)
+ }
+ if info.TrustedCAFile != "" {
+ cs = append(cs, info.TrustedCAFile)
+ }
+ return cs
+}
+
+// ServerConfig generates a tls.Config object for use by an HTTP server.
+func (info TLSInfo) ServerConfig() (*tls.Config, error) {
+ cfg, err := info.baseConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ cfg.ClientAuth = tls.NoClientCert
+ if info.CAFile != "" || info.ClientCertAuth {
+ cfg.ClientAuth = tls.RequireAndVerifyClientCert
+ }
+
+ CAFiles := info.cafiles()
+ if len(CAFiles) > 0 {
+ cp, err := tlsutil.NewCertPool(CAFiles)
+ if err != nil {
+ return nil, err
+ }
+ cfg.ClientCAs = cp
+ }
+
+ // "h2" NextProtos is necessary for enabling HTTP2 for go's HTTP server
+ cfg.NextProtos = []string{"h2"}
+
+ return cfg, nil
+}
+
+// ClientConfig generates a tls.Config object for use by an HTTP client.
+func (info TLSInfo) ClientConfig() (*tls.Config, error) {
+ var cfg *tls.Config
+ var err error
+
+ if !info.Empty() {
+ cfg, err = info.baseConfig()
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ cfg = &tls.Config{ServerName: info.ServerName}
+ }
+ cfg.InsecureSkipVerify = info.InsecureSkipVerify
+
+ CAFiles := info.cafiles()
+ if len(CAFiles) > 0 {
+ cfg.RootCAs, err = tlsutil.NewCertPool(CAFiles)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if info.selfCert {
+ cfg.InsecureSkipVerify = true
+ }
+ return cfg, nil
+}
+
+// IsClosedConnError returns true if the error is from closing listener, cmux.
+// copied from golang.org/x/net/http2/http2.go
+func IsClosedConnError(err error) bool {
+ // 'use of closed network connection' (Go <=1.8)
+ // 'use of closed file or network connection' (Go >1.8, internal/poll.ErrClosing)
+ // 'mux: listener closed' (cmux.ErrListenerClosed)
+ return err != nil && strings.Contains(err.Error(), "closed")
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/listener_tls.go b/vendor/github.com/coreos/etcd/pkg/transport/listener_tls.go
new file mode 100644
index 00000000..6f160094
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/listener_tls.go
@@ -0,0 +1,272 @@
+// Copyright 2017 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "context"
+ "crypto/tls"
+ "crypto/x509"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "strings"
+ "sync"
+)
+
+// tlsListener overrides a TLS listener so it will reject client
+// certificates with insufficient SAN credentials or CRL revoked
+// certificates.
+type tlsListener struct {
+ net.Listener
+ connc chan net.Conn
+ donec chan struct{}
+ err error
+ handshakeFailure func(*tls.Conn, error)
+ check tlsCheckFunc
+}
+
+type tlsCheckFunc func(context.Context, *tls.Conn) error
+
+// NewTLSListener handshakes TLS connections and performs optional CRL checking.
+func NewTLSListener(l net.Listener, tlsinfo *TLSInfo) (net.Listener, error) {
+ check := func(context.Context, *tls.Conn) error { return nil }
+ return newTLSListener(l, tlsinfo, check)
+}
+
+func newTLSListener(l net.Listener, tlsinfo *TLSInfo, check tlsCheckFunc) (net.Listener, error) {
+ if tlsinfo == nil || tlsinfo.Empty() {
+ l.Close()
+ return nil, fmt.Errorf("cannot listen on TLS for %s: KeyFile and CertFile are not presented", l.Addr().String())
+ }
+ tlscfg, err := tlsinfo.ServerConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ hf := tlsinfo.HandshakeFailure
+ if hf == nil {
+ hf = func(*tls.Conn, error) {}
+ }
+
+ if len(tlsinfo.CRLFile) > 0 {
+ prevCheck := check
+ check = func(ctx context.Context, tlsConn *tls.Conn) error {
+ if err := prevCheck(ctx, tlsConn); err != nil {
+ return err
+ }
+ st := tlsConn.ConnectionState()
+ if certs := st.PeerCertificates; len(certs) > 0 {
+ return checkCRL(tlsinfo.CRLFile, certs)
+ }
+ return nil
+ }
+ }
+
+ tlsl := &tlsListener{
+ Listener: tls.NewListener(l, tlscfg),
+ connc: make(chan net.Conn),
+ donec: make(chan struct{}),
+ handshakeFailure: hf,
+ check: check,
+ }
+ go tlsl.acceptLoop()
+ return tlsl, nil
+}
+
+func (l *tlsListener) Accept() (net.Conn, error) {
+ select {
+ case conn := <-l.connc:
+ return conn, nil
+ case <-l.donec:
+ return nil, l.err
+ }
+}
+
+func checkSAN(ctx context.Context, tlsConn *tls.Conn) error {
+ st := tlsConn.ConnectionState()
+ if certs := st.PeerCertificates; len(certs) > 0 {
+ addr := tlsConn.RemoteAddr().String()
+ return checkCertSAN(ctx, certs[0], addr)
+ }
+ return nil
+}
+
+// acceptLoop launches each TLS handshake in a separate goroutine
+// to prevent a hanging TLS connection from blocking other connections.
+func (l *tlsListener) acceptLoop() {
+ var wg sync.WaitGroup
+ var pendingMu sync.Mutex
+
+ pending := make(map[net.Conn]struct{})
+ ctx, cancel := context.WithCancel(context.Background())
+ defer func() {
+ cancel()
+ pendingMu.Lock()
+ for c := range pending {
+ c.Close()
+ }
+ pendingMu.Unlock()
+ wg.Wait()
+ close(l.donec)
+ }()
+
+ for {
+ conn, err := l.Listener.Accept()
+ if err != nil {
+ l.err = err
+ return
+ }
+
+ pendingMu.Lock()
+ pending[conn] = struct{}{}
+ pendingMu.Unlock()
+
+ wg.Add(1)
+ go func() {
+ defer func() {
+ if conn != nil {
+ conn.Close()
+ }
+ wg.Done()
+ }()
+
+ tlsConn := conn.(*tls.Conn)
+ herr := tlsConn.Handshake()
+ pendingMu.Lock()
+ delete(pending, conn)
+ pendingMu.Unlock()
+
+ if herr != nil {
+ l.handshakeFailure(tlsConn, herr)
+ return
+ }
+ if err := l.check(ctx, tlsConn); err != nil {
+ l.handshakeFailure(tlsConn, err)
+ return
+ }
+
+ select {
+ case l.connc <- tlsConn:
+ conn = nil
+ case <-ctx.Done():
+ }
+ }()
+ }
+}
+
+func checkCRL(crlPath string, cert []*x509.Certificate) error {
+ // TODO: cache
+ crlBytes, err := ioutil.ReadFile(crlPath)
+ if err != nil {
+ return err
+ }
+ certList, err := x509.ParseCRL(crlBytes)
+ if err != nil {
+ return err
+ }
+ revokedSerials := make(map[string]struct{})
+ for _, rc := range certList.TBSCertList.RevokedCertificates {
+ revokedSerials[string(rc.SerialNumber.Bytes())] = struct{}{}
+ }
+ for _, c := range cert {
+ serial := string(c.SerialNumber.Bytes())
+ if _, ok := revokedSerials[serial]; ok {
+ return fmt.Errorf("transport: certificate serial %x revoked", serial)
+ }
+ }
+ return nil
+}
+
+func checkCertSAN(ctx context.Context, cert *x509.Certificate, remoteAddr string) error {
+ if len(cert.IPAddresses) == 0 && len(cert.DNSNames) == 0 {
+ return nil
+ }
+ h, _, herr := net.SplitHostPort(remoteAddr)
+ if herr != nil {
+ return herr
+ }
+ if len(cert.IPAddresses) > 0 {
+ cerr := cert.VerifyHostname(h)
+ if cerr == nil {
+ return nil
+ }
+ if len(cert.DNSNames) == 0 {
+ return cerr
+ }
+ }
+ if len(cert.DNSNames) > 0 {
+ ok, err := isHostInDNS(ctx, h, cert.DNSNames)
+ if ok {
+ return nil
+ }
+ errStr := ""
+ if err != nil {
+ errStr = " (" + err.Error() + ")"
+ }
+ return fmt.Errorf("tls: %q does not match any of DNSNames %q"+errStr, h, cert.DNSNames)
+ }
+ return nil
+}
+
+func isHostInDNS(ctx context.Context, host string, dnsNames []string) (ok bool, err error) {
+ // reverse lookup
+ wildcards, names := []string{}, []string{}
+ for _, dns := range dnsNames {
+ if strings.HasPrefix(dns, "*.") {
+ wildcards = append(wildcards, dns[1:])
+ } else {
+ names = append(names, dns)
+ }
+ }
+ lnames, lerr := net.DefaultResolver.LookupAddr(ctx, host)
+ for _, name := range lnames {
+ // strip trailing '.' from PTR record
+ if name[len(name)-1] == '.' {
+ name = name[:len(name)-1]
+ }
+ for _, wc := range wildcards {
+ if strings.HasSuffix(name, wc) {
+ return true, nil
+ }
+ }
+ for _, n := range names {
+ if n == name {
+ return true, nil
+ }
+ }
+ }
+ err = lerr
+
+ // forward lookup
+ for _, dns := range names {
+ addrs, lerr := net.DefaultResolver.LookupHost(ctx, dns)
+ if lerr != nil {
+ err = lerr
+ continue
+ }
+ for _, addr := range addrs {
+ if addr == host {
+ return true, nil
+ }
+ }
+ }
+ return false, err
+}
+
+func (l *tlsListener) Close() error {
+ err := l.Listener.Close()
+ <-l.donec
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/timeout_conn.go b/vendor/github.com/coreos/etcd/pkg/transport/timeout_conn.go
new file mode 100644
index 00000000..7e8c0203
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/timeout_conn.go
@@ -0,0 +1,44 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "net"
+ "time"
+)
+
+type timeoutConn struct {
+ net.Conn
+ wtimeoutd time.Duration
+ rdtimeoutd time.Duration
+}
+
+func (c timeoutConn) Write(b []byte) (n int, err error) {
+ if c.wtimeoutd > 0 {
+ if err := c.SetWriteDeadline(time.Now().Add(c.wtimeoutd)); err != nil {
+ return 0, err
+ }
+ }
+ return c.Conn.Write(b)
+}
+
+func (c timeoutConn) Read(b []byte) (n int, err error) {
+ if c.rdtimeoutd > 0 {
+ if err := c.SetReadDeadline(time.Now().Add(c.rdtimeoutd)); err != nil {
+ return 0, err
+ }
+ }
+ return c.Conn.Read(b)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/timeout_dialer.go b/vendor/github.com/coreos/etcd/pkg/transport/timeout_dialer.go
new file mode 100644
index 00000000..6ae39ecf
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/timeout_dialer.go
@@ -0,0 +1,36 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "net"
+ "time"
+)
+
+type rwTimeoutDialer struct {
+ wtimeoutd time.Duration
+ rdtimeoutd time.Duration
+ net.Dialer
+}
+
+func (d *rwTimeoutDialer) Dial(network, address string) (net.Conn, error) {
+ conn, err := d.Dialer.Dial(network, address)
+ tconn := &timeoutConn{
+ rdtimeoutd: d.rdtimeoutd,
+ wtimeoutd: d.wtimeoutd,
+ Conn: conn,
+ }
+ return tconn, err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/timeout_listener.go b/vendor/github.com/coreos/etcd/pkg/transport/timeout_listener.go
new file mode 100644
index 00000000..b35e0495
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/timeout_listener.go
@@ -0,0 +1,57 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "net"
+ "time"
+)
+
+// NewTimeoutListener returns a listener that listens on the given address.
+// If read/write on the accepted connection blocks longer than its time limit,
+// it will return timeout error.
+func NewTimeoutListener(addr string, scheme string, tlsinfo *TLSInfo, rdtimeoutd, wtimeoutd time.Duration) (net.Listener, error) {
+ ln, err := newListener(addr, scheme)
+ if err != nil {
+ return nil, err
+ }
+ ln = &rwTimeoutListener{
+ Listener: ln,
+ rdtimeoutd: rdtimeoutd,
+ wtimeoutd: wtimeoutd,
+ }
+ if ln, err = wrapTLS(addr, scheme, tlsinfo, ln); err != nil {
+ return nil, err
+ }
+ return ln, nil
+}
+
+type rwTimeoutListener struct {
+ net.Listener
+ wtimeoutd time.Duration
+ rdtimeoutd time.Duration
+}
+
+func (rwln *rwTimeoutListener) Accept() (net.Conn, error) {
+ c, err := rwln.Listener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ return timeoutConn{
+ Conn: c,
+ wtimeoutd: rwln.wtimeoutd,
+ rdtimeoutd: rwln.rdtimeoutd,
+ }, nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/timeout_transport.go b/vendor/github.com/coreos/etcd/pkg/transport/timeout_transport.go
new file mode 100644
index 00000000..ea16b4c0
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/timeout_transport.go
@@ -0,0 +1,51 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "net"
+ "net/http"
+ "time"
+)
+
+// NewTimeoutTransport returns a transport created using the given TLS info.
+// If read/write on the created connection blocks longer than its time limit,
+// it will return timeout error.
+// If read/write timeout is set, transport will not be able to reuse connection.
+func NewTimeoutTransport(info TLSInfo, dialtimeoutd, rdtimeoutd, wtimeoutd time.Duration) (*http.Transport, error) {
+ tr, err := NewTransport(info, dialtimeoutd)
+ if err != nil {
+ return nil, err
+ }
+
+ if rdtimeoutd != 0 || wtimeoutd != 0 {
+ // the timed out connection will timeout soon after it is idle.
+ // it should not be put back to http transport as an idle connection for future usage.
+ tr.MaxIdleConnsPerHost = -1
+ } else {
+ // allow more idle connections between peers to avoid unnecessary port allocation.
+ tr.MaxIdleConnsPerHost = 1024
+ }
+
+ tr.Dial = (&rwTimeoutDialer{
+ Dialer: net.Dialer{
+ Timeout: dialtimeoutd,
+ KeepAlive: 30 * time.Second,
+ },
+ rdtimeoutd: rdtimeoutd,
+ wtimeoutd: wtimeoutd,
+ }).Dial
+ return tr, nil
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/tls.go b/vendor/github.com/coreos/etcd/pkg/transport/tls.go
new file mode 100644
index 00000000..62fe0d38
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/tls.go
@@ -0,0 +1,49 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "fmt"
+ "strings"
+ "time"
+)
+
+// ValidateSecureEndpoints scans the given endpoints against tls info, returning only those
+// endpoints that could be validated as secure.
+func ValidateSecureEndpoints(tlsInfo TLSInfo, eps []string) ([]string, error) {
+ t, err := NewTransport(tlsInfo, 5*time.Second)
+ if err != nil {
+ return nil, err
+ }
+ var errs []string
+ var endpoints []string
+ for _, ep := range eps {
+ if !strings.HasPrefix(ep, "https://") {
+ errs = append(errs, fmt.Sprintf("%q is insecure", ep))
+ continue
+ }
+ conn, cerr := t.Dial("tcp", ep[len("https://"):])
+ if cerr != nil {
+ errs = append(errs, fmt.Sprintf("%q failed to dial (%v)", ep, cerr))
+ continue
+ }
+ conn.Close()
+ endpoints = append(endpoints, ep)
+ }
+ if len(errs) != 0 {
+ err = fmt.Errorf("%s", strings.Join(errs, ","))
+ }
+ return endpoints, err
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/transport.go b/vendor/github.com/coreos/etcd/pkg/transport/transport.go
new file mode 100644
index 00000000..4a7fe69d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/transport.go
@@ -0,0 +1,71 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "net"
+ "net/http"
+ "strings"
+ "time"
+)
+
+type unixTransport struct{ *http.Transport }
+
+func NewTransport(info TLSInfo, dialtimeoutd time.Duration) (*http.Transport, error) {
+ cfg, err := info.ClientConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ t := &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ Dial: (&net.Dialer{
+ Timeout: dialtimeoutd,
+ // value taken from http.DefaultTransport
+ KeepAlive: 30 * time.Second,
+ }).Dial,
+ // value taken from http.DefaultTransport
+ TLSHandshakeTimeout: 10 * time.Second,
+ TLSClientConfig: cfg,
+ }
+
+ dialer := (&net.Dialer{
+ Timeout: dialtimeoutd,
+ KeepAlive: 30 * time.Second,
+ })
+ dial := func(net, addr string) (net.Conn, error) {
+ return dialer.Dial("unix", addr)
+ }
+
+ tu := &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ Dial: dial,
+ TLSHandshakeTimeout: 10 * time.Second,
+ TLSClientConfig: cfg,
+ }
+ ut := &unixTransport{tu}
+
+ t.RegisterProtocol("unix", ut)
+ t.RegisterProtocol("unixs", ut)
+
+ return t, nil
+}
+
+func (urt *unixTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ url := *req.URL
+ req.URL = &url
+ req.URL.Scheme = strings.Replace(req.URL.Scheme, "unix", "http", 1)
+ return urt.Transport.RoundTrip(req)
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/transport/unix_listener.go b/vendor/github.com/coreos/etcd/pkg/transport/unix_listener.go
new file mode 100644
index 00000000..123e2036
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/transport/unix_listener.go
@@ -0,0 +1,40 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package transport
+
+import (
+ "net"
+ "os"
+)
+
+type unixListener struct{ net.Listener }
+
+func NewUnixListener(addr string) (net.Listener, error) {
+ if err := os.Remove(addr); err != nil && !os.IsNotExist(err) {
+ return nil, err
+ }
+ l, err := net.Listen("unix", addr)
+ if err != nil {
+ return nil, err
+ }
+ return &unixListener{l}, nil
+}
+
+func (ul *unixListener) Close() error {
+ if err := os.Remove(ul.Addr().String()); err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ return ul.Listener.Close()
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/types/doc.go b/vendor/github.com/coreos/etcd/pkg/types/doc.go
new file mode 100644
index 00000000..de8ef0bd
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/types/doc.go
@@ -0,0 +1,17 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package types declares various data types and implements type-checking
+// functions.
+package types
diff --git a/vendor/github.com/coreos/etcd/pkg/types/id.go b/vendor/github.com/coreos/etcd/pkg/types/id.go
new file mode 100644
index 00000000..1b042d9c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/types/id.go
@@ -0,0 +1,41 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "strconv"
+)
+
+// ID represents a generic identifier which is canonically
+// stored as a uint64 but is typically represented as a
+// base-16 string for input/output
+type ID uint64
+
+func (i ID) String() string {
+ return strconv.FormatUint(uint64(i), 16)
+}
+
+// IDFromString attempts to create an ID from a base-16 string.
+func IDFromString(s string) (ID, error) {
+ i, err := strconv.ParseUint(s, 16, 64)
+ return ID(i), err
+}
+
+// IDSlice implements the sort interface
+type IDSlice []ID
+
+func (p IDSlice) Len() int { return len(p) }
+func (p IDSlice) Less(i, j int) bool { return uint64(p[i]) < uint64(p[j]) }
+func (p IDSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
diff --git a/vendor/github.com/coreos/etcd/pkg/types/set.go b/vendor/github.com/coreos/etcd/pkg/types/set.go
new file mode 100644
index 00000000..c111b0c0
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/types/set.go
@@ -0,0 +1,178 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "reflect"
+ "sort"
+ "sync"
+)
+
+type Set interface {
+ Add(string)
+ Remove(string)
+ Contains(string) bool
+ Equals(Set) bool
+ Length() int
+ Values() []string
+ Copy() Set
+ Sub(Set) Set
+}
+
+func NewUnsafeSet(values ...string) *unsafeSet {
+ set := &unsafeSet{make(map[string]struct{})}
+ for _, v := range values {
+ set.Add(v)
+ }
+ return set
+}
+
+func NewThreadsafeSet(values ...string) *tsafeSet {
+ us := NewUnsafeSet(values...)
+ return &tsafeSet{us, sync.RWMutex{}}
+}
+
+type unsafeSet struct {
+ d map[string]struct{}
+}
+
+// Add adds a new value to the set (no-op if the value is already present)
+func (us *unsafeSet) Add(value string) {
+ us.d[value] = struct{}{}
+}
+
+// Remove removes the given value from the set
+func (us *unsafeSet) Remove(value string) {
+ delete(us.d, value)
+}
+
+// Contains returns whether the set contains the given value
+func (us *unsafeSet) Contains(value string) (exists bool) {
+ _, exists = us.d[value]
+ return exists
+}
+
+// ContainsAll returns whether the set contains all given values
+func (us *unsafeSet) ContainsAll(values []string) bool {
+ for _, s := range values {
+ if !us.Contains(s) {
+ return false
+ }
+ }
+ return true
+}
+
+// Equals returns whether the contents of two sets are identical
+func (us *unsafeSet) Equals(other Set) bool {
+ v1 := sort.StringSlice(us.Values())
+ v2 := sort.StringSlice(other.Values())
+ v1.Sort()
+ v2.Sort()
+ return reflect.DeepEqual(v1, v2)
+}
+
+// Length returns the number of elements in the set
+func (us *unsafeSet) Length() int {
+ return len(us.d)
+}
+
+// Values returns the values of the Set in an unspecified order.
+func (us *unsafeSet) Values() (values []string) {
+ values = make([]string, 0)
+ for val := range us.d {
+ values = append(values, val)
+ }
+ return values
+}
+
+// Copy creates a new Set containing the values of the first
+func (us *unsafeSet) Copy() Set {
+ cp := NewUnsafeSet()
+ for val := range us.d {
+ cp.Add(val)
+ }
+
+ return cp
+}
+
+// Sub removes all elements in other from the set
+func (us *unsafeSet) Sub(other Set) Set {
+ oValues := other.Values()
+ result := us.Copy().(*unsafeSet)
+
+ for _, val := range oValues {
+ if _, ok := result.d[val]; !ok {
+ continue
+ }
+ delete(result.d, val)
+ }
+
+ return result
+}
+
+type tsafeSet struct {
+ us *unsafeSet
+ m sync.RWMutex
+}
+
+func (ts *tsafeSet) Add(value string) {
+ ts.m.Lock()
+ defer ts.m.Unlock()
+ ts.us.Add(value)
+}
+
+func (ts *tsafeSet) Remove(value string) {
+ ts.m.Lock()
+ defer ts.m.Unlock()
+ ts.us.Remove(value)
+}
+
+func (ts *tsafeSet) Contains(value string) (exists bool) {
+ ts.m.RLock()
+ defer ts.m.RUnlock()
+ return ts.us.Contains(value)
+}
+
+func (ts *tsafeSet) Equals(other Set) bool {
+ ts.m.RLock()
+ defer ts.m.RUnlock()
+ return ts.us.Equals(other)
+}
+
+func (ts *tsafeSet) Length() int {
+ ts.m.RLock()
+ defer ts.m.RUnlock()
+ return ts.us.Length()
+}
+
+func (ts *tsafeSet) Values() (values []string) {
+ ts.m.RLock()
+ defer ts.m.RUnlock()
+ return ts.us.Values()
+}
+
+func (ts *tsafeSet) Copy() Set {
+ ts.m.RLock()
+ defer ts.m.RUnlock()
+ usResult := ts.us.Copy().(*unsafeSet)
+ return &tsafeSet{usResult, sync.RWMutex{}}
+}
+
+func (ts *tsafeSet) Sub(other Set) Set {
+ ts.m.RLock()
+ defer ts.m.RUnlock()
+ usResult := ts.us.Sub(other).(*unsafeSet)
+ return &tsafeSet{usResult, sync.RWMutex{}}
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/types/slice.go b/vendor/github.com/coreos/etcd/pkg/types/slice.go
new file mode 100644
index 00000000..0dd9ca79
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/types/slice.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+// Uint64Slice implements sort interface
+type Uint64Slice []uint64
+
+func (p Uint64Slice) Len() int { return len(p) }
+func (p Uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p Uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
diff --git a/vendor/github.com/coreos/etcd/pkg/types/urls.go b/vendor/github.com/coreos/etcd/pkg/types/urls.go
new file mode 100644
index 00000000..9e5d03ff
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/types/urls.go
@@ -0,0 +1,82 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "sort"
+ "strings"
+)
+
+type URLs []url.URL
+
+func NewURLs(strs []string) (URLs, error) {
+ all := make([]url.URL, len(strs))
+ if len(all) == 0 {
+ return nil, errors.New("no valid URLs given")
+ }
+ for i, in := range strs {
+ in = strings.TrimSpace(in)
+ u, err := url.Parse(in)
+ if err != nil {
+ return nil, err
+ }
+ if u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "unix" && u.Scheme != "unixs" {
+ return nil, fmt.Errorf("URL scheme must be http, https, unix, or unixs: %s", in)
+ }
+ if _, _, err := net.SplitHostPort(u.Host); err != nil {
+ return nil, fmt.Errorf(`URL address does not have the form "host:port": %s`, in)
+ }
+ if u.Path != "" {
+ return nil, fmt.Errorf("URL must not contain a path: %s", in)
+ }
+ all[i] = *u
+ }
+ us := URLs(all)
+ us.Sort()
+
+ return us, nil
+}
+
+func MustNewURLs(strs []string) URLs {
+ urls, err := NewURLs(strs)
+ if err != nil {
+ panic(err)
+ }
+ return urls
+}
+
+func (us URLs) String() string {
+ return strings.Join(us.StringSlice(), ",")
+}
+
+func (us *URLs) Sort() {
+ sort.Sort(us)
+}
+func (us URLs) Len() int { return len(us) }
+func (us URLs) Less(i, j int) bool { return us[i].String() < us[j].String() }
+func (us URLs) Swap(i, j int) { us[i], us[j] = us[j], us[i] }
+
+func (us URLs) StringSlice() []string {
+ out := make([]string, len(us))
+ for i := range us {
+ out[i] = us[i].String()
+ }
+
+ return out
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/types/urlsmap.go b/vendor/github.com/coreos/etcd/pkg/types/urlsmap.go
new file mode 100644
index 00000000..47690cc3
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/types/urlsmap.go
@@ -0,0 +1,107 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// URLsMap is a map from a name to its URLs.
+type URLsMap map[string]URLs
+
+// NewURLsMap returns a URLsMap instantiated from the given string,
+// which consists of discovery-formatted names-to-URLs, like:
+// mach0=http://1.1.1.1:2380,mach0=http://2.2.2.2::2380,mach1=http://3.3.3.3:2380,mach2=http://4.4.4.4:2380
+func NewURLsMap(s string) (URLsMap, error) {
+ m := parse(s)
+
+ cl := URLsMap{}
+ for name, urls := range m {
+ us, err := NewURLs(urls)
+ if err != nil {
+ return nil, err
+ }
+ cl[name] = us
+ }
+ return cl, nil
+}
+
+// NewURLsMapFromStringMap takes a map of strings and returns a URLsMap. The
+// string values in the map can be multiple values separated by the sep string.
+func NewURLsMapFromStringMap(m map[string]string, sep string) (URLsMap, error) {
+ var err error
+ um := URLsMap{}
+ for k, v := range m {
+ um[k], err = NewURLs(strings.Split(v, sep))
+ if err != nil {
+ return nil, err
+ }
+ }
+ return um, nil
+}
+
+// String turns URLsMap into discovery-formatted name-to-URLs sorted by name.
+func (c URLsMap) String() string {
+ var pairs []string
+ for name, urls := range c {
+ for _, url := range urls {
+ pairs = append(pairs, fmt.Sprintf("%s=%s", name, url.String()))
+ }
+ }
+ sort.Strings(pairs)
+ return strings.Join(pairs, ",")
+}
+
+// URLs returns a list of all URLs.
+// The returned list is sorted in ascending lexicographical order.
+func (c URLsMap) URLs() []string {
+ var urls []string
+ for _, us := range c {
+ for _, u := range us {
+ urls = append(urls, u.String())
+ }
+ }
+ sort.Strings(urls)
+ return urls
+}
+
+// Len returns the size of URLsMap.
+func (c URLsMap) Len() int {
+ return len(c)
+}
+
+// parse parses the given string and returns a map listing the values specified for each key.
+func parse(s string) map[string][]string {
+ m := make(map[string][]string)
+ for s != "" {
+ key := s
+ if i := strings.IndexAny(key, ","); i >= 0 {
+ key, s = key[:i], key[i+1:]
+ } else {
+ s = ""
+ }
+ if key == "" {
+ continue
+ }
+ value := ""
+ if i := strings.Index(key, "="); i >= 0 {
+ key, value = key[:i], key[i+1:]
+ }
+ m[key] = append(m[key], value)
+ }
+ return m
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/wait/wait.go b/vendor/github.com/coreos/etcd/pkg/wait/wait.go
new file mode 100644
index 00000000..9b1df419
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/wait/wait.go
@@ -0,0 +1,91 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package wait provides utility functions for polling, listening using Go
+// channel.
+package wait
+
+import (
+ "log"
+ "sync"
+)
+
+// Wait is an interface that provides the ability to wait and trigger events that
+// are associated with IDs.
+type Wait interface {
+ // Register waits returns a chan that waits on the given ID.
+ // The chan will be triggered when Trigger is called with
+ // the same ID.
+ Register(id uint64) <-chan interface{}
+ // Trigger triggers the waiting chans with the given ID.
+ Trigger(id uint64, x interface{})
+ IsRegistered(id uint64) bool
+}
+
+type list struct {
+ l sync.RWMutex
+ m map[uint64]chan interface{}
+}
+
+// New creates a Wait.
+func New() Wait {
+ return &list{m: make(map[uint64]chan interface{})}
+}
+
+func (w *list) Register(id uint64) <-chan interface{} {
+ w.l.Lock()
+ defer w.l.Unlock()
+ ch := w.m[id]
+ if ch == nil {
+ ch = make(chan interface{}, 1)
+ w.m[id] = ch
+ } else {
+ log.Panicf("dup id %x", id)
+ }
+ return ch
+}
+
+func (w *list) Trigger(id uint64, x interface{}) {
+ w.l.Lock()
+ ch := w.m[id]
+ delete(w.m, id)
+ w.l.Unlock()
+ if ch != nil {
+ ch <- x
+ close(ch)
+ }
+}
+
+func (w *list) IsRegistered(id uint64) bool {
+ w.l.RLock()
+ defer w.l.RUnlock()
+ _, ok := w.m[id]
+ return ok
+}
+
+type waitWithResponse struct {
+ ch <-chan interface{}
+}
+
+func NewWithResponse(ch <-chan interface{}) Wait {
+ return &waitWithResponse{ch: ch}
+}
+
+func (w *waitWithResponse) Register(id uint64) <-chan interface{} {
+ return w.ch
+}
+func (w *waitWithResponse) Trigger(id uint64, x interface{}) {}
+func (w *waitWithResponse) IsRegistered(id uint64) bool {
+ panic("waitWithResponse.IsRegistered() shouldn't be called")
+}
diff --git a/vendor/github.com/coreos/etcd/pkg/wait/wait_time.go b/vendor/github.com/coreos/etcd/pkg/wait/wait_time.go
new file mode 100644
index 00000000..297e48a4
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/pkg/wait/wait_time.go
@@ -0,0 +1,66 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wait
+
+import "sync"
+
+type WaitTime interface {
+ // Wait returns a chan that waits on the given logical deadline.
+ // The chan will be triggered when Trigger is called with a
+ // deadline that is later than the one it is waiting for.
+ Wait(deadline uint64) <-chan struct{}
+ // Trigger triggers all the waiting chans with an earlier logical deadline.
+ Trigger(deadline uint64)
+}
+
+var closec chan struct{}
+
+func init() { closec = make(chan struct{}); close(closec) }
+
+type timeList struct {
+ l sync.Mutex
+ lastTriggerDeadline uint64
+ m map[uint64]chan struct{}
+}
+
+func NewTimeList() *timeList {
+ return &timeList{m: make(map[uint64]chan struct{})}
+}
+
+func (tl *timeList) Wait(deadline uint64) <-chan struct{} {
+ tl.l.Lock()
+ defer tl.l.Unlock()
+ if tl.lastTriggerDeadline >= deadline {
+ return closec
+ }
+ ch := tl.m[deadline]
+ if ch == nil {
+ ch = make(chan struct{})
+ tl.m[deadline] = ch
+ }
+ return ch
+}
+
+func (tl *timeList) Trigger(deadline uint64) {
+ tl.l.Lock()
+ defer tl.l.Unlock()
+ tl.lastTriggerDeadline = deadline
+ for t, ch := range tl.m {
+ if t <= deadline {
+ delete(tl.m, t)
+ close(ch)
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/raft/doc.go b/vendor/github.com/coreos/etcd/raft/doc.go
new file mode 100644
index 00000000..b55c591f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/doc.go
@@ -0,0 +1,300 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+Package raft sends and receives messages in the Protocol Buffer format
+defined in the raftpb package.
+
+Raft is a protocol with which a cluster of nodes can maintain a replicated state machine.
+The state machine is kept in sync through the use of a replicated log.
+For more details on Raft, see "In Search of an Understandable Consensus Algorithm"
+(https://ramcloud.stanford.edu/raft.pdf) by Diego Ongaro and John Ousterhout.
+
+A simple example application, _raftexample_, is also available to help illustrate
+how to use this package in practice:
+https://github.com/coreos/etcd/tree/master/contrib/raftexample
+
+Usage
+
+The primary object in raft is a Node. You either start a Node from scratch
+using raft.StartNode or start a Node from some initial state using raft.RestartNode.
+
+To start a node from scratch:
+
+ storage := raft.NewMemoryStorage()
+ c := &Config{
+ ID: 0x01,
+ ElectionTick: 10,
+ HeartbeatTick: 1,
+ Storage: storage,
+ MaxSizePerMsg: 4096,
+ MaxInflightMsgs: 256,
+ }
+ n := raft.StartNode(c, []raft.Peer{{ID: 0x02}, {ID: 0x03}})
+
+To restart a node from previous state:
+
+ storage := raft.NewMemoryStorage()
+
+ // recover the in-memory storage from persistent
+ // snapshot, state and entries.
+ storage.ApplySnapshot(snapshot)
+ storage.SetHardState(state)
+ storage.Append(entries)
+
+ c := &Config{
+ ID: 0x01,
+ ElectionTick: 10,
+ HeartbeatTick: 1,
+ Storage: storage,
+ MaxSizePerMsg: 4096,
+ MaxInflightMsgs: 256,
+ }
+
+ // restart raft without peer information.
+ // peer information is already included in the storage.
+ n := raft.RestartNode(c)
+
+Now that you are holding onto a Node you have a few responsibilities:
+
+First, you must read from the Node.Ready() channel and process the updates
+it contains. These steps may be performed in parallel, except as noted in step
+2.
+
+1. Write HardState, Entries, and Snapshot to persistent storage if they are
+not empty. Note that when writing an Entry with Index i, any
+previously-persisted entries with Index >= i must be discarded.
+
+2. Send all Messages to the nodes named in the To field. It is important that
+no messages be sent until the latest HardState has been persisted to disk,
+and all Entries written by any previous Ready batch (Messages may be sent while
+entries from the same batch are being persisted). To reduce the I/O latency, an
+optimization can be applied to make leader write to disk in parallel with its
+followers (as explained at section 10.2.1 in Raft thesis). If any Message has type
+MsgSnap, call Node.ReportSnapshot() after it has been sent (these messages may be
+large).
+
+Note: Marshalling messages is not thread-safe; it is important that you
+make sure that no new entries are persisted while marshalling.
+The easiest way to achieve this is to serialise the messages directly inside
+your main raft loop.
+
+3. Apply Snapshot (if any) and CommittedEntries to the state machine.
+If any committed Entry has Type EntryConfChange, call Node.ApplyConfChange()
+to apply it to the node. The configuration change may be cancelled at this point
+by setting the NodeID field to zero before calling ApplyConfChange
+(but ApplyConfChange must be called one way or the other, and the decision to cancel
+must be based solely on the state machine and not external information such as
+the observed health of the node).
+
+4. Call Node.Advance() to signal readiness for the next batch of updates.
+This may be done at any time after step 1, although all updates must be processed
+in the order they were returned by Ready.
+
+Second, all persisted log entries must be made available via an
+implementation of the Storage interface. The provided MemoryStorage
+type can be used for this (if you repopulate its state upon a
+restart), or you can supply your own disk-backed implementation.
+
+Third, when you receive a message from another node, pass it to Node.Step:
+
+ func recvRaftRPC(ctx context.Context, m raftpb.Message) {
+ n.Step(ctx, m)
+ }
+
+Finally, you need to call Node.Tick() at regular intervals (probably
+via a time.Ticker). Raft has two important timeouts: heartbeat and the
+election timeout. However, internally to the raft package time is
+represented by an abstract "tick".
+
+The total state machine handling loop will look something like this:
+
+ for {
+ select {
+ case <-s.Ticker:
+ n.Tick()
+ case rd := <-s.Node.Ready():
+ saveToStorage(rd.State, rd.Entries, rd.Snapshot)
+ send(rd.Messages)
+ if !raft.IsEmptySnap(rd.Snapshot) {
+ processSnapshot(rd.Snapshot)
+ }
+ for _, entry := range rd.CommittedEntries {
+ process(entry)
+ if entry.Type == raftpb.EntryConfChange {
+ var cc raftpb.ConfChange
+ cc.Unmarshal(entry.Data)
+ s.Node.ApplyConfChange(cc)
+ }
+ }
+ s.Node.Advance()
+ case <-s.done:
+ return
+ }
+ }
+
+To propose changes to the state machine from your node take your application
+data, serialize it into a byte slice and call:
+
+ n.Propose(ctx, data)
+
+If the proposal is committed, data will appear in committed entries with type
+raftpb.EntryNormal. There is no guarantee that a proposed command will be
+committed; you may have to re-propose after a timeout.
+
+To add or remove node in a cluster, build ConfChange struct 'cc' and call:
+
+ n.ProposeConfChange(ctx, cc)
+
+After config change is committed, some committed entry with type
+raftpb.EntryConfChange will be returned. You must apply it to node through:
+
+ var cc raftpb.ConfChange
+ cc.Unmarshal(data)
+ n.ApplyConfChange(cc)
+
+Note: An ID represents a unique node in a cluster for all time. A
+given ID MUST be used only once even if the old node has been removed.
+This means that for example IP addresses make poor node IDs since they
+may be reused. Node IDs must be non-zero.
+
+Implementation notes
+
+This implementation is up to date with the final Raft thesis
+(https://ramcloud.stanford.edu/~ongaro/thesis.pdf), although our
+implementation of the membership change protocol differs somewhat from
+that described in chapter 4. The key invariant that membership changes
+happen one node at a time is preserved, but in our implementation the
+membership change takes effect when its entry is applied, not when it
+is added to the log (so the entry is committed under the old
+membership instead of the new). This is equivalent in terms of safety,
+since the old and new configurations are guaranteed to overlap.
+
+To ensure that we do not attempt to commit two membership changes at
+once by matching log positions (which would be unsafe since they
+should have different quorum requirements), we simply disallow any
+proposed membership change while any uncommitted change appears in
+the leader's log.
+
+This approach introduces a problem when you try to remove a member
+from a two-member cluster: If one of the members dies before the
+other one receives the commit of the confchange entry, then the member
+cannot be removed any more since the cluster cannot make progress.
+For this reason it is highly recommended to use three or more nodes in
+every cluster.
+
+MessageType
+
+Package raft sends and receives message in Protocol Buffer format (defined
+in raftpb package). Each state (follower, candidate, leader) implements its
+own 'step' method ('stepFollower', 'stepCandidate', 'stepLeader') when
+advancing with the given raftpb.Message. Each step is determined by its
+raftpb.MessageType. Note that every step is checked by one common method
+'Step' that safety-checks the terms of node and incoming message to prevent
+stale log entries:
+
+ 'MsgHup' is used for election. If a node is a follower or candidate, the
+ 'tick' function in 'raft' struct is set as 'tickElection'. If a follower or
+ candidate has not received any heartbeat before the election timeout, it
+ passes 'MsgHup' to its Step method and becomes (or remains) a candidate to
+ start a new election.
+
+ 'MsgBeat' is an internal type that signals the leader to send a heartbeat of
+ the 'MsgHeartbeat' type. If a node is a leader, the 'tick' function in
+ the 'raft' struct is set as 'tickHeartbeat', and triggers the leader to
+ send periodic 'MsgHeartbeat' messages to its followers.
+
+ 'MsgProp' proposes to append data to its log entries. This is a special
+ type to redirect proposals to leader. Therefore, send method overwrites
+ raftpb.Message's term with its HardState's term to avoid attaching its
+ local term to 'MsgProp'. When 'MsgProp' is passed to the leader's 'Step'
+ method, the leader first calls the 'appendEntry' method to append entries
+ to its log, and then calls 'bcastAppend' method to send those entries to
+ its peers. When passed to candidate, 'MsgProp' is dropped. When passed to
+ follower, 'MsgProp' is stored in follower's mailbox(msgs) by the send
+ method. It is stored with sender's ID and later forwarded to leader by
+ rafthttp package.
+
+ 'MsgApp' contains log entries to replicate. A leader calls bcastAppend,
+ which calls sendAppend, which sends soon-to-be-replicated logs in 'MsgApp'
+ type. When 'MsgApp' is passed to candidate's Step method, candidate reverts
+ back to follower, because it indicates that there is a valid leader sending
+ 'MsgApp' messages. Candidate and follower respond to this message in
+ 'MsgAppResp' type.
+
+ 'MsgAppResp' is response to log replication request('MsgApp'). When
+ 'MsgApp' is passed to candidate or follower's Step method, it responds by
+ calling 'handleAppendEntries' method, which sends 'MsgAppResp' to raft
+ mailbox.
+
+ 'MsgVote' requests votes for election. When a node is a follower or
+ candidate and 'MsgHup' is passed to its Step method, then the node calls
+ 'campaign' method to campaign itself to become a leader. Once 'campaign'
+ method is called, the node becomes candidate and sends 'MsgVote' to peers
+ in cluster to request votes. When passed to leader or candidate's Step
+ method and the message's Term is lower than leader's or candidate's,
+ 'MsgVote' will be rejected ('MsgVoteResp' is returned with Reject true).
+ If leader or candidate receives 'MsgVote' with higher term, it will revert
+ back to follower. When 'MsgVote' is passed to follower, it votes for the
+ sender only when sender's last term is greater than MsgVote's term or
+ sender's last term is equal to MsgVote's term but sender's last committed
+ index is greater than or equal to follower's.
+
+ 'MsgVoteResp' contains responses from voting request. When 'MsgVoteResp' is
+ passed to candidate, the candidate calculates how many votes it has won. If
+ it's more than majority (quorum), it becomes leader and calls 'bcastAppend'.
+ If candidate receives majority of votes of denials, it reverts back to
+ follower.
+
+ 'MsgPreVote' and 'MsgPreVoteResp' are used in an optional two-phase election
+ protocol. When Config.PreVote is true, a pre-election is carried out first
+ (using the same rules as a regular election), and no node increases its term
+ number unless the pre-election indicates that the campaigining node would win.
+ This minimizes disruption when a partitioned node rejoins the cluster.
+
+ 'MsgSnap' requests to install a snapshot message. When a node has just
+ become a leader or the leader receives 'MsgProp' message, it calls
+ 'bcastAppend' method, which then calls 'sendAppend' method to each
+ follower. In 'sendAppend', if a leader fails to get term or entries,
+ the leader requests snapshot by sending 'MsgSnap' type message.
+
+ 'MsgSnapStatus' tells the result of snapshot install message. When a
+ follower rejected 'MsgSnap', it indicates the snapshot request with
+ 'MsgSnap' had failed from network issues which causes the network layer
+ to fail to send out snapshots to its followers. Then leader considers
+ follower's progress as probe. When 'MsgSnap' were not rejected, it
+ indicates that the snapshot succeeded and the leader sets follower's
+ progress to probe and resumes its log replication.
+
+ 'MsgHeartbeat' sends heartbeat from leader. When 'MsgHeartbeat' is passed
+ to candidate and message's term is higher than candidate's, the candidate
+ reverts back to follower and updates its committed index from the one in
+ this heartbeat. And it sends the message to its mailbox. When
+ 'MsgHeartbeat' is passed to follower's Step method and message's term is
+ higher than follower's, the follower updates its leaderID with the ID
+ from the message.
+
+ 'MsgHeartbeatResp' is a response to 'MsgHeartbeat'. When 'MsgHeartbeatResp'
+ is passed to leader's Step method, the leader knows which follower
+ responded. And only when the leader's last committed index is greater than
+ follower's Match index, the leader runs 'sendAppend` method.
+
+ 'MsgUnreachable' tells that request(message) wasn't delivered. When
+ 'MsgUnreachable' is passed to leader's Step method, the leader discovers
+ that the follower that sent this 'MsgUnreachable' is not reachable, often
+ indicating 'MsgApp' is lost. When follower's progress state is replicate,
+ the leader sets it back to probe.
+
+*/
+package raft
diff --git a/vendor/github.com/coreos/etcd/raft/log.go b/vendor/github.com/coreos/etcd/raft/log.go
new file mode 100644
index 00000000..c3036d3c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/log.go
@@ -0,0 +1,358 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "fmt"
+ "log"
+
+ pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+type raftLog struct {
+ // storage contains all stable entries since the last snapshot.
+ storage Storage
+
+ // unstable contains all unstable entries and snapshot.
+ // they will be saved into storage.
+ unstable unstable
+
+ // committed is the highest log position that is known to be in
+ // stable storage on a quorum of nodes.
+ committed uint64
+ // applied is the highest log position that the application has
+ // been instructed to apply to its state machine.
+ // Invariant: applied <= committed
+ applied uint64
+
+ logger Logger
+}
+
+// newLog returns log using the given storage. It recovers the log to the state
+// that it just commits and applies the latest snapshot.
+func newLog(storage Storage, logger Logger) *raftLog {
+ if storage == nil {
+ log.Panic("storage must not be nil")
+ }
+ log := &raftLog{
+ storage: storage,
+ logger: logger,
+ }
+ firstIndex, err := storage.FirstIndex()
+ if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+ lastIndex, err := storage.LastIndex()
+ if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+ log.unstable.offset = lastIndex + 1
+ log.unstable.logger = logger
+ // Initialize our committed and applied pointers to the time of the last compaction.
+ log.committed = firstIndex - 1
+ log.applied = firstIndex - 1
+
+ return log
+}
+
+func (l *raftLog) String() string {
+ return fmt.Sprintf("committed=%d, applied=%d, unstable.offset=%d, len(unstable.Entries)=%d", l.committed, l.applied, l.unstable.offset, len(l.unstable.entries))
+}
+
+// maybeAppend returns (0, false) if the entries cannot be appended. Otherwise,
+// it returns (last index of new entries, true).
+func (l *raftLog) maybeAppend(index, logTerm, committed uint64, ents ...pb.Entry) (lastnewi uint64, ok bool) {
+ if l.matchTerm(index, logTerm) {
+ lastnewi = index + uint64(len(ents))
+ ci := l.findConflict(ents)
+ switch {
+ case ci == 0:
+ case ci <= l.committed:
+ l.logger.Panicf("entry %d conflict with committed entry [committed(%d)]", ci, l.committed)
+ default:
+ offset := index + 1
+ l.append(ents[ci-offset:]...)
+ }
+ l.commitTo(min(committed, lastnewi))
+ return lastnewi, true
+ }
+ return 0, false
+}
+
+func (l *raftLog) append(ents ...pb.Entry) uint64 {
+ if len(ents) == 0 {
+ return l.lastIndex()
+ }
+ if after := ents[0].Index - 1; after < l.committed {
+ l.logger.Panicf("after(%d) is out of range [committed(%d)]", after, l.committed)
+ }
+ l.unstable.truncateAndAppend(ents)
+ return l.lastIndex()
+}
+
+// findConflict finds the index of the conflict.
+// It returns the first pair of conflicting entries between the existing
+// entries and the given entries, if there are any.
+// If there is no conflicting entries, and the existing entries contains
+// all the given entries, zero will be returned.
+// If there is no conflicting entries, but the given entries contains new
+// entries, the index of the first new entry will be returned.
+// An entry is considered to be conflicting if it has the same index but
+// a different term.
+// The first entry MUST have an index equal to the argument 'from'.
+// The index of the given entries MUST be continuously increasing.
+func (l *raftLog) findConflict(ents []pb.Entry) uint64 {
+ for _, ne := range ents {
+ if !l.matchTerm(ne.Index, ne.Term) {
+ if ne.Index <= l.lastIndex() {
+ l.logger.Infof("found conflict at index %d [existing term: %d, conflicting term: %d]",
+ ne.Index, l.zeroTermOnErrCompacted(l.term(ne.Index)), ne.Term)
+ }
+ return ne.Index
+ }
+ }
+ return 0
+}
+
+func (l *raftLog) unstableEntries() []pb.Entry {
+ if len(l.unstable.entries) == 0 {
+ return nil
+ }
+ return l.unstable.entries
+}
+
+// nextEnts returns all the available entries for execution.
+// If applied is smaller than the index of snapshot, it returns all committed
+// entries after the index of snapshot.
+func (l *raftLog) nextEnts() (ents []pb.Entry) {
+ off := max(l.applied+1, l.firstIndex())
+ if l.committed+1 > off {
+ ents, err := l.slice(off, l.committed+1, noLimit)
+ if err != nil {
+ l.logger.Panicf("unexpected error when getting unapplied entries (%v)", err)
+ }
+ return ents
+ }
+ return nil
+}
+
+// hasNextEnts returns if there is any available entries for execution. This
+// is a fast check without heavy raftLog.slice() in raftLog.nextEnts().
+func (l *raftLog) hasNextEnts() bool {
+ off := max(l.applied+1, l.firstIndex())
+ return l.committed+1 > off
+}
+
+func (l *raftLog) snapshot() (pb.Snapshot, error) {
+ if l.unstable.snapshot != nil {
+ return *l.unstable.snapshot, nil
+ }
+ return l.storage.Snapshot()
+}
+
+func (l *raftLog) firstIndex() uint64 {
+ if i, ok := l.unstable.maybeFirstIndex(); ok {
+ return i
+ }
+ index, err := l.storage.FirstIndex()
+ if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+ return index
+}
+
+func (l *raftLog) lastIndex() uint64 {
+ if i, ok := l.unstable.maybeLastIndex(); ok {
+ return i
+ }
+ i, err := l.storage.LastIndex()
+ if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+ return i
+}
+
+func (l *raftLog) commitTo(tocommit uint64) {
+ // never decrease commit
+ if l.committed < tocommit {
+ if l.lastIndex() < tocommit {
+ l.logger.Panicf("tocommit(%d) is out of range [lastIndex(%d)]. Was the raft log corrupted, truncated, or lost?", tocommit, l.lastIndex())
+ }
+ l.committed = tocommit
+ }
+}
+
+func (l *raftLog) appliedTo(i uint64) {
+ if i == 0 {
+ return
+ }
+ if l.committed < i || i < l.applied {
+ l.logger.Panicf("applied(%d) is out of range [prevApplied(%d), committed(%d)]", i, l.applied, l.committed)
+ }
+ l.applied = i
+}
+
+func (l *raftLog) stableTo(i, t uint64) { l.unstable.stableTo(i, t) }
+
+func (l *raftLog) stableSnapTo(i uint64) { l.unstable.stableSnapTo(i) }
+
+func (l *raftLog) lastTerm() uint64 {
+ t, err := l.term(l.lastIndex())
+ if err != nil {
+ l.logger.Panicf("unexpected error when getting the last term (%v)", err)
+ }
+ return t
+}
+
+func (l *raftLog) term(i uint64) (uint64, error) {
+ // the valid term range is [index of dummy entry, last index]
+ dummyIndex := l.firstIndex() - 1
+ if i < dummyIndex || i > l.lastIndex() {
+ // TODO: return an error instead?
+ return 0, nil
+ }
+
+ if t, ok := l.unstable.maybeTerm(i); ok {
+ return t, nil
+ }
+
+ t, err := l.storage.Term(i)
+ if err == nil {
+ return t, nil
+ }
+ if err == ErrCompacted || err == ErrUnavailable {
+ return 0, err
+ }
+ panic(err) // TODO(bdarnell)
+}
+
+func (l *raftLog) entries(i, maxsize uint64) ([]pb.Entry, error) {
+ if i > l.lastIndex() {
+ return nil, nil
+ }
+ return l.slice(i, l.lastIndex()+1, maxsize)
+}
+
+// allEntries returns all entries in the log.
+func (l *raftLog) allEntries() []pb.Entry {
+ ents, err := l.entries(l.firstIndex(), noLimit)
+ if err == nil {
+ return ents
+ }
+ if err == ErrCompacted { // try again if there was a racing compaction
+ return l.allEntries()
+ }
+ // TODO (xiangli): handle error?
+ panic(err)
+}
+
+// isUpToDate determines if the given (lastIndex,term) log is more up-to-date
+// by comparing the index and term of the last entries in the existing logs.
+// If the logs have last entries with different terms, then the log with the
+// later term is more up-to-date. If the logs end with the same term, then
+// whichever log has the larger lastIndex is more up-to-date. If the logs are
+// the same, the given log is up-to-date.
+func (l *raftLog) isUpToDate(lasti, term uint64) bool {
+ return term > l.lastTerm() || (term == l.lastTerm() && lasti >= l.lastIndex())
+}
+
+func (l *raftLog) matchTerm(i, term uint64) bool {
+ t, err := l.term(i)
+ if err != nil {
+ return false
+ }
+ return t == term
+}
+
+func (l *raftLog) maybeCommit(maxIndex, term uint64) bool {
+ if maxIndex > l.committed && l.zeroTermOnErrCompacted(l.term(maxIndex)) == term {
+ l.commitTo(maxIndex)
+ return true
+ }
+ return false
+}
+
+func (l *raftLog) restore(s pb.Snapshot) {
+ l.logger.Infof("log [%s] starts to restore snapshot [index: %d, term: %d]", l, s.Metadata.Index, s.Metadata.Term)
+ l.committed = s.Metadata.Index
+ l.unstable.restore(s)
+}
+
+// slice returns a slice of log entries from lo through hi-1, inclusive.
+func (l *raftLog) slice(lo, hi, maxSize uint64) ([]pb.Entry, error) {
+ err := l.mustCheckOutOfBounds(lo, hi)
+ if err != nil {
+ return nil, err
+ }
+ if lo == hi {
+ return nil, nil
+ }
+ var ents []pb.Entry
+ if lo < l.unstable.offset {
+ storedEnts, err := l.storage.Entries(lo, min(hi, l.unstable.offset), maxSize)
+ if err == ErrCompacted {
+ return nil, err
+ } else if err == ErrUnavailable {
+ l.logger.Panicf("entries[%d:%d) is unavailable from storage", lo, min(hi, l.unstable.offset))
+ } else if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+
+ // check if ents has reached the size limitation
+ if uint64(len(storedEnts)) < min(hi, l.unstable.offset)-lo {
+ return storedEnts, nil
+ }
+
+ ents = storedEnts
+ }
+ if hi > l.unstable.offset {
+ unstable := l.unstable.slice(max(lo, l.unstable.offset), hi)
+ if len(ents) > 0 {
+ ents = append([]pb.Entry{}, ents...)
+ ents = append(ents, unstable...)
+ } else {
+ ents = unstable
+ }
+ }
+ return limitSize(ents, maxSize), nil
+}
+
+// l.firstIndex <= lo <= hi <= l.firstIndex + len(l.entries)
+func (l *raftLog) mustCheckOutOfBounds(lo, hi uint64) error {
+ if lo > hi {
+ l.logger.Panicf("invalid slice %d > %d", lo, hi)
+ }
+ fi := l.firstIndex()
+ if lo < fi {
+ return ErrCompacted
+ }
+
+ length := l.lastIndex() + 1 - fi
+ if lo < fi || hi > fi+length {
+ l.logger.Panicf("slice[%d,%d) out of bound [%d,%d]", lo, hi, fi, l.lastIndex())
+ }
+ return nil
+}
+
+func (l *raftLog) zeroTermOnErrCompacted(t uint64, err error) uint64 {
+ if err == nil {
+ return t
+ }
+ if err == ErrCompacted {
+ return 0
+ }
+ l.logger.Panicf("unexpected error (%v)", err)
+ return 0
+}
diff --git a/vendor/github.com/coreos/etcd/raft/log_unstable.go b/vendor/github.com/coreos/etcd/raft/log_unstable.go
new file mode 100644
index 00000000..263af9ce
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/log_unstable.go
@@ -0,0 +1,159 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import pb "github.com/coreos/etcd/raft/raftpb"
+
+// unstable.entries[i] has raft log position i+unstable.offset.
+// Note that unstable.offset may be less than the highest log
+// position in storage; this means that the next write to storage
+// might need to truncate the log before persisting unstable.entries.
+type unstable struct {
+ // the incoming unstable snapshot, if any.
+ snapshot *pb.Snapshot
+ // all entries that have not yet been written to storage.
+ entries []pb.Entry
+ offset uint64
+
+ logger Logger
+}
+
+// maybeFirstIndex returns the index of the first possible entry in entries
+// if it has a snapshot.
+func (u *unstable) maybeFirstIndex() (uint64, bool) {
+ if u.snapshot != nil {
+ return u.snapshot.Metadata.Index + 1, true
+ }
+ return 0, false
+}
+
+// maybeLastIndex returns the last index if it has at least one
+// unstable entry or snapshot.
+func (u *unstable) maybeLastIndex() (uint64, bool) {
+ if l := len(u.entries); l != 0 {
+ return u.offset + uint64(l) - 1, true
+ }
+ if u.snapshot != nil {
+ return u.snapshot.Metadata.Index, true
+ }
+ return 0, false
+}
+
+// maybeTerm returns the term of the entry at index i, if there
+// is any.
+func (u *unstable) maybeTerm(i uint64) (uint64, bool) {
+ if i < u.offset {
+ if u.snapshot == nil {
+ return 0, false
+ }
+ if u.snapshot.Metadata.Index == i {
+ return u.snapshot.Metadata.Term, true
+ }
+ return 0, false
+ }
+
+ last, ok := u.maybeLastIndex()
+ if !ok {
+ return 0, false
+ }
+ if i > last {
+ return 0, false
+ }
+ return u.entries[i-u.offset].Term, true
+}
+
+func (u *unstable) stableTo(i, t uint64) {
+ gt, ok := u.maybeTerm(i)
+ if !ok {
+ return
+ }
+ // if i < offset, term is matched with the snapshot
+ // only update the unstable entries if term is matched with
+ // an unstable entry.
+ if gt == t && i >= u.offset {
+ u.entries = u.entries[i+1-u.offset:]
+ u.offset = i + 1
+ u.shrinkEntriesArray()
+ }
+}
+
+// shrinkEntriesArray discards the underlying array used by the entries slice
+// if most of it isn't being used. This avoids holding references to a bunch of
+// potentially large entries that aren't needed anymore. Simply clearing the
+// entries wouldn't be safe because clients might still be using them.
+func (u *unstable) shrinkEntriesArray() {
+ // We replace the array if we're using less than half of the space in
+ // it. This number is fairly arbitrary, chosen as an attempt to balance
+ // memory usage vs number of allocations. It could probably be improved
+ // with some focused tuning.
+ const lenMultiple = 2
+ if len(u.entries) == 0 {
+ u.entries = nil
+ } else if len(u.entries)*lenMultiple < cap(u.entries) {
+ newEntries := make([]pb.Entry, len(u.entries))
+ copy(newEntries, u.entries)
+ u.entries = newEntries
+ }
+}
+
+func (u *unstable) stableSnapTo(i uint64) {
+ if u.snapshot != nil && u.snapshot.Metadata.Index == i {
+ u.snapshot = nil
+ }
+}
+
+func (u *unstable) restore(s pb.Snapshot) {
+ u.offset = s.Metadata.Index + 1
+ u.entries = nil
+ u.snapshot = &s
+}
+
+func (u *unstable) truncateAndAppend(ents []pb.Entry) {
+ after := ents[0].Index
+ switch {
+ case after == u.offset+uint64(len(u.entries)):
+ // after is the next index in the u.entries
+ // directly append
+ u.entries = append(u.entries, ents...)
+ case after <= u.offset:
+ u.logger.Infof("replace the unstable entries from index %d", after)
+ // The log is being truncated to before our current offset
+ // portion, so set the offset and replace the entries
+ u.offset = after
+ u.entries = ents
+ default:
+ // truncate to after and copy to u.entries
+ // then append
+ u.logger.Infof("truncate the unstable entries before index %d", after)
+ u.entries = append([]pb.Entry{}, u.slice(u.offset, after)...)
+ u.entries = append(u.entries, ents...)
+ }
+}
+
+func (u *unstable) slice(lo uint64, hi uint64) []pb.Entry {
+ u.mustCheckOutOfBounds(lo, hi)
+ return u.entries[lo-u.offset : hi-u.offset]
+}
+
+// u.offset <= lo <= hi <= u.offset+len(u.offset)
+func (u *unstable) mustCheckOutOfBounds(lo, hi uint64) {
+ if lo > hi {
+ u.logger.Panicf("invalid unstable.slice %d > %d", lo, hi)
+ }
+ upper := u.offset + uint64(len(u.entries))
+ if lo < u.offset || hi > upper {
+ u.logger.Panicf("unstable.slice[%d,%d) out of bound [%d,%d]", lo, hi, u.offset, upper)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/raft/logger.go b/vendor/github.com/coreos/etcd/raft/logger.go
new file mode 100644
index 00000000..92e55b37
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/logger.go
@@ -0,0 +1,126 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+)
+
+type Logger interface {
+ Debug(v ...interface{})
+ Debugf(format string, v ...interface{})
+
+ Error(v ...interface{})
+ Errorf(format string, v ...interface{})
+
+ Info(v ...interface{})
+ Infof(format string, v ...interface{})
+
+ Warning(v ...interface{})
+ Warningf(format string, v ...interface{})
+
+ Fatal(v ...interface{})
+ Fatalf(format string, v ...interface{})
+
+ Panic(v ...interface{})
+ Panicf(format string, v ...interface{})
+}
+
+func SetLogger(l Logger) { raftLogger = l }
+
+var (
+ defaultLogger = &DefaultLogger{Logger: log.New(os.Stderr, "raft", log.LstdFlags)}
+ discardLogger = &DefaultLogger{Logger: log.New(ioutil.Discard, "", 0)}
+ raftLogger = Logger(defaultLogger)
+)
+
+const (
+ calldepth = 2
+)
+
+// DefaultLogger is a default implementation of the Logger interface.
+type DefaultLogger struct {
+ *log.Logger
+ debug bool
+}
+
+func (l *DefaultLogger) EnableTimestamps() {
+ l.SetFlags(l.Flags() | log.Ldate | log.Ltime)
+}
+
+func (l *DefaultLogger) EnableDebug() {
+ l.debug = true
+}
+
+func (l *DefaultLogger) Debug(v ...interface{}) {
+ if l.debug {
+ l.Output(calldepth, header("DEBUG", fmt.Sprint(v...)))
+ }
+}
+
+func (l *DefaultLogger) Debugf(format string, v ...interface{}) {
+ if l.debug {
+ l.Output(calldepth, header("DEBUG", fmt.Sprintf(format, v...)))
+ }
+}
+
+func (l *DefaultLogger) Info(v ...interface{}) {
+ l.Output(calldepth, header("INFO", fmt.Sprint(v...)))
+}
+
+func (l *DefaultLogger) Infof(format string, v ...interface{}) {
+ l.Output(calldepth, header("INFO", fmt.Sprintf(format, v...)))
+}
+
+func (l *DefaultLogger) Error(v ...interface{}) {
+ l.Output(calldepth, header("ERROR", fmt.Sprint(v...)))
+}
+
+func (l *DefaultLogger) Errorf(format string, v ...interface{}) {
+ l.Output(calldepth, header("ERROR", fmt.Sprintf(format, v...)))
+}
+
+func (l *DefaultLogger) Warning(v ...interface{}) {
+ l.Output(calldepth, header("WARN", fmt.Sprint(v...)))
+}
+
+func (l *DefaultLogger) Warningf(format string, v ...interface{}) {
+ l.Output(calldepth, header("WARN", fmt.Sprintf(format, v...)))
+}
+
+func (l *DefaultLogger) Fatal(v ...interface{}) {
+ l.Output(calldepth, header("FATAL", fmt.Sprint(v...)))
+ os.Exit(1)
+}
+
+func (l *DefaultLogger) Fatalf(format string, v ...interface{}) {
+ l.Output(calldepth, header("FATAL", fmt.Sprintf(format, v...)))
+ os.Exit(1)
+}
+
+func (l *DefaultLogger) Panic(v ...interface{}) {
+ l.Logger.Panic(v)
+}
+
+func (l *DefaultLogger) Panicf(format string, v ...interface{}) {
+ l.Logger.Panicf(format, v...)
+}
+
+func header(lvl, msg string) string {
+ return fmt.Sprintf("%s: %s", lvl, msg)
+}
diff --git a/vendor/github.com/coreos/etcd/raft/node.go b/vendor/github.com/coreos/etcd/raft/node.go
new file mode 100644
index 00000000..33a9db84
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/node.go
@@ -0,0 +1,539 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "context"
+ "errors"
+
+ pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+type SnapshotStatus int
+
+const (
+ SnapshotFinish SnapshotStatus = 1
+ SnapshotFailure SnapshotStatus = 2
+)
+
+var (
+ emptyState = pb.HardState{}
+
+ // ErrStopped is returned by methods on Nodes that have been stopped.
+ ErrStopped = errors.New("raft: stopped")
+)
+
+// SoftState provides state that is useful for logging and debugging.
+// The state is volatile and does not need to be persisted to the WAL.
+type SoftState struct {
+ Lead uint64 // must use atomic operations to access; keep 64-bit aligned.
+ RaftState StateType
+}
+
+func (a *SoftState) equal(b *SoftState) bool {
+ return a.Lead == b.Lead && a.RaftState == b.RaftState
+}
+
+// Ready encapsulates the entries and messages that are ready to read,
+// be saved to stable storage, committed or sent to other peers.
+// All fields in Ready are read-only.
+type Ready struct {
+ // The current volatile state of a Node.
+ // SoftState will be nil if there is no update.
+ // It is not required to consume or store SoftState.
+ *SoftState
+
+ // The current state of a Node to be saved to stable storage BEFORE
+ // Messages are sent.
+ // HardState will be equal to empty state if there is no update.
+ pb.HardState
+
+ // ReadStates can be used for node to serve linearizable read requests locally
+ // when its applied index is greater than the index in ReadState.
+ // Note that the readState will be returned when raft receives msgReadIndex.
+ // The returned is only valid for the request that requested to read.
+ ReadStates []ReadState
+
+ // Entries specifies entries to be saved to stable storage BEFORE
+ // Messages are sent.
+ Entries []pb.Entry
+
+ // Snapshot specifies the snapshot to be saved to stable storage.
+ Snapshot pb.Snapshot
+
+ // CommittedEntries specifies entries to be committed to a
+ // store/state-machine. These have previously been committed to stable
+ // store.
+ CommittedEntries []pb.Entry
+
+ // Messages specifies outbound messages to be sent AFTER Entries are
+ // committed to stable storage.
+ // If it contains a MsgSnap message, the application MUST report back to raft
+ // when the snapshot has been received or has failed by calling ReportSnapshot.
+ Messages []pb.Message
+
+ // MustSync indicates whether the HardState and Entries must be synchronously
+ // written to disk or if an asynchronous write is permissible.
+ MustSync bool
+}
+
+func isHardStateEqual(a, b pb.HardState) bool {
+ return a.Term == b.Term && a.Vote == b.Vote && a.Commit == b.Commit
+}
+
+// IsEmptyHardState returns true if the given HardState is empty.
+func IsEmptyHardState(st pb.HardState) bool {
+ return isHardStateEqual(st, emptyState)
+}
+
+// IsEmptySnap returns true if the given Snapshot is empty.
+func IsEmptySnap(sp pb.Snapshot) bool {
+ return sp.Metadata.Index == 0
+}
+
+func (rd Ready) containsUpdates() bool {
+ return rd.SoftState != nil || !IsEmptyHardState(rd.HardState) ||
+ !IsEmptySnap(rd.Snapshot) || len(rd.Entries) > 0 ||
+ len(rd.CommittedEntries) > 0 || len(rd.Messages) > 0 || len(rd.ReadStates) != 0
+}
+
+// Node represents a node in a raft cluster.
+type Node interface {
+ // Tick increments the internal logical clock for the Node by a single tick. Election
+ // timeouts and heartbeat timeouts are in units of ticks.
+ Tick()
+ // Campaign causes the Node to transition to candidate state and start campaigning to become leader.
+ Campaign(ctx context.Context) error
+ // Propose proposes that data be appended to the log.
+ Propose(ctx context.Context, data []byte) error
+ // ProposeConfChange proposes config change.
+ // At most one ConfChange can be in the process of going through consensus.
+ // Application needs to call ApplyConfChange when applying EntryConfChange type entry.
+ ProposeConfChange(ctx context.Context, cc pb.ConfChange) error
+ // Step advances the state machine using the given message. ctx.Err() will be returned, if any.
+ Step(ctx context.Context, msg pb.Message) error
+
+ // Ready returns a channel that returns the current point-in-time state.
+ // Users of the Node must call Advance after retrieving the state returned by Ready.
+ //
+ // NOTE: No committed entries from the next Ready may be applied until all committed entries
+ // and snapshots from the previous one have finished.
+ Ready() <-chan Ready
+
+ // Advance notifies the Node that the application has saved progress up to the last Ready.
+ // It prepares the node to return the next available Ready.
+ //
+ // The application should generally call Advance after it applies the entries in last Ready.
+ //
+ // However, as an optimization, the application may call Advance while it is applying the
+ // commands. For example. when the last Ready contains a snapshot, the application might take
+ // a long time to apply the snapshot data. To continue receiving Ready without blocking raft
+ // progress, it can call Advance before finishing applying the last ready.
+ Advance()
+ // ApplyConfChange applies config change to the local node.
+ // Returns an opaque ConfState protobuf which must be recorded
+ // in snapshots. Will never return nil; it returns a pointer only
+ // to match MemoryStorage.Compact.
+ ApplyConfChange(cc pb.ConfChange) *pb.ConfState
+
+ // TransferLeadership attempts to transfer leadership to the given transferee.
+ TransferLeadership(ctx context.Context, lead, transferee uint64)
+
+ // ReadIndex request a read state. The read state will be set in the ready.
+ // Read state has a read index. Once the application advances further than the read
+ // index, any linearizable read requests issued before the read request can be
+ // processed safely. The read state will have the same rctx attached.
+ ReadIndex(ctx context.Context, rctx []byte) error
+
+ // Status returns the current status of the raft state machine.
+ Status() Status
+ // ReportUnreachable reports the given node is not reachable for the last send.
+ ReportUnreachable(id uint64)
+ // ReportSnapshot reports the status of the sent snapshot.
+ ReportSnapshot(id uint64, status SnapshotStatus)
+ // Stop performs any necessary termination of the Node.
+ Stop()
+}
+
+type Peer struct {
+ ID uint64
+ Context []byte
+}
+
+// StartNode returns a new Node given configuration and a list of raft peers.
+// It appends a ConfChangeAddNode entry for each given peer to the initial log.
+func StartNode(c *Config, peers []Peer) Node {
+ r := newRaft(c)
+ // become the follower at term 1 and apply initial configuration
+ // entries of term 1
+ r.becomeFollower(1, None)
+ for _, peer := range peers {
+ cc := pb.ConfChange{Type: pb.ConfChangeAddNode, NodeID: peer.ID, Context: peer.Context}
+ d, err := cc.Marshal()
+ if err != nil {
+ panic("unexpected marshal error")
+ }
+ e := pb.Entry{Type: pb.EntryConfChange, Term: 1, Index: r.raftLog.lastIndex() + 1, Data: d}
+ r.raftLog.append(e)
+ }
+ // Mark these initial entries as committed.
+ // TODO(bdarnell): These entries are still unstable; do we need to preserve
+ // the invariant that committed < unstable?
+ r.raftLog.committed = r.raftLog.lastIndex()
+ // Now apply them, mainly so that the application can call Campaign
+ // immediately after StartNode in tests. Note that these nodes will
+ // be added to raft twice: here and when the application's Ready
+ // loop calls ApplyConfChange. The calls to addNode must come after
+ // all calls to raftLog.append so progress.next is set after these
+ // bootstrapping entries (it is an error if we try to append these
+ // entries since they have already been committed).
+ // We do not set raftLog.applied so the application will be able
+ // to observe all conf changes via Ready.CommittedEntries.
+ for _, peer := range peers {
+ r.addNode(peer.ID)
+ }
+
+ n := newNode()
+ n.logger = c.Logger
+ go n.run(r)
+ return &n
+}
+
+// RestartNode is similar to StartNode but does not take a list of peers.
+// The current membership of the cluster will be restored from the Storage.
+// If the caller has an existing state machine, pass in the last log index that
+// has been applied to it; otherwise use zero.
+func RestartNode(c *Config) Node {
+ r := newRaft(c)
+
+ n := newNode()
+ n.logger = c.Logger
+ go n.run(r)
+ return &n
+}
+
+// node is the canonical implementation of the Node interface
+type node struct {
+ propc chan pb.Message
+ recvc chan pb.Message
+ confc chan pb.ConfChange
+ confstatec chan pb.ConfState
+ readyc chan Ready
+ advancec chan struct{}
+ tickc chan struct{}
+ done chan struct{}
+ stop chan struct{}
+ status chan chan Status
+
+ logger Logger
+}
+
+func newNode() node {
+ return node{
+ propc: make(chan pb.Message),
+ recvc: make(chan pb.Message),
+ confc: make(chan pb.ConfChange),
+ confstatec: make(chan pb.ConfState),
+ readyc: make(chan Ready),
+ advancec: make(chan struct{}),
+ // make tickc a buffered chan, so raft node can buffer some ticks when the node
+ // is busy processing raft messages. Raft node will resume process buffered
+ // ticks when it becomes idle.
+ tickc: make(chan struct{}, 128),
+ done: make(chan struct{}),
+ stop: make(chan struct{}),
+ status: make(chan chan Status),
+ }
+}
+
+func (n *node) Stop() {
+ select {
+ case n.stop <- struct{}{}:
+ // Not already stopped, so trigger it
+ case <-n.done:
+ // Node has already been stopped - no need to do anything
+ return
+ }
+ // Block until the stop has been acknowledged by run()
+ <-n.done
+}
+
+func (n *node) run(r *raft) {
+ var propc chan pb.Message
+ var readyc chan Ready
+ var advancec chan struct{}
+ var prevLastUnstablei, prevLastUnstablet uint64
+ var havePrevLastUnstablei bool
+ var prevSnapi uint64
+ var rd Ready
+
+ lead := None
+ prevSoftSt := r.softState()
+ prevHardSt := emptyState
+
+ for {
+ if advancec != nil {
+ readyc = nil
+ } else {
+ rd = newReady(r, prevSoftSt, prevHardSt)
+ if rd.containsUpdates() {
+ readyc = n.readyc
+ } else {
+ readyc = nil
+ }
+ }
+
+ if lead != r.lead {
+ if r.hasLeader() {
+ if lead == None {
+ r.logger.Infof("raft.node: %x elected leader %x at term %d", r.id, r.lead, r.Term)
+ } else {
+ r.logger.Infof("raft.node: %x changed leader from %x to %x at term %d", r.id, lead, r.lead, r.Term)
+ }
+ propc = n.propc
+ } else {
+ r.logger.Infof("raft.node: %x lost leader %x at term %d", r.id, lead, r.Term)
+ propc = nil
+ }
+ lead = r.lead
+ }
+
+ select {
+ // TODO: maybe buffer the config propose if there exists one (the way
+ // described in raft dissertation)
+ // Currently it is dropped in Step silently.
+ case m := <-propc:
+ m.From = r.id
+ r.Step(m)
+ case m := <-n.recvc:
+ // filter out response message from unknown From.
+ if pr := r.getProgress(m.From); pr != nil || !IsResponseMsg(m.Type) {
+ r.Step(m) // raft never returns an error
+ }
+ case cc := <-n.confc:
+ if cc.NodeID == None {
+ r.resetPendingConf()
+ select {
+ case n.confstatec <- pb.ConfState{Nodes: r.nodes()}:
+ case <-n.done:
+ }
+ break
+ }
+ switch cc.Type {
+ case pb.ConfChangeAddNode:
+ r.addNode(cc.NodeID)
+ case pb.ConfChangeAddLearnerNode:
+ r.addLearner(cc.NodeID)
+ case pb.ConfChangeRemoveNode:
+ // block incoming proposal when local node is
+ // removed
+ if cc.NodeID == r.id {
+ propc = nil
+ }
+ r.removeNode(cc.NodeID)
+ case pb.ConfChangeUpdateNode:
+ r.resetPendingConf()
+ default:
+ panic("unexpected conf type")
+ }
+ select {
+ case n.confstatec <- pb.ConfState{Nodes: r.nodes()}:
+ case <-n.done:
+ }
+ case <-n.tickc:
+ r.tick()
+ case readyc <- rd:
+ if rd.SoftState != nil {
+ prevSoftSt = rd.SoftState
+ }
+ if len(rd.Entries) > 0 {
+ prevLastUnstablei = rd.Entries[len(rd.Entries)-1].Index
+ prevLastUnstablet = rd.Entries[len(rd.Entries)-1].Term
+ havePrevLastUnstablei = true
+ }
+ if !IsEmptyHardState(rd.HardState) {
+ prevHardSt = rd.HardState
+ }
+ if !IsEmptySnap(rd.Snapshot) {
+ prevSnapi = rd.Snapshot.Metadata.Index
+ }
+
+ r.msgs = nil
+ r.readStates = nil
+ advancec = n.advancec
+ case <-advancec:
+ if prevHardSt.Commit != 0 {
+ r.raftLog.appliedTo(prevHardSt.Commit)
+ }
+ if havePrevLastUnstablei {
+ r.raftLog.stableTo(prevLastUnstablei, prevLastUnstablet)
+ havePrevLastUnstablei = false
+ }
+ r.raftLog.stableSnapTo(prevSnapi)
+ advancec = nil
+ case c := <-n.status:
+ c <- getStatus(r)
+ case <-n.stop:
+ close(n.done)
+ return
+ }
+ }
+}
+
+// Tick increments the internal logical clock for this Node. Election timeouts
+// and heartbeat timeouts are in units of ticks.
+func (n *node) Tick() {
+ select {
+ case n.tickc <- struct{}{}:
+ case <-n.done:
+ default:
+ n.logger.Warningf("A tick missed to fire. Node blocks too long!")
+ }
+}
+
+func (n *node) Campaign(ctx context.Context) error { return n.step(ctx, pb.Message{Type: pb.MsgHup}) }
+
+func (n *node) Propose(ctx context.Context, data []byte) error {
+ return n.step(ctx, pb.Message{Type: pb.MsgProp, Entries: []pb.Entry{{Data: data}}})
+}
+
+func (n *node) Step(ctx context.Context, m pb.Message) error {
+ // ignore unexpected local messages receiving over network
+ if IsLocalMsg(m.Type) {
+ // TODO: return an error?
+ return nil
+ }
+ return n.step(ctx, m)
+}
+
+func (n *node) ProposeConfChange(ctx context.Context, cc pb.ConfChange) error {
+ data, err := cc.Marshal()
+ if err != nil {
+ return err
+ }
+ return n.Step(ctx, pb.Message{Type: pb.MsgProp, Entries: []pb.Entry{{Type: pb.EntryConfChange, Data: data}}})
+}
+
+// Step advances the state machine using msgs. The ctx.Err() will be returned,
+// if any.
+func (n *node) step(ctx context.Context, m pb.Message) error {
+ ch := n.recvc
+ if m.Type == pb.MsgProp {
+ ch = n.propc
+ }
+
+ select {
+ case ch <- m:
+ return nil
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-n.done:
+ return ErrStopped
+ }
+}
+
+func (n *node) Ready() <-chan Ready { return n.readyc }
+
+func (n *node) Advance() {
+ select {
+ case n.advancec <- struct{}{}:
+ case <-n.done:
+ }
+}
+
+func (n *node) ApplyConfChange(cc pb.ConfChange) *pb.ConfState {
+ var cs pb.ConfState
+ select {
+ case n.confc <- cc:
+ case <-n.done:
+ }
+ select {
+ case cs = <-n.confstatec:
+ case <-n.done:
+ }
+ return &cs
+}
+
+func (n *node) Status() Status {
+ c := make(chan Status)
+ select {
+ case n.status <- c:
+ return <-c
+ case <-n.done:
+ return Status{}
+ }
+}
+
+func (n *node) ReportUnreachable(id uint64) {
+ select {
+ case n.recvc <- pb.Message{Type: pb.MsgUnreachable, From: id}:
+ case <-n.done:
+ }
+}
+
+func (n *node) ReportSnapshot(id uint64, status SnapshotStatus) {
+ rej := status == SnapshotFailure
+
+ select {
+ case n.recvc <- pb.Message{Type: pb.MsgSnapStatus, From: id, Reject: rej}:
+ case <-n.done:
+ }
+}
+
+func (n *node) TransferLeadership(ctx context.Context, lead, transferee uint64) {
+ select {
+ // manually set 'from' and 'to', so that leader can voluntarily transfers its leadership
+ case n.recvc <- pb.Message{Type: pb.MsgTransferLeader, From: transferee, To: lead}:
+ case <-n.done:
+ case <-ctx.Done():
+ }
+}
+
+func (n *node) ReadIndex(ctx context.Context, rctx []byte) error {
+ return n.step(ctx, pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}})
+}
+
+func newReady(r *raft, prevSoftSt *SoftState, prevHardSt pb.HardState) Ready {
+ rd := Ready{
+ Entries: r.raftLog.unstableEntries(),
+ CommittedEntries: r.raftLog.nextEnts(),
+ Messages: r.msgs,
+ }
+ if softSt := r.softState(); !softSt.equal(prevSoftSt) {
+ rd.SoftState = softSt
+ }
+ if hardSt := r.hardState(); !isHardStateEqual(hardSt, prevHardSt) {
+ rd.HardState = hardSt
+ }
+ if r.raftLog.unstable.snapshot != nil {
+ rd.Snapshot = *r.raftLog.unstable.snapshot
+ }
+ if len(r.readStates) != 0 {
+ rd.ReadStates = r.readStates
+ }
+ rd.MustSync = MustSync(rd.HardState, prevHardSt, len(rd.Entries))
+ return rd
+}
+
+// MustSync returns true if the hard state and count of Raft entries indicate
+// that a synchronous write to persistent storage is required.
+func MustSync(st, prevst pb.HardState, entsnum int) bool {
+ // Persistent state on all servers:
+ // (Updated on stable storage before responding to RPCs)
+ // currentTerm
+ // votedFor
+ // log entries[]
+ return entsnum != 0 || st.Vote != prevst.Vote || st.Term != prevst.Term
+}
diff --git a/vendor/github.com/coreos/etcd/raft/progress.go b/vendor/github.com/coreos/etcd/raft/progress.go
new file mode 100644
index 00000000..ef3787db
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/progress.go
@@ -0,0 +1,284 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import "fmt"
+
+const (
+ ProgressStateProbe ProgressStateType = iota
+ ProgressStateReplicate
+ ProgressStateSnapshot
+)
+
+type ProgressStateType uint64
+
+var prstmap = [...]string{
+ "ProgressStateProbe",
+ "ProgressStateReplicate",
+ "ProgressStateSnapshot",
+}
+
+func (st ProgressStateType) String() string { return prstmap[uint64(st)] }
+
+// Progress represents a follower’s progress in the view of the leader. Leader maintains
+// progresses of all followers, and sends entries to the follower based on its progress.
+type Progress struct {
+ Match, Next uint64
+ // State defines how the leader should interact with the follower.
+ //
+ // When in ProgressStateProbe, leader sends at most one replication message
+ // per heartbeat interval. It also probes actual progress of the follower.
+ //
+ // When in ProgressStateReplicate, leader optimistically increases next
+ // to the latest entry sent after sending replication message. This is
+ // an optimized state for fast replicating log entries to the follower.
+ //
+ // When in ProgressStateSnapshot, leader should have sent out snapshot
+ // before and stops sending any replication message.
+ State ProgressStateType
+
+ // Paused is used in ProgressStateProbe.
+ // When Paused is true, raft should pause sending replication message to this peer.
+ Paused bool
+ // PendingSnapshot is used in ProgressStateSnapshot.
+ // If there is a pending snapshot, the pendingSnapshot will be set to the
+ // index of the snapshot. If pendingSnapshot is set, the replication process of
+ // this Progress will be paused. raft will not resend snapshot until the pending one
+ // is reported to be failed.
+ PendingSnapshot uint64
+
+ // RecentActive is true if the progress is recently active. Receiving any messages
+ // from the corresponding follower indicates the progress is active.
+ // RecentActive can be reset to false after an election timeout.
+ RecentActive bool
+
+ // inflights is a sliding window for the inflight messages.
+ // Each inflight message contains one or more log entries.
+ // The max number of entries per message is defined in raft config as MaxSizePerMsg.
+ // Thus inflight effectively limits both the number of inflight messages
+ // and the bandwidth each Progress can use.
+ // When inflights is full, no more message should be sent.
+ // When a leader sends out a message, the index of the last
+ // entry should be added to inflights. The index MUST be added
+ // into inflights in order.
+ // When a leader receives a reply, the previous inflights should
+ // be freed by calling inflights.freeTo with the index of the last
+ // received entry.
+ ins *inflights
+
+ // IsLearner is true if this progress is tracked for a learner.
+ IsLearner bool
+}
+
+func (pr *Progress) resetState(state ProgressStateType) {
+ pr.Paused = false
+ pr.PendingSnapshot = 0
+ pr.State = state
+ pr.ins.reset()
+}
+
+func (pr *Progress) becomeProbe() {
+ // If the original state is ProgressStateSnapshot, progress knows that
+ // the pending snapshot has been sent to this peer successfully, then
+ // probes from pendingSnapshot + 1.
+ if pr.State == ProgressStateSnapshot {
+ pendingSnapshot := pr.PendingSnapshot
+ pr.resetState(ProgressStateProbe)
+ pr.Next = max(pr.Match+1, pendingSnapshot+1)
+ } else {
+ pr.resetState(ProgressStateProbe)
+ pr.Next = pr.Match + 1
+ }
+}
+
+func (pr *Progress) becomeReplicate() {
+ pr.resetState(ProgressStateReplicate)
+ pr.Next = pr.Match + 1
+}
+
+func (pr *Progress) becomeSnapshot(snapshoti uint64) {
+ pr.resetState(ProgressStateSnapshot)
+ pr.PendingSnapshot = snapshoti
+}
+
+// maybeUpdate returns false if the given n index comes from an outdated message.
+// Otherwise it updates the progress and returns true.
+func (pr *Progress) maybeUpdate(n uint64) bool {
+ var updated bool
+ if pr.Match < n {
+ pr.Match = n
+ updated = true
+ pr.resume()
+ }
+ if pr.Next < n+1 {
+ pr.Next = n + 1
+ }
+ return updated
+}
+
+func (pr *Progress) optimisticUpdate(n uint64) { pr.Next = n + 1 }
+
+// maybeDecrTo returns false if the given to index comes from an out of order message.
+// Otherwise it decreases the progress next index to min(rejected, last) and returns true.
+func (pr *Progress) maybeDecrTo(rejected, last uint64) bool {
+ if pr.State == ProgressStateReplicate {
+ // the rejection must be stale if the progress has matched and "rejected"
+ // is smaller than "match".
+ if rejected <= pr.Match {
+ return false
+ }
+ // directly decrease next to match + 1
+ pr.Next = pr.Match + 1
+ return true
+ }
+
+ // the rejection must be stale if "rejected" does not match next - 1
+ if pr.Next-1 != rejected {
+ return false
+ }
+
+ if pr.Next = min(rejected, last+1); pr.Next < 1 {
+ pr.Next = 1
+ }
+ pr.resume()
+ return true
+}
+
+func (pr *Progress) pause() { pr.Paused = true }
+func (pr *Progress) resume() { pr.Paused = false }
+
+// IsPaused returns whether sending log entries to this node has been
+// paused. A node may be paused because it has rejected recent
+// MsgApps, is currently waiting for a snapshot, or has reached the
+// MaxInflightMsgs limit.
+func (pr *Progress) IsPaused() bool {
+ switch pr.State {
+ case ProgressStateProbe:
+ return pr.Paused
+ case ProgressStateReplicate:
+ return pr.ins.full()
+ case ProgressStateSnapshot:
+ return true
+ default:
+ panic("unexpected state")
+ }
+}
+
+func (pr *Progress) snapshotFailure() { pr.PendingSnapshot = 0 }
+
+// needSnapshotAbort returns true if snapshot progress's Match
+// is equal or higher than the pendingSnapshot.
+func (pr *Progress) needSnapshotAbort() bool {
+ return pr.State == ProgressStateSnapshot && pr.Match >= pr.PendingSnapshot
+}
+
+func (pr *Progress) String() string {
+ return fmt.Sprintf("next = %d, match = %d, state = %s, waiting = %v, pendingSnapshot = %d", pr.Next, pr.Match, pr.State, pr.IsPaused(), pr.PendingSnapshot)
+}
+
+type inflights struct {
+ // the starting index in the buffer
+ start int
+ // number of inflights in the buffer
+ count int
+
+ // the size of the buffer
+ size int
+
+ // buffer contains the index of the last entry
+ // inside one message.
+ buffer []uint64
+}
+
+func newInflights(size int) *inflights {
+ return &inflights{
+ size: size,
+ }
+}
+
+// add adds an inflight into inflights
+func (in *inflights) add(inflight uint64) {
+ if in.full() {
+ panic("cannot add into a full inflights")
+ }
+ next := in.start + in.count
+ size := in.size
+ if next >= size {
+ next -= size
+ }
+ if next >= len(in.buffer) {
+ in.growBuf()
+ }
+ in.buffer[next] = inflight
+ in.count++
+}
+
+// grow the inflight buffer by doubling up to inflights.size. We grow on demand
+// instead of preallocating to inflights.size to handle systems which have
+// thousands of Raft groups per process.
+func (in *inflights) growBuf() {
+ newSize := len(in.buffer) * 2
+ if newSize == 0 {
+ newSize = 1
+ } else if newSize > in.size {
+ newSize = in.size
+ }
+ newBuffer := make([]uint64, newSize)
+ copy(newBuffer, in.buffer)
+ in.buffer = newBuffer
+}
+
+// freeTo frees the inflights smaller or equal to the given `to` flight.
+func (in *inflights) freeTo(to uint64) {
+ if in.count == 0 || to < in.buffer[in.start] {
+ // out of the left side of the window
+ return
+ }
+
+ idx := in.start
+ var i int
+ for i = 0; i < in.count; i++ {
+ if to < in.buffer[idx] { // found the first large inflight
+ break
+ }
+
+ // increase index and maybe rotate
+ size := in.size
+ if idx++; idx >= size {
+ idx -= size
+ }
+ }
+ // free i inflights and set new start index
+ in.count -= i
+ in.start = idx
+ if in.count == 0 {
+ // inflights is empty, reset the start index so that we don't grow the
+ // buffer unnecessarily.
+ in.start = 0
+ }
+}
+
+func (in *inflights) freeFirstOne() { in.freeTo(in.buffer[in.start]) }
+
+// full returns true if the inflights is full.
+func (in *inflights) full() bool {
+ return in.count == in.size
+}
+
+// resets frees all inflights.
+func (in *inflights) reset() {
+ in.count = 0
+ in.start = 0
+}
diff --git a/vendor/github.com/coreos/etcd/raft/raft.go b/vendor/github.com/coreos/etcd/raft/raft.go
new file mode 100644
index 00000000..b4c0f024
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/raft.go
@@ -0,0 +1,1406 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "math"
+ "math/rand"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+// None is a placeholder node ID used when there is no leader.
+const None uint64 = 0
+const noLimit = math.MaxUint64
+
+// Possible values for StateType.
+const (
+ StateFollower StateType = iota
+ StateCandidate
+ StateLeader
+ StatePreCandidate
+ numStates
+)
+
+type ReadOnlyOption int
+
+const (
+ // ReadOnlySafe guarantees the linearizability of the read only request by
+ // communicating with the quorum. It is the default and suggested option.
+ ReadOnlySafe ReadOnlyOption = iota
+ // ReadOnlyLeaseBased ensures linearizability of the read only request by
+ // relying on the leader lease. It can be affected by clock drift.
+ // If the clock drift is unbounded, leader might keep the lease longer than it
+ // should (clock can move backward/pause without any bound). ReadIndex is not safe
+ // in that case.
+ ReadOnlyLeaseBased
+)
+
+// Possible values for CampaignType
+const (
+ // campaignPreElection represents the first phase of a normal election when
+ // Config.PreVote is true.
+ campaignPreElection CampaignType = "CampaignPreElection"
+ // campaignElection represents a normal (time-based) election (the second phase
+ // of the election when Config.PreVote is true).
+ campaignElection CampaignType = "CampaignElection"
+ // campaignTransfer represents the type of leader transfer
+ campaignTransfer CampaignType = "CampaignTransfer"
+)
+
+// lockedRand is a small wrapper around rand.Rand to provide
+// synchronization. Only the methods needed by the code are exposed
+// (e.g. Intn).
+type lockedRand struct {
+ mu sync.Mutex
+ rand *rand.Rand
+}
+
+func (r *lockedRand) Intn(n int) int {
+ r.mu.Lock()
+ v := r.rand.Intn(n)
+ r.mu.Unlock()
+ return v
+}
+
+var globalRand = &lockedRand{
+ rand: rand.New(rand.NewSource(time.Now().UnixNano())),
+}
+
+// CampaignType represents the type of campaigning
+// the reason we use the type of string instead of uint64
+// is because it's simpler to compare and fill in raft entries
+type CampaignType string
+
+// StateType represents the role of a node in a cluster.
+type StateType uint64
+
+var stmap = [...]string{
+ "StateFollower",
+ "StateCandidate",
+ "StateLeader",
+ "StatePreCandidate",
+}
+
+func (st StateType) String() string {
+ return stmap[uint64(st)]
+}
+
+// Config contains the parameters to start a raft.
+type Config struct {
+ // ID is the identity of the local raft. ID cannot be 0.
+ ID uint64
+
+ // peers contains the IDs of all nodes (including self) in the raft cluster. It
+ // should only be set when starting a new raft cluster. Restarting raft from
+ // previous configuration will panic if peers is set. peer is private and only
+ // used for testing right now.
+ peers []uint64
+
+ // learners contains the IDs of all leaner nodes (including self if the local node is a leaner) in the raft cluster.
+ // learners only receives entries from the leader node. It does not vote or promote itself.
+ learners []uint64
+
+ // ElectionTick is the number of Node.Tick invocations that must pass between
+ // elections. That is, if a follower does not receive any message from the
+ // leader of current term before ElectionTick has elapsed, it will become
+ // candidate and start an election. ElectionTick must be greater than
+ // HeartbeatTick. We suggest ElectionTick = 10 * HeartbeatTick to avoid
+ // unnecessary leader switching.
+ ElectionTick int
+ // HeartbeatTick is the number of Node.Tick invocations that must pass between
+ // heartbeats. That is, a leader sends heartbeat messages to maintain its
+ // leadership every HeartbeatTick ticks.
+ HeartbeatTick int
+
+ // Storage is the storage for raft. raft generates entries and states to be
+ // stored in storage. raft reads the persisted entries and states out of
+ // Storage when it needs. raft reads out the previous state and configuration
+ // out of storage when restarting.
+ Storage Storage
+ // Applied is the last applied index. It should only be set when restarting
+ // raft. raft will not return entries to the application smaller or equal to
+ // Applied. If Applied is unset when restarting, raft might return previous
+ // applied entries. This is a very application dependent configuration.
+ Applied uint64
+
+ // MaxSizePerMsg limits the max size of each append message. Smaller value
+ // lowers the raft recovery cost(initial probing and message lost during normal
+ // operation). On the other side, it might affect the throughput during normal
+ // replication. Note: math.MaxUint64 for unlimited, 0 for at most one entry per
+ // message.
+ MaxSizePerMsg uint64
+ // MaxInflightMsgs limits the max number of in-flight append messages during
+ // optimistic replication phase. The application transportation layer usually
+ // has its own sending buffer over TCP/UDP. Setting MaxInflightMsgs to avoid
+ // overflowing that sending buffer. TODO (xiangli): feedback to application to
+ // limit the proposal rate?
+ MaxInflightMsgs int
+
+ // CheckQuorum specifies if the leader should check quorum activity. Leader
+ // steps down when quorum is not active for an electionTimeout.
+ CheckQuorum bool
+
+ // PreVote enables the Pre-Vote algorithm described in raft thesis section
+ // 9.6. This prevents disruption when a node that has been partitioned away
+ // rejoins the cluster.
+ PreVote bool
+
+ // ReadOnlyOption specifies how the read only request is processed.
+ //
+ // ReadOnlySafe guarantees the linearizability of the read only request by
+ // communicating with the quorum. It is the default and suggested option.
+ //
+ // ReadOnlyLeaseBased ensures linearizability of the read only request by
+ // relying on the leader lease. It can be affected by clock drift.
+ // If the clock drift is unbounded, leader might keep the lease longer than it
+ // should (clock can move backward/pause without any bound). ReadIndex is not safe
+ // in that case.
+ // CheckQuorum MUST be enabled if ReadOnlyOption is ReadOnlyLeaseBased.
+ ReadOnlyOption ReadOnlyOption
+
+ // Logger is the logger used for raft log. For multinode which can host
+ // multiple raft group, each raft group can have its own logger
+ Logger Logger
+
+ // DisableProposalForwarding set to true means that followers will drop
+ // proposals, rather than forwarding them to the leader. One use case for
+ // this feature would be in a situation where the Raft leader is used to
+ // compute the data of a proposal, for example, adding a timestamp from a
+ // hybrid logical clock to data in a monotonically increasing way. Forwarding
+ // should be disabled to prevent a follower with an innaccurate hybrid
+ // logical clock from assigning the timestamp and then forwarding the data
+ // to the leader.
+ DisableProposalForwarding bool
+}
+
+func (c *Config) validate() error {
+ if c.ID == None {
+ return errors.New("cannot use none as id")
+ }
+
+ if c.HeartbeatTick <= 0 {
+ return errors.New("heartbeat tick must be greater than 0")
+ }
+
+ if c.ElectionTick <= c.HeartbeatTick {
+ return errors.New("election tick must be greater than heartbeat tick")
+ }
+
+ if c.Storage == nil {
+ return errors.New("storage cannot be nil")
+ }
+
+ if c.MaxInflightMsgs <= 0 {
+ return errors.New("max inflight messages must be greater than 0")
+ }
+
+ if c.Logger == nil {
+ c.Logger = raftLogger
+ }
+
+ if c.ReadOnlyOption == ReadOnlyLeaseBased && !c.CheckQuorum {
+ return errors.New("CheckQuorum must be enabled when ReadOnlyOption is ReadOnlyLeaseBased")
+ }
+
+ return nil
+}
+
+type raft struct {
+ id uint64
+
+ Term uint64
+ Vote uint64
+
+ readStates []ReadState
+
+ // the log
+ raftLog *raftLog
+
+ maxInflight int
+ maxMsgSize uint64
+ prs map[uint64]*Progress
+ learnerPrs map[uint64]*Progress
+
+ state StateType
+
+ // isLearner is true if the local raft node is a learner.
+ isLearner bool
+
+ votes map[uint64]bool
+
+ msgs []pb.Message
+
+ // the leader id
+ lead uint64
+ // leadTransferee is id of the leader transfer target when its value is not zero.
+ // Follow the procedure defined in raft thesis 3.10.
+ leadTransferee uint64
+ // New configuration is ignored if there exists unapplied configuration.
+ pendingConf bool
+
+ readOnly *readOnly
+
+ // number of ticks since it reached last electionTimeout when it is leader
+ // or candidate.
+ // number of ticks since it reached last electionTimeout or received a
+ // valid message from current leader when it is a follower.
+ electionElapsed int
+
+ // number of ticks since it reached last heartbeatTimeout.
+ // only leader keeps heartbeatElapsed.
+ heartbeatElapsed int
+
+ checkQuorum bool
+ preVote bool
+
+ heartbeatTimeout int
+ electionTimeout int
+ // randomizedElectionTimeout is a random number between
+ // [electiontimeout, 2 * electiontimeout - 1]. It gets reset
+ // when raft changes its state to follower or candidate.
+ randomizedElectionTimeout int
+ disableProposalForwarding bool
+
+ tick func()
+ step stepFunc
+
+ logger Logger
+}
+
+func newRaft(c *Config) *raft {
+ if err := c.validate(); err != nil {
+ panic(err.Error())
+ }
+ raftlog := newLog(c.Storage, c.Logger)
+ hs, cs, err := c.Storage.InitialState()
+ if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+ peers := c.peers
+ learners := c.learners
+ if len(cs.Nodes) > 0 || len(cs.Learners) > 0 {
+ if len(peers) > 0 || len(learners) > 0 {
+ // TODO(bdarnell): the peers argument is always nil except in
+ // tests; the argument should be removed and these tests should be
+ // updated to specify their nodes through a snapshot.
+ panic("cannot specify both newRaft(peers, learners) and ConfState.(Nodes, Learners)")
+ }
+ peers = cs.Nodes
+ learners = cs.Learners
+ }
+ r := &raft{
+ id: c.ID,
+ lead: None,
+ isLearner: false,
+ raftLog: raftlog,
+ maxMsgSize: c.MaxSizePerMsg,
+ maxInflight: c.MaxInflightMsgs,
+ prs: make(map[uint64]*Progress),
+ learnerPrs: make(map[uint64]*Progress),
+ electionTimeout: c.ElectionTick,
+ heartbeatTimeout: c.HeartbeatTick,
+ logger: c.Logger,
+ checkQuorum: c.CheckQuorum,
+ preVote: c.PreVote,
+ readOnly: newReadOnly(c.ReadOnlyOption),
+ disableProposalForwarding: c.DisableProposalForwarding,
+ }
+ for _, p := range peers {
+ r.prs[p] = &Progress{Next: 1, ins: newInflights(r.maxInflight)}
+ }
+ for _, p := range learners {
+ if _, ok := r.prs[p]; ok {
+ panic(fmt.Sprintf("node %x is in both learner and peer list", p))
+ }
+ r.learnerPrs[p] = &Progress{Next: 1, ins: newInflights(r.maxInflight), IsLearner: true}
+ if r.id == p {
+ r.isLearner = true
+ }
+ }
+
+ if !isHardStateEqual(hs, emptyState) {
+ r.loadState(hs)
+ }
+ if c.Applied > 0 {
+ raftlog.appliedTo(c.Applied)
+ }
+ r.becomeFollower(r.Term, None)
+
+ var nodesStrs []string
+ for _, n := range r.nodes() {
+ nodesStrs = append(nodesStrs, fmt.Sprintf("%x", n))
+ }
+
+ r.logger.Infof("newRaft %x [peers: [%s], term: %d, commit: %d, applied: %d, lastindex: %d, lastterm: %d]",
+ r.id, strings.Join(nodesStrs, ","), r.Term, r.raftLog.committed, r.raftLog.applied, r.raftLog.lastIndex(), r.raftLog.lastTerm())
+ return r
+}
+
+func (r *raft) hasLeader() bool { return r.lead != None }
+
+func (r *raft) softState() *SoftState { return &SoftState{Lead: r.lead, RaftState: r.state} }
+
+func (r *raft) hardState() pb.HardState {
+ return pb.HardState{
+ Term: r.Term,
+ Vote: r.Vote,
+ Commit: r.raftLog.committed,
+ }
+}
+
+func (r *raft) quorum() int { return len(r.prs)/2 + 1 }
+
+func (r *raft) nodes() []uint64 {
+ nodes := make([]uint64, 0, len(r.prs)+len(r.learnerPrs))
+ for id := range r.prs {
+ nodes = append(nodes, id)
+ }
+ for id := range r.learnerPrs {
+ nodes = append(nodes, id)
+ }
+ sort.Sort(uint64Slice(nodes))
+ return nodes
+}
+
+// send persists state to stable storage and then sends to its mailbox.
+func (r *raft) send(m pb.Message) {
+ m.From = r.id
+ if m.Type == pb.MsgVote || m.Type == pb.MsgVoteResp || m.Type == pb.MsgPreVote || m.Type == pb.MsgPreVoteResp {
+ if m.Term == 0 {
+ // All {pre-,}campaign messages need to have the term set when
+ // sending.
+ // - MsgVote: m.Term is the term the node is campaigning for,
+ // non-zero as we increment the term when campaigning.
+ // - MsgVoteResp: m.Term is the new r.Term if the MsgVote was
+ // granted, non-zero for the same reason MsgVote is
+ // - MsgPreVote: m.Term is the term the node will campaign,
+ // non-zero as we use m.Term to indicate the next term we'll be
+ // campaigning for
+ // - MsgPreVoteResp: m.Term is the term received in the original
+ // MsgPreVote if the pre-vote was granted, non-zero for the
+ // same reasons MsgPreVote is
+ panic(fmt.Sprintf("term should be set when sending %s", m.Type))
+ }
+ } else {
+ if m.Term != 0 {
+ panic(fmt.Sprintf("term should not be set when sending %s (was %d)", m.Type, m.Term))
+ }
+ // do not attach term to MsgProp, MsgReadIndex
+ // proposals are a way to forward to the leader and
+ // should be treated as local message.
+ // MsgReadIndex is also forwarded to leader.
+ if m.Type != pb.MsgProp && m.Type != pb.MsgReadIndex {
+ m.Term = r.Term
+ }
+ }
+ r.msgs = append(r.msgs, m)
+}
+
+func (r *raft) getProgress(id uint64) *Progress {
+ if pr, ok := r.prs[id]; ok {
+ return pr
+ }
+
+ return r.learnerPrs[id]
+}
+
+// sendAppend sends RPC, with entries to the given peer.
+func (r *raft) sendAppend(to uint64) {
+ pr := r.getProgress(to)
+ if pr.IsPaused() {
+ return
+ }
+ m := pb.Message{}
+ m.To = to
+
+ term, errt := r.raftLog.term(pr.Next - 1)
+ ents, erre := r.raftLog.entries(pr.Next, r.maxMsgSize)
+
+ if errt != nil || erre != nil { // send snapshot if we failed to get term or entries
+ if !pr.RecentActive {
+ r.logger.Debugf("ignore sending snapshot to %x since it is not recently active", to)
+ return
+ }
+
+ m.Type = pb.MsgSnap
+ snapshot, err := r.raftLog.snapshot()
+ if err != nil {
+ if err == ErrSnapshotTemporarilyUnavailable {
+ r.logger.Debugf("%x failed to send snapshot to %x because snapshot is temporarily unavailable", r.id, to)
+ return
+ }
+ panic(err) // TODO(bdarnell)
+ }
+ if IsEmptySnap(snapshot) {
+ panic("need non-empty snapshot")
+ }
+ m.Snapshot = snapshot
+ sindex, sterm := snapshot.Metadata.Index, snapshot.Metadata.Term
+ r.logger.Debugf("%x [firstindex: %d, commit: %d] sent snapshot[index: %d, term: %d] to %x [%s]",
+ r.id, r.raftLog.firstIndex(), r.raftLog.committed, sindex, sterm, to, pr)
+ pr.becomeSnapshot(sindex)
+ r.logger.Debugf("%x paused sending replication messages to %x [%s]", r.id, to, pr)
+ } else {
+ m.Type = pb.MsgApp
+ m.Index = pr.Next - 1
+ m.LogTerm = term
+ m.Entries = ents
+ m.Commit = r.raftLog.committed
+ if n := len(m.Entries); n != 0 {
+ switch pr.State {
+ // optimistically increase the next when in ProgressStateReplicate
+ case ProgressStateReplicate:
+ last := m.Entries[n-1].Index
+ pr.optimisticUpdate(last)
+ pr.ins.add(last)
+ case ProgressStateProbe:
+ pr.pause()
+ default:
+ r.logger.Panicf("%x is sending append in unhandled state %s", r.id, pr.State)
+ }
+ }
+ }
+ r.send(m)
+}
+
+// sendHeartbeat sends an empty MsgApp
+func (r *raft) sendHeartbeat(to uint64, ctx []byte) {
+ // Attach the commit as min(to.matched, r.committed).
+ // When the leader sends out heartbeat message,
+ // the receiver(follower) might not be matched with the leader
+ // or it might not have all the committed entries.
+ // The leader MUST NOT forward the follower's commit to
+ // an unmatched index.
+ commit := min(r.getProgress(to).Match, r.raftLog.committed)
+ m := pb.Message{
+ To: to,
+ Type: pb.MsgHeartbeat,
+ Commit: commit,
+ Context: ctx,
+ }
+
+ r.send(m)
+}
+
+func (r *raft) forEachProgress(f func(id uint64, pr *Progress)) {
+ for id, pr := range r.prs {
+ f(id, pr)
+ }
+
+ for id, pr := range r.learnerPrs {
+ f(id, pr)
+ }
+}
+
+// bcastAppend sends RPC, with entries to all peers that are not up-to-date
+// according to the progress recorded in r.prs.
+func (r *raft) bcastAppend() {
+ r.forEachProgress(func(id uint64, _ *Progress) {
+ if id == r.id {
+ return
+ }
+
+ r.sendAppend(id)
+ })
+}
+
+// bcastHeartbeat sends RPC, without entries to all the peers.
+func (r *raft) bcastHeartbeat() {
+ lastCtx := r.readOnly.lastPendingRequestCtx()
+ if len(lastCtx) == 0 {
+ r.bcastHeartbeatWithCtx(nil)
+ } else {
+ r.bcastHeartbeatWithCtx([]byte(lastCtx))
+ }
+}
+
+func (r *raft) bcastHeartbeatWithCtx(ctx []byte) {
+ r.forEachProgress(func(id uint64, _ *Progress) {
+ if id == r.id {
+ return
+ }
+ r.sendHeartbeat(id, ctx)
+ })
+}
+
+// maybeCommit attempts to advance the commit index. Returns true if
+// the commit index changed (in which case the caller should call
+// r.bcastAppend).
+func (r *raft) maybeCommit() bool {
+ // TODO(bmizerany): optimize.. Currently naive
+ mis := make(uint64Slice, 0, len(r.prs))
+ for _, p := range r.prs {
+ mis = append(mis, p.Match)
+ }
+ sort.Sort(sort.Reverse(mis))
+ mci := mis[r.quorum()-1]
+ return r.raftLog.maybeCommit(mci, r.Term)
+}
+
+func (r *raft) reset(term uint64) {
+ if r.Term != term {
+ r.Term = term
+ r.Vote = None
+ }
+ r.lead = None
+
+ r.electionElapsed = 0
+ r.heartbeatElapsed = 0
+ r.resetRandomizedElectionTimeout()
+
+ r.abortLeaderTransfer()
+
+ r.votes = make(map[uint64]bool)
+ r.forEachProgress(func(id uint64, pr *Progress) {
+ *pr = Progress{Next: r.raftLog.lastIndex() + 1, ins: newInflights(r.maxInflight), IsLearner: pr.IsLearner}
+ if id == r.id {
+ pr.Match = r.raftLog.lastIndex()
+ }
+ })
+
+ r.pendingConf = false
+ r.readOnly = newReadOnly(r.readOnly.option)
+}
+
+func (r *raft) appendEntry(es ...pb.Entry) {
+ li := r.raftLog.lastIndex()
+ for i := range es {
+ es[i].Term = r.Term
+ es[i].Index = li + 1 + uint64(i)
+ }
+ r.raftLog.append(es...)
+ r.getProgress(r.id).maybeUpdate(r.raftLog.lastIndex())
+ // Regardless of maybeCommit's return, our caller will call bcastAppend.
+ r.maybeCommit()
+}
+
+// tickElection is run by followers and candidates after r.electionTimeout.
+func (r *raft) tickElection() {
+ r.electionElapsed++
+
+ if r.promotable() && r.pastElectionTimeout() {
+ r.electionElapsed = 0
+ r.Step(pb.Message{From: r.id, Type: pb.MsgHup})
+ }
+}
+
+// tickHeartbeat is run by leaders to send a MsgBeat after r.heartbeatTimeout.
+func (r *raft) tickHeartbeat() {
+ r.heartbeatElapsed++
+ r.electionElapsed++
+
+ if r.electionElapsed >= r.electionTimeout {
+ r.electionElapsed = 0
+ if r.checkQuorum {
+ r.Step(pb.Message{From: r.id, Type: pb.MsgCheckQuorum})
+ }
+ // If current leader cannot transfer leadership in electionTimeout, it becomes leader again.
+ if r.state == StateLeader && r.leadTransferee != None {
+ r.abortLeaderTransfer()
+ }
+ }
+
+ if r.state != StateLeader {
+ return
+ }
+
+ if r.heartbeatElapsed >= r.heartbeatTimeout {
+ r.heartbeatElapsed = 0
+ r.Step(pb.Message{From: r.id, Type: pb.MsgBeat})
+ }
+}
+
+func (r *raft) becomeFollower(term uint64, lead uint64) {
+ r.step = stepFollower
+ r.reset(term)
+ r.tick = r.tickElection
+ r.lead = lead
+ r.state = StateFollower
+ r.logger.Infof("%x became follower at term %d", r.id, r.Term)
+}
+
+func (r *raft) becomeCandidate() {
+ // TODO(xiangli) remove the panic when the raft implementation is stable
+ if r.state == StateLeader {
+ panic("invalid transition [leader -> candidate]")
+ }
+ r.step = stepCandidate
+ r.reset(r.Term + 1)
+ r.tick = r.tickElection
+ r.Vote = r.id
+ r.state = StateCandidate
+ r.logger.Infof("%x became candidate at term %d", r.id, r.Term)
+}
+
+func (r *raft) becomePreCandidate() {
+ // TODO(xiangli) remove the panic when the raft implementation is stable
+ if r.state == StateLeader {
+ panic("invalid transition [leader -> pre-candidate]")
+ }
+ // Becoming a pre-candidate changes our step functions and state,
+ // but doesn't change anything else. In particular it does not increase
+ // r.Term or change r.Vote.
+ r.step = stepCandidate
+ r.votes = make(map[uint64]bool)
+ r.tick = r.tickElection
+ r.state = StatePreCandidate
+ r.logger.Infof("%x became pre-candidate at term %d", r.id, r.Term)
+}
+
+func (r *raft) becomeLeader() {
+ // TODO(xiangli) remove the panic when the raft implementation is stable
+ if r.state == StateFollower {
+ panic("invalid transition [follower -> leader]")
+ }
+ r.step = stepLeader
+ r.reset(r.Term)
+ r.tick = r.tickHeartbeat
+ r.lead = r.id
+ r.state = StateLeader
+ ents, err := r.raftLog.entries(r.raftLog.committed+1, noLimit)
+ if err != nil {
+ r.logger.Panicf("unexpected error getting uncommitted entries (%v)", err)
+ }
+
+ nconf := numOfPendingConf(ents)
+ if nconf > 1 {
+ panic("unexpected multiple uncommitted config entry")
+ }
+ if nconf == 1 {
+ r.pendingConf = true
+ }
+
+ r.appendEntry(pb.Entry{Data: nil})
+ r.logger.Infof("%x became leader at term %d", r.id, r.Term)
+}
+
+func (r *raft) campaign(t CampaignType) {
+ var term uint64
+ var voteMsg pb.MessageType
+ if t == campaignPreElection {
+ r.becomePreCandidate()
+ voteMsg = pb.MsgPreVote
+ // PreVote RPCs are sent for the next term before we've incremented r.Term.
+ term = r.Term + 1
+ } else {
+ r.becomeCandidate()
+ voteMsg = pb.MsgVote
+ term = r.Term
+ }
+ if r.quorum() == r.poll(r.id, voteRespMsgType(voteMsg), true) {
+ // We won the election after voting for ourselves (which must mean that
+ // this is a single-node cluster). Advance to the next state.
+ if t == campaignPreElection {
+ r.campaign(campaignElection)
+ } else {
+ r.becomeLeader()
+ }
+ return
+ }
+ for id := range r.prs {
+ if id == r.id {
+ continue
+ }
+ r.logger.Infof("%x [logterm: %d, index: %d] sent %s request to %x at term %d",
+ r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), voteMsg, id, r.Term)
+
+ var ctx []byte
+ if t == campaignTransfer {
+ ctx = []byte(t)
+ }
+ r.send(pb.Message{Term: term, To: id, Type: voteMsg, Index: r.raftLog.lastIndex(), LogTerm: r.raftLog.lastTerm(), Context: ctx})
+ }
+}
+
+func (r *raft) poll(id uint64, t pb.MessageType, v bool) (granted int) {
+ if v {
+ r.logger.Infof("%x received %s from %x at term %d", r.id, t, id, r.Term)
+ } else {
+ r.logger.Infof("%x received %s rejection from %x at term %d", r.id, t, id, r.Term)
+ }
+ if _, ok := r.votes[id]; !ok {
+ r.votes[id] = v
+ }
+ for _, vv := range r.votes {
+ if vv {
+ granted++
+ }
+ }
+ return granted
+}
+
+func (r *raft) Step(m pb.Message) error {
+ // Handle the message term, which may result in our stepping down to a follower.
+ switch {
+ case m.Term == 0:
+ // local message
+ case m.Term > r.Term:
+ if m.Type == pb.MsgVote || m.Type == pb.MsgPreVote {
+ force := bytes.Equal(m.Context, []byte(campaignTransfer))
+ inLease := r.checkQuorum && r.lead != None && r.electionElapsed < r.electionTimeout
+ if !force && inLease {
+ // If a server receives a RequestVote request within the minimum election timeout
+ // of hearing from a current leader, it does not update its term or grant its vote
+ r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] ignored %s from %x [logterm: %d, index: %d] at term %d: lease is not expired (remaining ticks: %d)",
+ r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term, r.electionTimeout-r.electionElapsed)
+ return nil
+ }
+ }
+ switch {
+ case m.Type == pb.MsgPreVote:
+ // Never change our term in response to a PreVote
+ case m.Type == pb.MsgPreVoteResp && !m.Reject:
+ // We send pre-vote requests with a term in our future. If the
+ // pre-vote is granted, we will increment our term when we get a
+ // quorum. If it is not, the term comes from the node that
+ // rejected our vote so we should become a follower at the new
+ // term.
+ default:
+ r.logger.Infof("%x [term: %d] received a %s message with higher term from %x [term: %d]",
+ r.id, r.Term, m.Type, m.From, m.Term)
+ if m.Type == pb.MsgApp || m.Type == pb.MsgHeartbeat || m.Type == pb.MsgSnap {
+ r.becomeFollower(m.Term, m.From)
+ } else {
+ r.becomeFollower(m.Term, None)
+ }
+ }
+
+ case m.Term < r.Term:
+ if r.checkQuorum && (m.Type == pb.MsgHeartbeat || m.Type == pb.MsgApp) {
+ // We have received messages from a leader at a lower term. It is possible
+ // that these messages were simply delayed in the network, but this could
+ // also mean that this node has advanced its term number during a network
+ // partition, and it is now unable to either win an election or to rejoin
+ // the majority on the old term. If checkQuorum is false, this will be
+ // handled by incrementing term numbers in response to MsgVote with a
+ // higher term, but if checkQuorum is true we may not advance the term on
+ // MsgVote and must generate other messages to advance the term. The net
+ // result of these two features is to minimize the disruption caused by
+ // nodes that have been removed from the cluster's configuration: a
+ // removed node will send MsgVotes (or MsgPreVotes) which will be ignored,
+ // but it will not receive MsgApp or MsgHeartbeat, so it will not create
+ // disruptive term increases
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp})
+ } else {
+ // ignore other cases
+ r.logger.Infof("%x [term: %d] ignored a %s message with lower term from %x [term: %d]",
+ r.id, r.Term, m.Type, m.From, m.Term)
+ }
+ return nil
+ }
+
+ switch m.Type {
+ case pb.MsgHup:
+ if r.state != StateLeader {
+ ents, err := r.raftLog.slice(r.raftLog.applied+1, r.raftLog.committed+1, noLimit)
+ if err != nil {
+ r.logger.Panicf("unexpected error getting unapplied entries (%v)", err)
+ }
+ if n := numOfPendingConf(ents); n != 0 && r.raftLog.committed > r.raftLog.applied {
+ r.logger.Warningf("%x cannot campaign at term %d since there are still %d pending configuration changes to apply", r.id, r.Term, n)
+ return nil
+ }
+
+ r.logger.Infof("%x is starting a new election at term %d", r.id, r.Term)
+ if r.preVote {
+ r.campaign(campaignPreElection)
+ } else {
+ r.campaign(campaignElection)
+ }
+ } else {
+ r.logger.Debugf("%x ignoring MsgHup because already leader", r.id)
+ }
+
+ case pb.MsgVote, pb.MsgPreVote:
+ if r.isLearner {
+ // TODO: learner may need to vote, in case of node down when confchange.
+ r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] ignored %s from %x [logterm: %d, index: %d] at term %d: learner can not vote",
+ r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term)
+ return nil
+ }
+ // The m.Term > r.Term clause is for MsgPreVote. For MsgVote m.Term should
+ // always equal r.Term.
+ if (r.Vote == None || m.Term > r.Term || r.Vote == m.From) && r.raftLog.isUpToDate(m.Index, m.LogTerm) {
+ r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] cast %s for %x [logterm: %d, index: %d] at term %d",
+ r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term)
+ // When responding to Msg{Pre,}Vote messages we include the term
+ // from the message, not the local term. To see why consider the
+ // case where a single node was previously partitioned away and
+ // it's local term is now of date. If we include the local term
+ // (recall that for pre-votes we don't update the local term), the
+ // (pre-)campaigning node on the other end will proceed to ignore
+ // the message (it ignores all out of date messages).
+ // The term in the original message and current local term are the
+ // same in the case of regular votes, but different for pre-votes.
+ r.send(pb.Message{To: m.From, Term: m.Term, Type: voteRespMsgType(m.Type)})
+ if m.Type == pb.MsgVote {
+ // Only record real votes.
+ r.electionElapsed = 0
+ r.Vote = m.From
+ }
+ } else {
+ r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] rejected %s from %x [logterm: %d, index: %d] at term %d",
+ r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term)
+ r.send(pb.Message{To: m.From, Term: r.Term, Type: voteRespMsgType(m.Type), Reject: true})
+ }
+
+ default:
+ r.step(r, m)
+ }
+ return nil
+}
+
+type stepFunc func(r *raft, m pb.Message)
+
+func stepLeader(r *raft, m pb.Message) {
+ // These message types do not require any progress for m.From.
+ switch m.Type {
+ case pb.MsgBeat:
+ r.bcastHeartbeat()
+ return
+ case pb.MsgCheckQuorum:
+ if !r.checkQuorumActive() {
+ r.logger.Warningf("%x stepped down to follower since quorum is not active", r.id)
+ r.becomeFollower(r.Term, None)
+ }
+ return
+ case pb.MsgProp:
+ if len(m.Entries) == 0 {
+ r.logger.Panicf("%x stepped empty MsgProp", r.id)
+ }
+ if _, ok := r.prs[r.id]; !ok {
+ // If we are not currently a member of the range (i.e. this node
+ // was removed from the configuration while serving as leader),
+ // drop any new proposals.
+ return
+ }
+ if r.leadTransferee != None {
+ r.logger.Debugf("%x [term %d] transfer leadership to %x is in progress; dropping proposal", r.id, r.Term, r.leadTransferee)
+ return
+ }
+
+ for i, e := range m.Entries {
+ if e.Type == pb.EntryConfChange {
+ if r.pendingConf {
+ r.logger.Infof("propose conf %s ignored since pending unapplied configuration", e.String())
+ m.Entries[i] = pb.Entry{Type: pb.EntryNormal}
+ }
+ r.pendingConf = true
+ }
+ }
+ r.appendEntry(m.Entries...)
+ r.bcastAppend()
+ return
+ case pb.MsgReadIndex:
+ if r.quorum() > 1 {
+ if r.raftLog.zeroTermOnErrCompacted(r.raftLog.term(r.raftLog.committed)) != r.Term {
+ // Reject read only request when this leader has not committed any log entry at its term.
+ return
+ }
+
+ // thinking: use an interally defined context instead of the user given context.
+ // We can express this in terms of the term and index instead of a user-supplied value.
+ // This would allow multiple reads to piggyback on the same message.
+ switch r.readOnly.option {
+ case ReadOnlySafe:
+ r.readOnly.addRequest(r.raftLog.committed, m)
+ r.bcastHeartbeatWithCtx(m.Entries[0].Data)
+ case ReadOnlyLeaseBased:
+ ri := r.raftLog.committed
+ if m.From == None || m.From == r.id { // from local member
+ r.readStates = append(r.readStates, ReadState{Index: r.raftLog.committed, RequestCtx: m.Entries[0].Data})
+ } else {
+ r.send(pb.Message{To: m.From, Type: pb.MsgReadIndexResp, Index: ri, Entries: m.Entries})
+ }
+ }
+ } else {
+ r.readStates = append(r.readStates, ReadState{Index: r.raftLog.committed, RequestCtx: m.Entries[0].Data})
+ }
+
+ return
+ }
+
+ // All other message types require a progress for m.From (pr).
+ pr := r.getProgress(m.From)
+ if pr == nil {
+ r.logger.Debugf("%x no progress available for %x", r.id, m.From)
+ return
+ }
+ switch m.Type {
+ case pb.MsgAppResp:
+ pr.RecentActive = true
+
+ if m.Reject {
+ r.logger.Debugf("%x received msgApp rejection(lastindex: %d) from %x for index %d",
+ r.id, m.RejectHint, m.From, m.Index)
+ if pr.maybeDecrTo(m.Index, m.RejectHint) {
+ r.logger.Debugf("%x decreased progress of %x to [%s]", r.id, m.From, pr)
+ if pr.State == ProgressStateReplicate {
+ pr.becomeProbe()
+ }
+ r.sendAppend(m.From)
+ }
+ } else {
+ oldPaused := pr.IsPaused()
+ if pr.maybeUpdate(m.Index) {
+ switch {
+ case pr.State == ProgressStateProbe:
+ pr.becomeReplicate()
+ case pr.State == ProgressStateSnapshot && pr.needSnapshotAbort():
+ r.logger.Debugf("%x snapshot aborted, resumed sending replication messages to %x [%s]", r.id, m.From, pr)
+ pr.becomeProbe()
+ case pr.State == ProgressStateReplicate:
+ pr.ins.freeTo(m.Index)
+ }
+
+ if r.maybeCommit() {
+ r.bcastAppend()
+ } else if oldPaused {
+ // update() reset the wait state on this node. If we had delayed sending
+ // an update before, send it now.
+ r.sendAppend(m.From)
+ }
+ // Transfer leadership is in progress.
+ if m.From == r.leadTransferee && pr.Match == r.raftLog.lastIndex() {
+ r.logger.Infof("%x sent MsgTimeoutNow to %x after received MsgAppResp", r.id, m.From)
+ r.sendTimeoutNow(m.From)
+ }
+ }
+ }
+ case pb.MsgHeartbeatResp:
+ pr.RecentActive = true
+ pr.resume()
+
+ // free one slot for the full inflights window to allow progress.
+ if pr.State == ProgressStateReplicate && pr.ins.full() {
+ pr.ins.freeFirstOne()
+ }
+ if pr.Match < r.raftLog.lastIndex() {
+ r.sendAppend(m.From)
+ }
+
+ if r.readOnly.option != ReadOnlySafe || len(m.Context) == 0 {
+ return
+ }
+
+ ackCount := r.readOnly.recvAck(m)
+ if ackCount < r.quorum() {
+ return
+ }
+
+ rss := r.readOnly.advance(m)
+ for _, rs := range rss {
+ req := rs.req
+ if req.From == None || req.From == r.id { // from local member
+ r.readStates = append(r.readStates, ReadState{Index: rs.index, RequestCtx: req.Entries[0].Data})
+ } else {
+ r.send(pb.Message{To: req.From, Type: pb.MsgReadIndexResp, Index: rs.index, Entries: req.Entries})
+ }
+ }
+ case pb.MsgSnapStatus:
+ if pr.State != ProgressStateSnapshot {
+ return
+ }
+ if !m.Reject {
+ pr.becomeProbe()
+ r.logger.Debugf("%x snapshot succeeded, resumed sending replication messages to %x [%s]", r.id, m.From, pr)
+ } else {
+ pr.snapshotFailure()
+ pr.becomeProbe()
+ r.logger.Debugf("%x snapshot failed, resumed sending replication messages to %x [%s]", r.id, m.From, pr)
+ }
+ // If snapshot finish, wait for the msgAppResp from the remote node before sending
+ // out the next msgApp.
+ // If snapshot failure, wait for a heartbeat interval before next try
+ pr.pause()
+ case pb.MsgUnreachable:
+ // During optimistic replication, if the remote becomes unreachable,
+ // there is huge probability that a MsgApp is lost.
+ if pr.State == ProgressStateReplicate {
+ pr.becomeProbe()
+ }
+ r.logger.Debugf("%x failed to send message to %x because it is unreachable [%s]", r.id, m.From, pr)
+ case pb.MsgTransferLeader:
+ if pr.IsLearner {
+ r.logger.Debugf("%x is learner. Ignored transferring leadership", r.id)
+ return
+ }
+ leadTransferee := m.From
+ lastLeadTransferee := r.leadTransferee
+ if lastLeadTransferee != None {
+ if lastLeadTransferee == leadTransferee {
+ r.logger.Infof("%x [term %d] transfer leadership to %x is in progress, ignores request to same node %x",
+ r.id, r.Term, leadTransferee, leadTransferee)
+ return
+ }
+ r.abortLeaderTransfer()
+ r.logger.Infof("%x [term %d] abort previous transferring leadership to %x", r.id, r.Term, lastLeadTransferee)
+ }
+ if leadTransferee == r.id {
+ r.logger.Debugf("%x is already leader. Ignored transferring leadership to self", r.id)
+ return
+ }
+ // Transfer leadership to third party.
+ r.logger.Infof("%x [term %d] starts to transfer leadership to %x", r.id, r.Term, leadTransferee)
+ // Transfer leadership should be finished in one electionTimeout, so reset r.electionElapsed.
+ r.electionElapsed = 0
+ r.leadTransferee = leadTransferee
+ if pr.Match == r.raftLog.lastIndex() {
+ r.sendTimeoutNow(leadTransferee)
+ r.logger.Infof("%x sends MsgTimeoutNow to %x immediately as %x already has up-to-date log", r.id, leadTransferee, leadTransferee)
+ } else {
+ r.sendAppend(leadTransferee)
+ }
+ }
+}
+
+// stepCandidate is shared by StateCandidate and StatePreCandidate; the difference is
+// whether they respond to MsgVoteResp or MsgPreVoteResp.
+func stepCandidate(r *raft, m pb.Message) {
+ // Only handle vote responses corresponding to our candidacy (while in
+ // StateCandidate, we may get stale MsgPreVoteResp messages in this term from
+ // our pre-candidate state).
+ var myVoteRespType pb.MessageType
+ if r.state == StatePreCandidate {
+ myVoteRespType = pb.MsgPreVoteResp
+ } else {
+ myVoteRespType = pb.MsgVoteResp
+ }
+ switch m.Type {
+ case pb.MsgProp:
+ r.logger.Infof("%x no leader at term %d; dropping proposal", r.id, r.Term)
+ return
+ case pb.MsgApp:
+ r.becomeFollower(r.Term, m.From)
+ r.handleAppendEntries(m)
+ case pb.MsgHeartbeat:
+ r.becomeFollower(r.Term, m.From)
+ r.handleHeartbeat(m)
+ case pb.MsgSnap:
+ r.becomeFollower(m.Term, m.From)
+ r.handleSnapshot(m)
+ case myVoteRespType:
+ gr := r.poll(m.From, m.Type, !m.Reject)
+ r.logger.Infof("%x [quorum:%d] has received %d %s votes and %d vote rejections", r.id, r.quorum(), gr, m.Type, len(r.votes)-gr)
+ switch r.quorum() {
+ case gr:
+ if r.state == StatePreCandidate {
+ r.campaign(campaignElection)
+ } else {
+ r.becomeLeader()
+ r.bcastAppend()
+ }
+ case len(r.votes) - gr:
+ r.becomeFollower(r.Term, None)
+ }
+ case pb.MsgTimeoutNow:
+ r.logger.Debugf("%x [term %d state %v] ignored MsgTimeoutNow from %x", r.id, r.Term, r.state, m.From)
+ }
+}
+
+func stepFollower(r *raft, m pb.Message) {
+ switch m.Type {
+ case pb.MsgProp:
+ if r.lead == None {
+ r.logger.Infof("%x no leader at term %d; dropping proposal", r.id, r.Term)
+ return
+ } else if r.disableProposalForwarding {
+ r.logger.Infof("%x not forwarding to leader %x at term %d; dropping proposal", r.id, r.lead, r.Term)
+ return
+ }
+ m.To = r.lead
+ r.send(m)
+ case pb.MsgApp:
+ r.electionElapsed = 0
+ r.lead = m.From
+ r.handleAppendEntries(m)
+ case pb.MsgHeartbeat:
+ r.electionElapsed = 0
+ r.lead = m.From
+ r.handleHeartbeat(m)
+ case pb.MsgSnap:
+ r.electionElapsed = 0
+ r.lead = m.From
+ r.handleSnapshot(m)
+ case pb.MsgTransferLeader:
+ if r.lead == None {
+ r.logger.Infof("%x no leader at term %d; dropping leader transfer msg", r.id, r.Term)
+ return
+ }
+ m.To = r.lead
+ r.send(m)
+ case pb.MsgTimeoutNow:
+ if r.promotable() {
+ r.logger.Infof("%x [term %d] received MsgTimeoutNow from %x and starts an election to get leadership.", r.id, r.Term, m.From)
+ // Leadership transfers never use pre-vote even if r.preVote is true; we
+ // know we are not recovering from a partition so there is no need for the
+ // extra round trip.
+ r.campaign(campaignTransfer)
+ } else {
+ r.logger.Infof("%x received MsgTimeoutNow from %x but is not promotable", r.id, m.From)
+ }
+ case pb.MsgReadIndex:
+ if r.lead == None {
+ r.logger.Infof("%x no leader at term %d; dropping index reading msg", r.id, r.Term)
+ return
+ }
+ m.To = r.lead
+ r.send(m)
+ case pb.MsgReadIndexResp:
+ if len(m.Entries) != 1 {
+ r.logger.Errorf("%x invalid format of MsgReadIndexResp from %x, entries count: %d", r.id, m.From, len(m.Entries))
+ return
+ }
+ r.readStates = append(r.readStates, ReadState{Index: m.Index, RequestCtx: m.Entries[0].Data})
+ }
+}
+
+func (r *raft) handleAppendEntries(m pb.Message) {
+ if m.Index < r.raftLog.committed {
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: r.raftLog.committed})
+ return
+ }
+
+ if mlastIndex, ok := r.raftLog.maybeAppend(m.Index, m.LogTerm, m.Commit, m.Entries...); ok {
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: mlastIndex})
+ } else {
+ r.logger.Debugf("%x [logterm: %d, index: %d] rejected msgApp [logterm: %d, index: %d] from %x",
+ r.id, r.raftLog.zeroTermOnErrCompacted(r.raftLog.term(m.Index)), m.Index, m.LogTerm, m.Index, m.From)
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: m.Index, Reject: true, RejectHint: r.raftLog.lastIndex()})
+ }
+}
+
+func (r *raft) handleHeartbeat(m pb.Message) {
+ r.raftLog.commitTo(m.Commit)
+ r.send(pb.Message{To: m.From, Type: pb.MsgHeartbeatResp, Context: m.Context})
+}
+
+func (r *raft) handleSnapshot(m pb.Message) {
+ sindex, sterm := m.Snapshot.Metadata.Index, m.Snapshot.Metadata.Term
+ if r.restore(m.Snapshot) {
+ r.logger.Infof("%x [commit: %d] restored snapshot [index: %d, term: %d]",
+ r.id, r.raftLog.committed, sindex, sterm)
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: r.raftLog.lastIndex()})
+ } else {
+ r.logger.Infof("%x [commit: %d] ignored snapshot [index: %d, term: %d]",
+ r.id, r.raftLog.committed, sindex, sterm)
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: r.raftLog.committed})
+ }
+}
+
+// restore recovers the state machine from a snapshot. It restores the log and the
+// configuration of state machine.
+func (r *raft) restore(s pb.Snapshot) bool {
+ if s.Metadata.Index <= r.raftLog.committed {
+ return false
+ }
+ if r.raftLog.matchTerm(s.Metadata.Index, s.Metadata.Term) {
+ r.logger.Infof("%x [commit: %d, lastindex: %d, lastterm: %d] fast-forwarded commit to snapshot [index: %d, term: %d]",
+ r.id, r.raftLog.committed, r.raftLog.lastIndex(), r.raftLog.lastTerm(), s.Metadata.Index, s.Metadata.Term)
+ r.raftLog.commitTo(s.Metadata.Index)
+ return false
+ }
+
+ // The normal peer can't become learner.
+ if !r.isLearner {
+ for _, id := range s.Metadata.ConfState.Learners {
+ if id == r.id {
+ r.logger.Errorf("%x can't become learner when restores snapshot [index: %d, term: %d]", r.id, s.Metadata.Index, s.Metadata.Term)
+ return false
+ }
+ }
+ }
+
+ r.logger.Infof("%x [commit: %d, lastindex: %d, lastterm: %d] starts to restore snapshot [index: %d, term: %d]",
+ r.id, r.raftLog.committed, r.raftLog.lastIndex(), r.raftLog.lastTerm(), s.Metadata.Index, s.Metadata.Term)
+
+ r.raftLog.restore(s)
+ r.prs = make(map[uint64]*Progress)
+ r.learnerPrs = make(map[uint64]*Progress)
+ r.restoreNode(s.Metadata.ConfState.Nodes, false)
+ r.restoreNode(s.Metadata.ConfState.Learners, true)
+ return true
+}
+
+func (r *raft) restoreNode(nodes []uint64, isLearner bool) {
+ for _, n := range nodes {
+ match, next := uint64(0), r.raftLog.lastIndex()+1
+ if n == r.id {
+ match = next - 1
+ r.isLearner = isLearner
+ }
+ r.setProgress(n, match, next, isLearner)
+ r.logger.Infof("%x restored progress of %x [%s]", r.id, n, r.getProgress(n))
+ }
+}
+
+// promotable indicates whether state machine can be promoted to leader,
+// which is true when its own id is in progress list.
+func (r *raft) promotable() bool {
+ _, ok := r.prs[r.id]
+ return ok
+}
+
+func (r *raft) addNode(id uint64) {
+ r.addNodeOrLearnerNode(id, false)
+}
+
+func (r *raft) addLearner(id uint64) {
+ r.addNodeOrLearnerNode(id, true)
+}
+
+func (r *raft) addNodeOrLearnerNode(id uint64, isLearner bool) {
+ r.pendingConf = false
+ pr := r.getProgress(id)
+ if pr == nil {
+ r.setProgress(id, 0, r.raftLog.lastIndex()+1, isLearner)
+ } else {
+ if isLearner && !pr.IsLearner {
+ // can only change Learner to Voter
+ r.logger.Infof("%x ignored addLeaner: do not support changing %x from raft peer to learner.", r.id, id)
+ return
+ }
+
+ if isLearner == pr.IsLearner {
+ // Ignore any redundant addNode calls (which can happen because the
+ // initial bootstrapping entries are applied twice).
+ return
+ }
+
+ // change Learner to Voter, use origin Learner progress
+ delete(r.learnerPrs, id)
+ pr.IsLearner = false
+ r.prs[id] = pr
+ }
+
+ if r.id == id {
+ r.isLearner = isLearner
+ }
+
+ // When a node is first added, we should mark it as recently active.
+ // Otherwise, CheckQuorum may cause us to step down if it is invoked
+ // before the added node has a chance to communicate with us.
+ pr = r.getProgress(id)
+ pr.RecentActive = true
+}
+
+func (r *raft) removeNode(id uint64) {
+ r.delProgress(id)
+ r.pendingConf = false
+
+ // do not try to commit or abort transferring if there is no nodes in the cluster.
+ if len(r.prs) == 0 && len(r.learnerPrs) == 0 {
+ return
+ }
+
+ // The quorum size is now smaller, so see if any pending entries can
+ // be committed.
+ if r.maybeCommit() {
+ r.bcastAppend()
+ }
+ // If the removed node is the leadTransferee, then abort the leadership transferring.
+ if r.state == StateLeader && r.leadTransferee == id {
+ r.abortLeaderTransfer()
+ }
+}
+
+func (r *raft) resetPendingConf() { r.pendingConf = false }
+
+func (r *raft) setProgress(id, match, next uint64, isLearner bool) {
+ if !isLearner {
+ delete(r.learnerPrs, id)
+ r.prs[id] = &Progress{Next: next, Match: match, ins: newInflights(r.maxInflight)}
+ return
+ }
+
+ if _, ok := r.prs[id]; ok {
+ panic(fmt.Sprintf("%x unexpected changing from voter to learner for %x", r.id, id))
+ }
+ r.learnerPrs[id] = &Progress{Next: next, Match: match, ins: newInflights(r.maxInflight), IsLearner: true}
+}
+
+func (r *raft) delProgress(id uint64) {
+ delete(r.prs, id)
+ delete(r.learnerPrs, id)
+}
+
+func (r *raft) loadState(state pb.HardState) {
+ if state.Commit < r.raftLog.committed || state.Commit > r.raftLog.lastIndex() {
+ r.logger.Panicf("%x state.commit %d is out of range [%d, %d]", r.id, state.Commit, r.raftLog.committed, r.raftLog.lastIndex())
+ }
+ r.raftLog.committed = state.Commit
+ r.Term = state.Term
+ r.Vote = state.Vote
+}
+
+// pastElectionTimeout returns true iff r.electionElapsed is greater
+// than or equal to the randomized election timeout in
+// [electiontimeout, 2 * electiontimeout - 1].
+func (r *raft) pastElectionTimeout() bool {
+ return r.electionElapsed >= r.randomizedElectionTimeout
+}
+
+func (r *raft) resetRandomizedElectionTimeout() {
+ r.randomizedElectionTimeout = r.electionTimeout + globalRand.Intn(r.electionTimeout)
+}
+
+// checkQuorumActive returns true if the quorum is active from
+// the view of the local raft state machine. Otherwise, it returns
+// false.
+// checkQuorumActive also resets all RecentActive to false.
+func (r *raft) checkQuorumActive() bool {
+ var act int
+
+ r.forEachProgress(func(id uint64, pr *Progress) {
+ if id == r.id { // self is always active
+ act++
+ return
+ }
+
+ if pr.RecentActive && !pr.IsLearner {
+ act++
+ }
+
+ pr.RecentActive = false
+ })
+
+ return act >= r.quorum()
+}
+
+func (r *raft) sendTimeoutNow(to uint64) {
+ r.send(pb.Message{To: to, Type: pb.MsgTimeoutNow})
+}
+
+func (r *raft) abortLeaderTransfer() {
+ r.leadTransferee = None
+}
+
+func numOfPendingConf(ents []pb.Entry) int {
+ n := 0
+ for i := range ents {
+ if ents[i].Type == pb.EntryConfChange {
+ n++
+ }
+ }
+ return n
+}
diff --git a/vendor/github.com/coreos/etcd/raft/raftpb/raft.pb.go b/vendor/github.com/coreos/etcd/raft/raftpb/raft.pb.go
new file mode 100644
index 00000000..fd9ee372
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/raftpb/raft.pb.go
@@ -0,0 +1,2004 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: raft.proto
+
+/*
+ Package raftpb is a generated protocol buffer package.
+
+ It is generated from these files:
+ raft.proto
+
+ It has these top-level messages:
+ Entry
+ SnapshotMetadata
+ Snapshot
+ Message
+ HardState
+ ConfState
+ ConfChange
+*/
+package raftpb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type EntryType int32
+
+const (
+ EntryNormal EntryType = 0
+ EntryConfChange EntryType = 1
+)
+
+var EntryType_name = map[int32]string{
+ 0: "EntryNormal",
+ 1: "EntryConfChange",
+}
+var EntryType_value = map[string]int32{
+ "EntryNormal": 0,
+ "EntryConfChange": 1,
+}
+
+func (x EntryType) Enum() *EntryType {
+ p := new(EntryType)
+ *p = x
+ return p
+}
+func (x EntryType) String() string {
+ return proto.EnumName(EntryType_name, int32(x))
+}
+func (x *EntryType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(EntryType_value, data, "EntryType")
+ if err != nil {
+ return err
+ }
+ *x = EntryType(value)
+ return nil
+}
+func (EntryType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRaft, []int{0} }
+
+type MessageType int32
+
+const (
+ MsgHup MessageType = 0
+ MsgBeat MessageType = 1
+ MsgProp MessageType = 2
+ MsgApp MessageType = 3
+ MsgAppResp MessageType = 4
+ MsgVote MessageType = 5
+ MsgVoteResp MessageType = 6
+ MsgSnap MessageType = 7
+ MsgHeartbeat MessageType = 8
+ MsgHeartbeatResp MessageType = 9
+ MsgUnreachable MessageType = 10
+ MsgSnapStatus MessageType = 11
+ MsgCheckQuorum MessageType = 12
+ MsgTransferLeader MessageType = 13
+ MsgTimeoutNow MessageType = 14
+ MsgReadIndex MessageType = 15
+ MsgReadIndexResp MessageType = 16
+ MsgPreVote MessageType = 17
+ MsgPreVoteResp MessageType = 18
+)
+
+var MessageType_name = map[int32]string{
+ 0: "MsgHup",
+ 1: "MsgBeat",
+ 2: "MsgProp",
+ 3: "MsgApp",
+ 4: "MsgAppResp",
+ 5: "MsgVote",
+ 6: "MsgVoteResp",
+ 7: "MsgSnap",
+ 8: "MsgHeartbeat",
+ 9: "MsgHeartbeatResp",
+ 10: "MsgUnreachable",
+ 11: "MsgSnapStatus",
+ 12: "MsgCheckQuorum",
+ 13: "MsgTransferLeader",
+ 14: "MsgTimeoutNow",
+ 15: "MsgReadIndex",
+ 16: "MsgReadIndexResp",
+ 17: "MsgPreVote",
+ 18: "MsgPreVoteResp",
+}
+var MessageType_value = map[string]int32{
+ "MsgHup": 0,
+ "MsgBeat": 1,
+ "MsgProp": 2,
+ "MsgApp": 3,
+ "MsgAppResp": 4,
+ "MsgVote": 5,
+ "MsgVoteResp": 6,
+ "MsgSnap": 7,
+ "MsgHeartbeat": 8,
+ "MsgHeartbeatResp": 9,
+ "MsgUnreachable": 10,
+ "MsgSnapStatus": 11,
+ "MsgCheckQuorum": 12,
+ "MsgTransferLeader": 13,
+ "MsgTimeoutNow": 14,
+ "MsgReadIndex": 15,
+ "MsgReadIndexResp": 16,
+ "MsgPreVote": 17,
+ "MsgPreVoteResp": 18,
+}
+
+func (x MessageType) Enum() *MessageType {
+ p := new(MessageType)
+ *p = x
+ return p
+}
+func (x MessageType) String() string {
+ return proto.EnumName(MessageType_name, int32(x))
+}
+func (x *MessageType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MessageType_value, data, "MessageType")
+ if err != nil {
+ return err
+ }
+ *x = MessageType(value)
+ return nil
+}
+func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRaft, []int{1} }
+
+type ConfChangeType int32
+
+const (
+ ConfChangeAddNode ConfChangeType = 0
+ ConfChangeRemoveNode ConfChangeType = 1
+ ConfChangeUpdateNode ConfChangeType = 2
+ ConfChangeAddLearnerNode ConfChangeType = 3
+)
+
+var ConfChangeType_name = map[int32]string{
+ 0: "ConfChangeAddNode",
+ 1: "ConfChangeRemoveNode",
+ 2: "ConfChangeUpdateNode",
+ 3: "ConfChangeAddLearnerNode",
+}
+var ConfChangeType_value = map[string]int32{
+ "ConfChangeAddNode": 0,
+ "ConfChangeRemoveNode": 1,
+ "ConfChangeUpdateNode": 2,
+ "ConfChangeAddLearnerNode": 3,
+}
+
+func (x ConfChangeType) Enum() *ConfChangeType {
+ p := new(ConfChangeType)
+ *p = x
+ return p
+}
+func (x ConfChangeType) String() string {
+ return proto.EnumName(ConfChangeType_name, int32(x))
+}
+func (x *ConfChangeType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(ConfChangeType_value, data, "ConfChangeType")
+ if err != nil {
+ return err
+ }
+ *x = ConfChangeType(value)
+ return nil
+}
+func (ConfChangeType) EnumDescriptor() ([]byte, []int) { return fileDescriptorRaft, []int{2} }
+
+type Entry struct {
+ Term uint64 `protobuf:"varint,2,opt,name=Term" json:"Term"`
+ Index uint64 `protobuf:"varint,3,opt,name=Index" json:"Index"`
+ Type EntryType `protobuf:"varint,1,opt,name=Type,enum=raftpb.EntryType" json:"Type"`
+ Data []byte `protobuf:"bytes,4,opt,name=Data" json:"Data,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Entry) Reset() { *m = Entry{} }
+func (m *Entry) String() string { return proto.CompactTextString(m) }
+func (*Entry) ProtoMessage() {}
+func (*Entry) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{0} }
+
+type SnapshotMetadata struct {
+ ConfState ConfState `protobuf:"bytes,1,opt,name=conf_state,json=confState" json:"conf_state"`
+ Index uint64 `protobuf:"varint,2,opt,name=index" json:"index"`
+ Term uint64 `protobuf:"varint,3,opt,name=term" json:"term"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SnapshotMetadata) Reset() { *m = SnapshotMetadata{} }
+func (m *SnapshotMetadata) String() string { return proto.CompactTextString(m) }
+func (*SnapshotMetadata) ProtoMessage() {}
+func (*SnapshotMetadata) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{1} }
+
+type Snapshot struct {
+ Data []byte `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
+ Metadata SnapshotMetadata `protobuf:"bytes,2,opt,name=metadata" json:"metadata"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Snapshot) Reset() { *m = Snapshot{} }
+func (m *Snapshot) String() string { return proto.CompactTextString(m) }
+func (*Snapshot) ProtoMessage() {}
+func (*Snapshot) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{2} }
+
+type Message struct {
+ Type MessageType `protobuf:"varint,1,opt,name=type,enum=raftpb.MessageType" json:"type"`
+ To uint64 `protobuf:"varint,2,opt,name=to" json:"to"`
+ From uint64 `protobuf:"varint,3,opt,name=from" json:"from"`
+ Term uint64 `protobuf:"varint,4,opt,name=term" json:"term"`
+ LogTerm uint64 `protobuf:"varint,5,opt,name=logTerm" json:"logTerm"`
+ Index uint64 `protobuf:"varint,6,opt,name=index" json:"index"`
+ Entries []Entry `protobuf:"bytes,7,rep,name=entries" json:"entries"`
+ Commit uint64 `protobuf:"varint,8,opt,name=commit" json:"commit"`
+ Snapshot Snapshot `protobuf:"bytes,9,opt,name=snapshot" json:"snapshot"`
+ Reject bool `protobuf:"varint,10,opt,name=reject" json:"reject"`
+ RejectHint uint64 `protobuf:"varint,11,opt,name=rejectHint" json:"rejectHint"`
+ Context []byte `protobuf:"bytes,12,opt,name=context" json:"context,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Message) Reset() { *m = Message{} }
+func (m *Message) String() string { return proto.CompactTextString(m) }
+func (*Message) ProtoMessage() {}
+func (*Message) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{3} }
+
+type HardState struct {
+ Term uint64 `protobuf:"varint,1,opt,name=term" json:"term"`
+ Vote uint64 `protobuf:"varint,2,opt,name=vote" json:"vote"`
+ Commit uint64 `protobuf:"varint,3,opt,name=commit" json:"commit"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *HardState) Reset() { *m = HardState{} }
+func (m *HardState) String() string { return proto.CompactTextString(m) }
+func (*HardState) ProtoMessage() {}
+func (*HardState) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{4} }
+
+type ConfState struct {
+ Nodes []uint64 `protobuf:"varint,1,rep,name=nodes" json:"nodes,omitempty"`
+ Learners []uint64 `protobuf:"varint,2,rep,name=learners" json:"learners,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ConfState) Reset() { *m = ConfState{} }
+func (m *ConfState) String() string { return proto.CompactTextString(m) }
+func (*ConfState) ProtoMessage() {}
+func (*ConfState) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{5} }
+
+type ConfChange struct {
+ ID uint64 `protobuf:"varint,1,opt,name=ID" json:"ID"`
+ Type ConfChangeType `protobuf:"varint,2,opt,name=Type,enum=raftpb.ConfChangeType" json:"Type"`
+ NodeID uint64 `protobuf:"varint,3,opt,name=NodeID" json:"NodeID"`
+ Context []byte `protobuf:"bytes,4,opt,name=Context" json:"Context,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ConfChange) Reset() { *m = ConfChange{} }
+func (m *ConfChange) String() string { return proto.CompactTextString(m) }
+func (*ConfChange) ProtoMessage() {}
+func (*ConfChange) Descriptor() ([]byte, []int) { return fileDescriptorRaft, []int{6} }
+
+func init() {
+ proto.RegisterType((*Entry)(nil), "raftpb.Entry")
+ proto.RegisterType((*SnapshotMetadata)(nil), "raftpb.SnapshotMetadata")
+ proto.RegisterType((*Snapshot)(nil), "raftpb.Snapshot")
+ proto.RegisterType((*Message)(nil), "raftpb.Message")
+ proto.RegisterType((*HardState)(nil), "raftpb.HardState")
+ proto.RegisterType((*ConfState)(nil), "raftpb.ConfState")
+ proto.RegisterType((*ConfChange)(nil), "raftpb.ConfChange")
+ proto.RegisterEnum("raftpb.EntryType", EntryType_name, EntryType_value)
+ proto.RegisterEnum("raftpb.MessageType", MessageType_name, MessageType_value)
+ proto.RegisterEnum("raftpb.ConfChangeType", ConfChangeType_name, ConfChangeType_value)
+}
+func (m *Entry) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Entry) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Type))
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Index))
+ if m.Data != nil {
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Data)))
+ i += copy(dAtA[i:], m.Data)
+ }
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *SnapshotMetadata) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *SnapshotMetadata) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.ConfState.Size()))
+ n1, err := m.ConfState.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n1
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Index))
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *Snapshot) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if m.Data != nil {
+ dAtA[i] = 0xa
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Data)))
+ i += copy(dAtA[i:], m.Data)
+ }
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Metadata.Size()))
+ n2, err := m.Metadata.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n2
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *Message) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Message) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Type))
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.To))
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.From))
+ dAtA[i] = 0x20
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ dAtA[i] = 0x28
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.LogTerm))
+ dAtA[i] = 0x30
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Index))
+ if len(m.Entries) > 0 {
+ for _, msg := range m.Entries {
+ dAtA[i] = 0x3a
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(msg.Size()))
+ n, err := msg.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n
+ }
+ }
+ dAtA[i] = 0x40
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Commit))
+ dAtA[i] = 0x4a
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Snapshot.Size()))
+ n3, err := m.Snapshot.MarshalTo(dAtA[i:])
+ if err != nil {
+ return 0, err
+ }
+ i += n3
+ dAtA[i] = 0x50
+ i++
+ if m.Reject {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
+ dAtA[i] = 0x58
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.RejectHint))
+ if m.Context != nil {
+ dAtA[i] = 0x62
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Context)))
+ i += copy(dAtA[i:], m.Context)
+ }
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *HardState) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *HardState) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Term))
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Vote))
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Commit))
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *ConfState) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ConfState) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ if len(m.Nodes) > 0 {
+ for _, num := range m.Nodes {
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(num))
+ }
+ }
+ if len(m.Learners) > 0 {
+ for _, num := range m.Learners {
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(num))
+ }
+ }
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *ConfChange) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *ConfChange) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.ID))
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.Type))
+ dAtA[i] = 0x18
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(m.NodeID))
+ if m.Context != nil {
+ dAtA[i] = 0x22
+ i++
+ i = encodeVarintRaft(dAtA, i, uint64(len(m.Context)))
+ i += copy(dAtA[i:], m.Context)
+ }
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func encodeVarintRaft(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Entry) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRaft(uint64(m.Type))
+ n += 1 + sovRaft(uint64(m.Term))
+ n += 1 + sovRaft(uint64(m.Index))
+ if m.Data != nil {
+ l = len(m.Data)
+ n += 1 + l + sovRaft(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *SnapshotMetadata) Size() (n int) {
+ var l int
+ _ = l
+ l = m.ConfState.Size()
+ n += 1 + l + sovRaft(uint64(l))
+ n += 1 + sovRaft(uint64(m.Index))
+ n += 1 + sovRaft(uint64(m.Term))
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *Snapshot) Size() (n int) {
+ var l int
+ _ = l
+ if m.Data != nil {
+ l = len(m.Data)
+ n += 1 + l + sovRaft(uint64(l))
+ }
+ l = m.Metadata.Size()
+ n += 1 + l + sovRaft(uint64(l))
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *Message) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRaft(uint64(m.Type))
+ n += 1 + sovRaft(uint64(m.To))
+ n += 1 + sovRaft(uint64(m.From))
+ n += 1 + sovRaft(uint64(m.Term))
+ n += 1 + sovRaft(uint64(m.LogTerm))
+ n += 1 + sovRaft(uint64(m.Index))
+ if len(m.Entries) > 0 {
+ for _, e := range m.Entries {
+ l = e.Size()
+ n += 1 + l + sovRaft(uint64(l))
+ }
+ }
+ n += 1 + sovRaft(uint64(m.Commit))
+ l = m.Snapshot.Size()
+ n += 1 + l + sovRaft(uint64(l))
+ n += 2
+ n += 1 + sovRaft(uint64(m.RejectHint))
+ if m.Context != nil {
+ l = len(m.Context)
+ n += 1 + l + sovRaft(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *HardState) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRaft(uint64(m.Term))
+ n += 1 + sovRaft(uint64(m.Vote))
+ n += 1 + sovRaft(uint64(m.Commit))
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *ConfState) Size() (n int) {
+ var l int
+ _ = l
+ if len(m.Nodes) > 0 {
+ for _, e := range m.Nodes {
+ n += 1 + sovRaft(uint64(e))
+ }
+ }
+ if len(m.Learners) > 0 {
+ for _, e := range m.Learners {
+ n += 1 + sovRaft(uint64(e))
+ }
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *ConfChange) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRaft(uint64(m.ID))
+ n += 1 + sovRaft(uint64(m.Type))
+ n += 1 + sovRaft(uint64(m.NodeID))
+ if m.Context != nil {
+ l = len(m.Context)
+ n += 1 + l + sovRaft(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovRaft(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozRaft(x uint64) (n int) {
+ return sovRaft(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Entry) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Entry: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Entry: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+ }
+ m.Type = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Type |= (EntryType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Term", wireType)
+ }
+ m.Term = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Term |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType)
+ }
+ m.Index = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Index |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *SnapshotMetadata) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: SnapshotMetadata: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: SnapshotMetadata: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ConfState", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.ConfState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType)
+ }
+ m.Index = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Index |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Term", wireType)
+ }
+ m.Term = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Term |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Snapshot) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Snapshot: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Message) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Message: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+ }
+ m.Type = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Type |= (MessageType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
+ }
+ m.To = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.To |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field From", wireType)
+ }
+ m.From = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.From |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Term", wireType)
+ }
+ m.Term = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Term |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 5:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field LogTerm", wireType)
+ }
+ m.LogTerm = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.LogTerm |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 6:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType)
+ }
+ m.Index = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Index |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 7:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Entries", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Entries = append(m.Entries, Entry{})
+ if err := m.Entries[len(m.Entries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 8:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType)
+ }
+ m.Commit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Commit |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 9:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Snapshot", wireType)
+ }
+ var msglen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ msglen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if msglen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + msglen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+ return err
+ }
+ iNdEx = postIndex
+ case 10:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Reject", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Reject = bool(v != 0)
+ case 11:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field RejectHint", wireType)
+ }
+ m.RejectHint = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.RejectHint |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 12:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Context", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Context = append(m.Context[:0], dAtA[iNdEx:postIndex]...)
+ if m.Context == nil {
+ m.Context = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *HardState) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: HardState: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: HardState: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Term", wireType)
+ }
+ m.Term = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Term |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType)
+ }
+ m.Vote = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Vote |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType)
+ }
+ m.Commit = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Commit |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ConfState) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ConfState: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ConfState: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType == 0 {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Nodes = append(m.Nodes, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ for iNdEx < postIndex {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Nodes = append(m.Nodes, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field Nodes", wireType)
+ }
+ case 2:
+ if wireType == 0 {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Learners = append(m.Learners, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ for iNdEx < postIndex {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Learners = append(m.Learners, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field Learners", wireType)
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *ConfChange) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: ConfChange: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: ConfChange: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
+ }
+ m.ID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.ID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+ }
+ m.Type = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Type |= (ConfChangeType(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field NodeID", wireType)
+ }
+ m.NodeID = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.NodeID |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 4:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Context", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRaft
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Context = append(m.Context[:0], dAtA[iNdEx:postIndex]...)
+ if m.Context == nil {
+ m.Context = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRaft(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRaft
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipRaft(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthRaft
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRaft
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipRaft(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthRaft = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowRaft = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("raft.proto", fileDescriptorRaft) }
+
+var fileDescriptorRaft = []byte{
+ // 815 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x54, 0xcd, 0x6e, 0x23, 0x45,
+ 0x10, 0xf6, 0x8c, 0xc7, 0x7f, 0x35, 0x8e, 0xd3, 0xa9, 0x35, 0xa8, 0x15, 0x45, 0xc6, 0xb2, 0x38,
+ 0x58, 0x41, 0x1b, 0x20, 0x07, 0x0e, 0x48, 0x1c, 0x36, 0x09, 0x52, 0x22, 0xad, 0xa3, 0xc5, 0x9b,
+ 0xe5, 0x80, 0x84, 0x50, 0xc7, 0x53, 0x9e, 0x18, 0x32, 0xd3, 0xa3, 0x9e, 0xf6, 0xb2, 0xb9, 0x20,
+ 0x1e, 0x80, 0x07, 0xe0, 0xc2, 0xfb, 0xe4, 0xb8, 0x12, 0x77, 0xc4, 0x86, 0x17, 0x41, 0xdd, 0xd3,
+ 0x63, 0xcf, 0x24, 0xb7, 0xae, 0xef, 0xab, 0xae, 0xfa, 0xea, 0xeb, 0x9a, 0x01, 0x50, 0x62, 0xa9,
+ 0x8f, 0x32, 0x25, 0xb5, 0xc4, 0xb6, 0x39, 0x67, 0xd7, 0xfb, 0xc3, 0x58, 0xc6, 0xd2, 0x42, 0x9f,
+ 0x9b, 0x53, 0xc1, 0x4e, 0x7e, 0x83, 0xd6, 0xb7, 0xa9, 0x56, 0x77, 0xf8, 0x19, 0x04, 0x57, 0x77,
+ 0x19, 0x71, 0x6f, 0xec, 0x4d, 0x07, 0xc7, 0x7b, 0x47, 0xc5, 0xad, 0x23, 0x4b, 0x1a, 0xe2, 0x24,
+ 0xb8, 0xff, 0xe7, 0x93, 0xc6, 0xdc, 0x26, 0x21, 0x87, 0xe0, 0x8a, 0x54, 0xc2, 0xfd, 0xb1, 0x37,
+ 0x0d, 0x36, 0x0c, 0xa9, 0x04, 0xf7, 0xa1, 0x75, 0x91, 0x46, 0xf4, 0x8e, 0x37, 0x2b, 0x54, 0x01,
+ 0x21, 0x42, 0x70, 0x26, 0xb4, 0xe0, 0xc1, 0xd8, 0x9b, 0xf6, 0xe7, 0xf6, 0x3c, 0xf9, 0xdd, 0x03,
+ 0xf6, 0x3a, 0x15, 0x59, 0x7e, 0x23, 0xf5, 0x8c, 0xb4, 0x88, 0x84, 0x16, 0xf8, 0x15, 0xc0, 0x42,
+ 0xa6, 0xcb, 0x9f, 0x72, 0x2d, 0x74, 0xa1, 0x28, 0xdc, 0x2a, 0x3a, 0x95, 0xe9, 0xf2, 0xb5, 0x21,
+ 0x5c, 0xf1, 0xde, 0xa2, 0x04, 0x4c, 0xf3, 0x95, 0x6d, 0x5e, 0xd5, 0x55, 0x40, 0x46, 0xb2, 0x36,
+ 0x92, 0xab, 0xba, 0x2c, 0x32, 0xf9, 0x01, 0xba, 0xa5, 0x02, 0x23, 0xd1, 0x28, 0xb0, 0x3d, 0xfb,
+ 0x73, 0x7b, 0xc6, 0xaf, 0xa1, 0x9b, 0x38, 0x65, 0xb6, 0x70, 0x78, 0xcc, 0x4b, 0x2d, 0x8f, 0x95,
+ 0xbb, 0xba, 0x9b, 0xfc, 0xc9, 0x5f, 0x4d, 0xe8, 0xcc, 0x28, 0xcf, 0x45, 0x4c, 0xf8, 0x1c, 0x02,
+ 0xbd, 0x75, 0xf8, 0x59, 0x59, 0xc3, 0xd1, 0x55, 0x8f, 0x4d, 0x1a, 0x0e, 0xc1, 0xd7, 0xb2, 0x36,
+ 0x89, 0xaf, 0xa5, 0x19, 0x63, 0xa9, 0xe4, 0xa3, 0x31, 0x0c, 0xb2, 0x19, 0x30, 0x78, 0x3c, 0x20,
+ 0x8e, 0xa0, 0x73, 0x2b, 0x63, 0xfb, 0x60, 0xad, 0x0a, 0x59, 0x82, 0x5b, 0xdb, 0xda, 0x4f, 0x6d,
+ 0x7b, 0x0e, 0x1d, 0x4a, 0xb5, 0x5a, 0x51, 0xce, 0x3b, 0xe3, 0xe6, 0x34, 0x3c, 0xde, 0xa9, 0x6d,
+ 0x46, 0x59, 0xca, 0xe5, 0xe0, 0x01, 0xb4, 0x17, 0x32, 0x49, 0x56, 0x9a, 0x77, 0x2b, 0xb5, 0x1c,
+ 0x86, 0xc7, 0xd0, 0xcd, 0x9d, 0x63, 0xbc, 0x67, 0x9d, 0x64, 0x8f, 0x9d, 0x2c, 0x1d, 0x2c, 0xf3,
+ 0x4c, 0x45, 0x45, 0x3f, 0xd3, 0x42, 0x73, 0x18, 0x7b, 0xd3, 0x6e, 0x59, 0xb1, 0xc0, 0xf0, 0x53,
+ 0x80, 0xe2, 0x74, 0xbe, 0x4a, 0x35, 0x0f, 0x2b, 0x3d, 0x2b, 0x38, 0x72, 0xe8, 0x2c, 0x64, 0xaa,
+ 0xe9, 0x9d, 0xe6, 0x7d, 0xfb, 0xb0, 0x65, 0x38, 0xf9, 0x11, 0x7a, 0xe7, 0x42, 0x45, 0xc5, 0xfa,
+ 0x94, 0x0e, 0x7a, 0x4f, 0x1c, 0xe4, 0x10, 0xbc, 0x95, 0x9a, 0xea, 0xfb, 0x6e, 0x90, 0xca, 0xc0,
+ 0xcd, 0xa7, 0x03, 0x4f, 0xbe, 0x81, 0xde, 0x66, 0x5d, 0x71, 0x08, 0xad, 0x54, 0x46, 0x94, 0x73,
+ 0x6f, 0xdc, 0x9c, 0x06, 0xf3, 0x22, 0xc0, 0x7d, 0xe8, 0xde, 0x92, 0x50, 0x29, 0xa9, 0x9c, 0xfb,
+ 0x96, 0xd8, 0xc4, 0x93, 0x3f, 0x3c, 0x00, 0x73, 0xff, 0xf4, 0x46, 0xa4, 0xb1, 0xdd, 0x88, 0x8b,
+ 0xb3, 0x9a, 0x3a, 0xff, 0xe2, 0x0c, 0xbf, 0x70, 0x1f, 0xae, 0x6f, 0xd7, 0xea, 0xe3, 0xea, 0x67,
+ 0x52, 0xdc, 0x7b, 0xf2, 0xf5, 0x1e, 0x40, 0xfb, 0x52, 0x46, 0x74, 0x71, 0x56, 0xd7, 0x5c, 0x60,
+ 0xc6, 0xac, 0x53, 0x67, 0x56, 0xf1, 0xa1, 0x96, 0xe1, 0xe1, 0x97, 0xd0, 0xdb, 0xfc, 0x0e, 0x70,
+ 0x17, 0x42, 0x1b, 0x5c, 0x4a, 0x95, 0x88, 0x5b, 0xd6, 0xc0, 0x67, 0xb0, 0x6b, 0x81, 0x6d, 0x63,
+ 0xe6, 0x1d, 0xfe, 0xed, 0x43, 0x58, 0x59, 0x70, 0x04, 0x68, 0xcf, 0xf2, 0xf8, 0x7c, 0x9d, 0xb1,
+ 0x06, 0x86, 0xd0, 0x99, 0xe5, 0xf1, 0x09, 0x09, 0xcd, 0x3c, 0x17, 0xbc, 0x52, 0x32, 0x63, 0xbe,
+ 0xcb, 0x7a, 0x91, 0x65, 0xac, 0x89, 0x03, 0x80, 0xe2, 0x3c, 0xa7, 0x3c, 0x63, 0x81, 0x4b, 0xfc,
+ 0x5e, 0x6a, 0x62, 0x2d, 0x23, 0xc2, 0x05, 0x96, 0x6d, 0x3b, 0xd6, 0x2c, 0x13, 0xeb, 0x20, 0x83,
+ 0xbe, 0x69, 0x46, 0x42, 0xe9, 0x6b, 0xd3, 0xa5, 0x8b, 0x43, 0x60, 0x55, 0xc4, 0x5e, 0xea, 0x21,
+ 0xc2, 0x60, 0x96, 0xc7, 0x6f, 0x52, 0x45, 0x62, 0x71, 0x23, 0xae, 0x6f, 0x89, 0x01, 0xee, 0xc1,
+ 0x8e, 0x2b, 0x64, 0x1e, 0x6f, 0x9d, 0xb3, 0xd0, 0xa5, 0x9d, 0xde, 0xd0, 0xe2, 0x97, 0xef, 0xd6,
+ 0x52, 0xad, 0x13, 0xd6, 0xc7, 0x8f, 0x60, 0x6f, 0x96, 0xc7, 0x57, 0x4a, 0xa4, 0xf9, 0x92, 0xd4,
+ 0x4b, 0x12, 0x11, 0x29, 0xb6, 0xe3, 0x6e, 0x5f, 0xad, 0x12, 0x92, 0x6b, 0x7d, 0x29, 0x7f, 0x65,
+ 0x03, 0x27, 0x66, 0x4e, 0x22, 0xb2, 0x3f, 0x43, 0xb6, 0xeb, 0xc4, 0x6c, 0x10, 0x2b, 0x86, 0xb9,
+ 0x79, 0x5f, 0x29, 0xb2, 0x23, 0xee, 0xb9, 0xae, 0x2e, 0xb6, 0x39, 0x78, 0x78, 0x07, 0x83, 0xfa,
+ 0xf3, 0x1a, 0x1d, 0x5b, 0xe4, 0x45, 0x14, 0x99, 0xb7, 0x64, 0x0d, 0xe4, 0x30, 0xdc, 0xc2, 0x73,
+ 0x4a, 0xe4, 0x5b, 0xb2, 0x8c, 0x57, 0x67, 0xde, 0x64, 0x91, 0xd0, 0x05, 0xe3, 0xe3, 0x01, 0xf0,
+ 0x5a, 0xa9, 0x97, 0xc5, 0x36, 0x5a, 0xb6, 0x79, 0xc2, 0xef, 0x3f, 0x8c, 0x1a, 0xef, 0x3f, 0x8c,
+ 0x1a, 0xf7, 0x0f, 0x23, 0xef, 0xfd, 0xc3, 0xc8, 0xfb, 0xf7, 0x61, 0xe4, 0xfd, 0xf9, 0xdf, 0xa8,
+ 0xf1, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x86, 0x52, 0x5b, 0xe0, 0x74, 0x06, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/raft/rawnode.go b/vendor/github.com/coreos/etcd/raft/rawnode.go
new file mode 100644
index 00000000..925cb851
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/rawnode.go
@@ -0,0 +1,266 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "errors"
+
+ pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+// ErrStepLocalMsg is returned when try to step a local raft message
+var ErrStepLocalMsg = errors.New("raft: cannot step raft local message")
+
+// ErrStepPeerNotFound is returned when try to step a response message
+// but there is no peer found in raft.prs for that node.
+var ErrStepPeerNotFound = errors.New("raft: cannot step as peer not found")
+
+// RawNode is a thread-unsafe Node.
+// The methods of this struct correspond to the methods of Node and are described
+// more fully there.
+type RawNode struct {
+ raft *raft
+ prevSoftSt *SoftState
+ prevHardSt pb.HardState
+}
+
+func (rn *RawNode) newReady() Ready {
+ return newReady(rn.raft, rn.prevSoftSt, rn.prevHardSt)
+}
+
+func (rn *RawNode) commitReady(rd Ready) {
+ if rd.SoftState != nil {
+ rn.prevSoftSt = rd.SoftState
+ }
+ if !IsEmptyHardState(rd.HardState) {
+ rn.prevHardSt = rd.HardState
+ }
+ if rn.prevHardSt.Commit != 0 {
+ // In most cases, prevHardSt and rd.HardState will be the same
+ // because when there are new entries to apply we just sent a
+ // HardState with an updated Commit value. However, on initial
+ // startup the two are different because we don't send a HardState
+ // until something changes, but we do send any un-applied but
+ // committed entries (and previously-committed entries may be
+ // incorporated into the snapshot, even if rd.CommittedEntries is
+ // empty). Therefore we mark all committed entries as applied
+ // whether they were included in rd.HardState or not.
+ rn.raft.raftLog.appliedTo(rn.prevHardSt.Commit)
+ }
+ if len(rd.Entries) > 0 {
+ e := rd.Entries[len(rd.Entries)-1]
+ rn.raft.raftLog.stableTo(e.Index, e.Term)
+ }
+ if !IsEmptySnap(rd.Snapshot) {
+ rn.raft.raftLog.stableSnapTo(rd.Snapshot.Metadata.Index)
+ }
+ if len(rd.ReadStates) != 0 {
+ rn.raft.readStates = nil
+ }
+}
+
+// NewRawNode returns a new RawNode given configuration and a list of raft peers.
+func NewRawNode(config *Config, peers []Peer) (*RawNode, error) {
+ if config.ID == 0 {
+ panic("config.ID must not be zero")
+ }
+ r := newRaft(config)
+ rn := &RawNode{
+ raft: r,
+ }
+ lastIndex, err := config.Storage.LastIndex()
+ if err != nil {
+ panic(err) // TODO(bdarnell)
+ }
+ // If the log is empty, this is a new RawNode (like StartNode); otherwise it's
+ // restoring an existing RawNode (like RestartNode).
+ // TODO(bdarnell): rethink RawNode initialization and whether the application needs
+ // to be able to tell us when it expects the RawNode to exist.
+ if lastIndex == 0 {
+ r.becomeFollower(1, None)
+ ents := make([]pb.Entry, len(peers))
+ for i, peer := range peers {
+ cc := pb.ConfChange{Type: pb.ConfChangeAddNode, NodeID: peer.ID, Context: peer.Context}
+ data, err := cc.Marshal()
+ if err != nil {
+ panic("unexpected marshal error")
+ }
+
+ ents[i] = pb.Entry{Type: pb.EntryConfChange, Term: 1, Index: uint64(i + 1), Data: data}
+ }
+ r.raftLog.append(ents...)
+ r.raftLog.committed = uint64(len(ents))
+ for _, peer := range peers {
+ r.addNode(peer.ID)
+ }
+ }
+
+ // Set the initial hard and soft states after performing all initialization.
+ rn.prevSoftSt = r.softState()
+ if lastIndex == 0 {
+ rn.prevHardSt = emptyState
+ } else {
+ rn.prevHardSt = r.hardState()
+ }
+
+ return rn, nil
+}
+
+// Tick advances the internal logical clock by a single tick.
+func (rn *RawNode) Tick() {
+ rn.raft.tick()
+}
+
+// TickQuiesced advances the internal logical clock by a single tick without
+// performing any other state machine processing. It allows the caller to avoid
+// periodic heartbeats and elections when all of the peers in a Raft group are
+// known to be at the same state. Expected usage is to periodically invoke Tick
+// or TickQuiesced depending on whether the group is "active" or "quiesced".
+//
+// WARNING: Be very careful about using this method as it subverts the Raft
+// state machine. You should probably be using Tick instead.
+func (rn *RawNode) TickQuiesced() {
+ rn.raft.electionElapsed++
+}
+
+// Campaign causes this RawNode to transition to candidate state.
+func (rn *RawNode) Campaign() error {
+ return rn.raft.Step(pb.Message{
+ Type: pb.MsgHup,
+ })
+}
+
+// Propose proposes data be appended to the raft log.
+func (rn *RawNode) Propose(data []byte) error {
+ return rn.raft.Step(pb.Message{
+ Type: pb.MsgProp,
+ From: rn.raft.id,
+ Entries: []pb.Entry{
+ {Data: data},
+ }})
+}
+
+// ProposeConfChange proposes a config change.
+func (rn *RawNode) ProposeConfChange(cc pb.ConfChange) error {
+ data, err := cc.Marshal()
+ if err != nil {
+ return err
+ }
+ return rn.raft.Step(pb.Message{
+ Type: pb.MsgProp,
+ Entries: []pb.Entry{
+ {Type: pb.EntryConfChange, Data: data},
+ },
+ })
+}
+
+// ApplyConfChange applies a config change to the local node.
+func (rn *RawNode) ApplyConfChange(cc pb.ConfChange) *pb.ConfState {
+ if cc.NodeID == None {
+ rn.raft.resetPendingConf()
+ return &pb.ConfState{Nodes: rn.raft.nodes()}
+ }
+ switch cc.Type {
+ case pb.ConfChangeAddNode:
+ rn.raft.addNode(cc.NodeID)
+ case pb.ConfChangeAddLearnerNode:
+ rn.raft.addLearner(cc.NodeID)
+ case pb.ConfChangeRemoveNode:
+ rn.raft.removeNode(cc.NodeID)
+ case pb.ConfChangeUpdateNode:
+ rn.raft.resetPendingConf()
+ default:
+ panic("unexpected conf type")
+ }
+ return &pb.ConfState{Nodes: rn.raft.nodes()}
+}
+
+// Step advances the state machine using the given message.
+func (rn *RawNode) Step(m pb.Message) error {
+ // ignore unexpected local messages receiving over network
+ if IsLocalMsg(m.Type) {
+ return ErrStepLocalMsg
+ }
+ if pr := rn.raft.getProgress(m.From); pr != nil || !IsResponseMsg(m.Type) {
+ return rn.raft.Step(m)
+ }
+ return ErrStepPeerNotFound
+}
+
+// Ready returns the current point-in-time state of this RawNode.
+func (rn *RawNode) Ready() Ready {
+ rd := rn.newReady()
+ rn.raft.msgs = nil
+ return rd
+}
+
+// HasReady called when RawNode user need to check if any Ready pending.
+// Checking logic in this method should be consistent with Ready.containsUpdates().
+func (rn *RawNode) HasReady() bool {
+ r := rn.raft
+ if !r.softState().equal(rn.prevSoftSt) {
+ return true
+ }
+ if hardSt := r.hardState(); !IsEmptyHardState(hardSt) && !isHardStateEqual(hardSt, rn.prevHardSt) {
+ return true
+ }
+ if r.raftLog.unstable.snapshot != nil && !IsEmptySnap(*r.raftLog.unstable.snapshot) {
+ return true
+ }
+ if len(r.msgs) > 0 || len(r.raftLog.unstableEntries()) > 0 || r.raftLog.hasNextEnts() {
+ return true
+ }
+ if len(r.readStates) != 0 {
+ return true
+ }
+ return false
+}
+
+// Advance notifies the RawNode that the application has applied and saved progress in the
+// last Ready results.
+func (rn *RawNode) Advance(rd Ready) {
+ rn.commitReady(rd)
+}
+
+// Status returns the current status of the given group.
+func (rn *RawNode) Status() *Status {
+ status := getStatus(rn.raft)
+ return &status
+}
+
+// ReportUnreachable reports the given node is not reachable for the last send.
+func (rn *RawNode) ReportUnreachable(id uint64) {
+ _ = rn.raft.Step(pb.Message{Type: pb.MsgUnreachable, From: id})
+}
+
+// ReportSnapshot reports the status of the sent snapshot.
+func (rn *RawNode) ReportSnapshot(id uint64, status SnapshotStatus) {
+ rej := status == SnapshotFailure
+
+ _ = rn.raft.Step(pb.Message{Type: pb.MsgSnapStatus, From: id, Reject: rej})
+}
+
+// TransferLeader tries to transfer leadership to the given transferee.
+func (rn *RawNode) TransferLeader(transferee uint64) {
+ _ = rn.raft.Step(pb.Message{Type: pb.MsgTransferLeader, From: transferee})
+}
+
+// ReadIndex requests a read state. The read state will be set in ready.
+// Read State has a read index. Once the application advances further than the read
+// index, any linearizable read requests issued before the read request can be
+// processed safely. The read state will have the same rctx attached.
+func (rn *RawNode) ReadIndex(rctx []byte) {
+ _ = rn.raft.Step(pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}})
+}
diff --git a/vendor/github.com/coreos/etcd/raft/read_only.go b/vendor/github.com/coreos/etcd/raft/read_only.go
new file mode 100644
index 00000000..ae746fa7
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/read_only.go
@@ -0,0 +1,118 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import pb "github.com/coreos/etcd/raft/raftpb"
+
+// ReadState provides state for read only query.
+// It's caller's responsibility to call ReadIndex first before getting
+// this state from ready, it's also caller's duty to differentiate if this
+// state is what it requests through RequestCtx, eg. given a unique id as
+// RequestCtx
+type ReadState struct {
+ Index uint64
+ RequestCtx []byte
+}
+
+type readIndexStatus struct {
+ req pb.Message
+ index uint64
+ acks map[uint64]struct{}
+}
+
+type readOnly struct {
+ option ReadOnlyOption
+ pendingReadIndex map[string]*readIndexStatus
+ readIndexQueue []string
+}
+
+func newReadOnly(option ReadOnlyOption) *readOnly {
+ return &readOnly{
+ option: option,
+ pendingReadIndex: make(map[string]*readIndexStatus),
+ }
+}
+
+// addRequest adds a read only reuqest into readonly struct.
+// `index` is the commit index of the raft state machine when it received
+// the read only request.
+// `m` is the original read only request message from the local or remote node.
+func (ro *readOnly) addRequest(index uint64, m pb.Message) {
+ ctx := string(m.Entries[0].Data)
+ if _, ok := ro.pendingReadIndex[ctx]; ok {
+ return
+ }
+ ro.pendingReadIndex[ctx] = &readIndexStatus{index: index, req: m, acks: make(map[uint64]struct{})}
+ ro.readIndexQueue = append(ro.readIndexQueue, ctx)
+}
+
+// recvAck notifies the readonly struct that the raft state machine received
+// an acknowledgment of the heartbeat that attached with the read only request
+// context.
+func (ro *readOnly) recvAck(m pb.Message) int {
+ rs, ok := ro.pendingReadIndex[string(m.Context)]
+ if !ok {
+ return 0
+ }
+
+ rs.acks[m.From] = struct{}{}
+ // add one to include an ack from local node
+ return len(rs.acks) + 1
+}
+
+// advance advances the read only request queue kept by the readonly struct.
+// It dequeues the requests until it finds the read only request that has
+// the same context as the given `m`.
+func (ro *readOnly) advance(m pb.Message) []*readIndexStatus {
+ var (
+ i int
+ found bool
+ )
+
+ ctx := string(m.Context)
+ rss := []*readIndexStatus{}
+
+ for _, okctx := range ro.readIndexQueue {
+ i++
+ rs, ok := ro.pendingReadIndex[okctx]
+ if !ok {
+ panic("cannot find corresponding read state from pending map")
+ }
+ rss = append(rss, rs)
+ if okctx == ctx {
+ found = true
+ break
+ }
+ }
+
+ if found {
+ ro.readIndexQueue = ro.readIndexQueue[i:]
+ for _, rs := range rss {
+ delete(ro.pendingReadIndex, string(rs.req.Entries[0].Data))
+ }
+ return rss
+ }
+
+ return nil
+}
+
+// lastPendingRequestCtx returns the context of the last pending read only
+// request in readonly struct.
+func (ro *readOnly) lastPendingRequestCtx() string {
+ if len(ro.readIndexQueue) == 0 {
+ return ""
+ }
+ return ro.readIndexQueue[len(ro.readIndexQueue)-1]
+}
diff --git a/vendor/github.com/coreos/etcd/raft/status.go b/vendor/github.com/coreos/etcd/raft/status.go
new file mode 100644
index 00000000..f4d3d86a
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/status.go
@@ -0,0 +1,88 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "fmt"
+
+ pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+type Status struct {
+ ID uint64
+
+ pb.HardState
+ SoftState
+
+ Applied uint64
+ Progress map[uint64]Progress
+
+ LeadTransferee uint64
+}
+
+// getStatus gets a copy of the current raft status.
+func getStatus(r *raft) Status {
+ s := Status{
+ ID: r.id,
+ LeadTransferee: r.leadTransferee,
+ }
+
+ s.HardState = r.hardState()
+ s.SoftState = *r.softState()
+
+ s.Applied = r.raftLog.applied
+
+ if s.RaftState == StateLeader {
+ s.Progress = make(map[uint64]Progress)
+ for id, p := range r.prs {
+ s.Progress[id] = *p
+ }
+
+ for id, p := range r.learnerPrs {
+ s.Progress[id] = *p
+ }
+ }
+
+ return s
+}
+
+// MarshalJSON translates the raft status into JSON.
+// TODO: try to simplify this by introducing ID type into raft
+func (s Status) MarshalJSON() ([]byte, error) {
+ j := fmt.Sprintf(`{"id":"%x","term":%d,"vote":"%x","commit":%d,"lead":"%x","raftState":%q,"applied":%d,"progress":{`,
+ s.ID, s.Term, s.Vote, s.Commit, s.Lead, s.RaftState, s.Applied)
+
+ if len(s.Progress) == 0 {
+ j += "},"
+ } else {
+ for k, v := range s.Progress {
+ subj := fmt.Sprintf(`"%x":{"match":%d,"next":%d,"state":%q},`, k, v.Match, v.Next, v.State)
+ j += subj
+ }
+ // remove the trailing ","
+ j = j[:len(j)-1] + "},"
+ }
+
+ j += fmt.Sprintf(`"leadtransferee":"%x"}`, s.LeadTransferee)
+ return []byte(j), nil
+}
+
+func (s Status) String() string {
+ b, err := s.MarshalJSON()
+ if err != nil {
+ raftLogger.Panicf("unexpected error: %v", err)
+ }
+ return string(b)
+}
diff --git a/vendor/github.com/coreos/etcd/raft/storage.go b/vendor/github.com/coreos/etcd/raft/storage.go
new file mode 100644
index 00000000..69c3a7d9
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/storage.go
@@ -0,0 +1,271 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "errors"
+ "sync"
+
+ pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+// ErrCompacted is returned by Storage.Entries/Compact when a requested
+// index is unavailable because it predates the last snapshot.
+var ErrCompacted = errors.New("requested index is unavailable due to compaction")
+
+// ErrSnapOutOfDate is returned by Storage.CreateSnapshot when a requested
+// index is older than the existing snapshot.
+var ErrSnapOutOfDate = errors.New("requested index is older than the existing snapshot")
+
+// ErrUnavailable is returned by Storage interface when the requested log entries
+// are unavailable.
+var ErrUnavailable = errors.New("requested entry at index is unavailable")
+
+// ErrSnapshotTemporarilyUnavailable is returned by the Storage interface when the required
+// snapshot is temporarily unavailable.
+var ErrSnapshotTemporarilyUnavailable = errors.New("snapshot is temporarily unavailable")
+
+// Storage is an interface that may be implemented by the application
+// to retrieve log entries from storage.
+//
+// If any Storage method returns an error, the raft instance will
+// become inoperable and refuse to participate in elections; the
+// application is responsible for cleanup and recovery in this case.
+type Storage interface {
+ // InitialState returns the saved HardState and ConfState information.
+ InitialState() (pb.HardState, pb.ConfState, error)
+ // Entries returns a slice of log entries in the range [lo,hi).
+ // MaxSize limits the total size of the log entries returned, but
+ // Entries returns at least one entry if any.
+ Entries(lo, hi, maxSize uint64) ([]pb.Entry, error)
+ // Term returns the term of entry i, which must be in the range
+ // [FirstIndex()-1, LastIndex()]. The term of the entry before
+ // FirstIndex is retained for matching purposes even though the
+ // rest of that entry may not be available.
+ Term(i uint64) (uint64, error)
+ // LastIndex returns the index of the last entry in the log.
+ LastIndex() (uint64, error)
+ // FirstIndex returns the index of the first log entry that is
+ // possibly available via Entries (older entries have been incorporated
+ // into the latest Snapshot; if storage only contains the dummy entry the
+ // first log entry is not available).
+ FirstIndex() (uint64, error)
+ // Snapshot returns the most recent snapshot.
+ // If snapshot is temporarily unavailable, it should return ErrSnapshotTemporarilyUnavailable,
+ // so raft state machine could know that Storage needs some time to prepare
+ // snapshot and call Snapshot later.
+ Snapshot() (pb.Snapshot, error)
+}
+
+// MemoryStorage implements the Storage interface backed by an
+// in-memory array.
+type MemoryStorage struct {
+ // Protects access to all fields. Most methods of MemoryStorage are
+ // run on the raft goroutine, but Append() is run on an application
+ // goroutine.
+ sync.Mutex
+
+ hardState pb.HardState
+ snapshot pb.Snapshot
+ // ents[i] has raft log position i+snapshot.Metadata.Index
+ ents []pb.Entry
+}
+
+// NewMemoryStorage creates an empty MemoryStorage.
+func NewMemoryStorage() *MemoryStorage {
+ return &MemoryStorage{
+ // When starting from scratch populate the list with a dummy entry at term zero.
+ ents: make([]pb.Entry, 1),
+ }
+}
+
+// InitialState implements the Storage interface.
+func (ms *MemoryStorage) InitialState() (pb.HardState, pb.ConfState, error) {
+ return ms.hardState, ms.snapshot.Metadata.ConfState, nil
+}
+
+// SetHardState saves the current HardState.
+func (ms *MemoryStorage) SetHardState(st pb.HardState) error {
+ ms.Lock()
+ defer ms.Unlock()
+ ms.hardState = st
+ return nil
+}
+
+// Entries implements the Storage interface.
+func (ms *MemoryStorage) Entries(lo, hi, maxSize uint64) ([]pb.Entry, error) {
+ ms.Lock()
+ defer ms.Unlock()
+ offset := ms.ents[0].Index
+ if lo <= offset {
+ return nil, ErrCompacted
+ }
+ if hi > ms.lastIndex()+1 {
+ raftLogger.Panicf("entries' hi(%d) is out of bound lastindex(%d)", hi, ms.lastIndex())
+ }
+ // only contains dummy entries.
+ if len(ms.ents) == 1 {
+ return nil, ErrUnavailable
+ }
+
+ ents := ms.ents[lo-offset : hi-offset]
+ return limitSize(ents, maxSize), nil
+}
+
+// Term implements the Storage interface.
+func (ms *MemoryStorage) Term(i uint64) (uint64, error) {
+ ms.Lock()
+ defer ms.Unlock()
+ offset := ms.ents[0].Index
+ if i < offset {
+ return 0, ErrCompacted
+ }
+ if int(i-offset) >= len(ms.ents) {
+ return 0, ErrUnavailable
+ }
+ return ms.ents[i-offset].Term, nil
+}
+
+// LastIndex implements the Storage interface.
+func (ms *MemoryStorage) LastIndex() (uint64, error) {
+ ms.Lock()
+ defer ms.Unlock()
+ return ms.lastIndex(), nil
+}
+
+func (ms *MemoryStorage) lastIndex() uint64 {
+ return ms.ents[0].Index + uint64(len(ms.ents)) - 1
+}
+
+// FirstIndex implements the Storage interface.
+func (ms *MemoryStorage) FirstIndex() (uint64, error) {
+ ms.Lock()
+ defer ms.Unlock()
+ return ms.firstIndex(), nil
+}
+
+func (ms *MemoryStorage) firstIndex() uint64 {
+ return ms.ents[0].Index + 1
+}
+
+// Snapshot implements the Storage interface.
+func (ms *MemoryStorage) Snapshot() (pb.Snapshot, error) {
+ ms.Lock()
+ defer ms.Unlock()
+ return ms.snapshot, nil
+}
+
+// ApplySnapshot overwrites the contents of this Storage object with
+// those of the given snapshot.
+func (ms *MemoryStorage) ApplySnapshot(snap pb.Snapshot) error {
+ ms.Lock()
+ defer ms.Unlock()
+
+ //handle check for old snapshot being applied
+ msIndex := ms.snapshot.Metadata.Index
+ snapIndex := snap.Metadata.Index
+ if msIndex >= snapIndex {
+ return ErrSnapOutOfDate
+ }
+
+ ms.snapshot = snap
+ ms.ents = []pb.Entry{{Term: snap.Metadata.Term, Index: snap.Metadata.Index}}
+ return nil
+}
+
+// CreateSnapshot makes a snapshot which can be retrieved with Snapshot() and
+// can be used to reconstruct the state at that point.
+// If any configuration changes have been made since the last compaction,
+// the result of the last ApplyConfChange must be passed in.
+func (ms *MemoryStorage) CreateSnapshot(i uint64, cs *pb.ConfState, data []byte) (pb.Snapshot, error) {
+ ms.Lock()
+ defer ms.Unlock()
+ if i <= ms.snapshot.Metadata.Index {
+ return pb.Snapshot{}, ErrSnapOutOfDate
+ }
+
+ offset := ms.ents[0].Index
+ if i > ms.lastIndex() {
+ raftLogger.Panicf("snapshot %d is out of bound lastindex(%d)", i, ms.lastIndex())
+ }
+
+ ms.snapshot.Metadata.Index = i
+ ms.snapshot.Metadata.Term = ms.ents[i-offset].Term
+ if cs != nil {
+ ms.snapshot.Metadata.ConfState = *cs
+ }
+ ms.snapshot.Data = data
+ return ms.snapshot, nil
+}
+
+// Compact discards all log entries prior to compactIndex.
+// It is the application's responsibility to not attempt to compact an index
+// greater than raftLog.applied.
+func (ms *MemoryStorage) Compact(compactIndex uint64) error {
+ ms.Lock()
+ defer ms.Unlock()
+ offset := ms.ents[0].Index
+ if compactIndex <= offset {
+ return ErrCompacted
+ }
+ if compactIndex > ms.lastIndex() {
+ raftLogger.Panicf("compact %d is out of bound lastindex(%d)", compactIndex, ms.lastIndex())
+ }
+
+ i := compactIndex - offset
+ ents := make([]pb.Entry, 1, 1+uint64(len(ms.ents))-i)
+ ents[0].Index = ms.ents[i].Index
+ ents[0].Term = ms.ents[i].Term
+ ents = append(ents, ms.ents[i+1:]...)
+ ms.ents = ents
+ return nil
+}
+
+// Append the new entries to storage.
+// TODO (xiangli): ensure the entries are continuous and
+// entries[0].Index > ms.entries[0].Index
+func (ms *MemoryStorage) Append(entries []pb.Entry) error {
+ if len(entries) == 0 {
+ return nil
+ }
+
+ ms.Lock()
+ defer ms.Unlock()
+
+ first := ms.firstIndex()
+ last := entries[0].Index + uint64(len(entries)) - 1
+
+ // shortcut if there is no new entry.
+ if last < first {
+ return nil
+ }
+ // truncate compacted entries
+ if first > entries[0].Index {
+ entries = entries[first-entries[0].Index:]
+ }
+
+ offset := entries[0].Index - ms.ents[0].Index
+ switch {
+ case uint64(len(ms.ents)) > offset:
+ ms.ents = append([]pb.Entry{}, ms.ents[:offset]...)
+ ms.ents = append(ms.ents, entries...)
+ case uint64(len(ms.ents)) == offset:
+ ms.ents = append(ms.ents, entries...)
+ default:
+ raftLogger.Panicf("missing log entry [last: %d, append at: %d]",
+ ms.lastIndex(), entries[0].Index)
+ }
+ return nil
+}
diff --git a/vendor/github.com/coreos/etcd/raft/util.go b/vendor/github.com/coreos/etcd/raft/util.go
new file mode 100644
index 00000000..f4141fe6
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/raft/util.go
@@ -0,0 +1,129 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raft
+
+import (
+ "bytes"
+ "fmt"
+
+ pb "github.com/coreos/etcd/raft/raftpb"
+)
+
+func (st StateType) MarshalJSON() ([]byte, error) {
+ return []byte(fmt.Sprintf("%q", st.String())), nil
+}
+
+// uint64Slice implements sort interface
+type uint64Slice []uint64
+
+func (p uint64Slice) Len() int { return len(p) }
+func (p uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
+func (p uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func min(a, b uint64) uint64 {
+ if a > b {
+ return b
+ }
+ return a
+}
+
+func max(a, b uint64) uint64 {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+func IsLocalMsg(msgt pb.MessageType) bool {
+ return msgt == pb.MsgHup || msgt == pb.MsgBeat || msgt == pb.MsgUnreachable ||
+ msgt == pb.MsgSnapStatus || msgt == pb.MsgCheckQuorum
+}
+
+func IsResponseMsg(msgt pb.MessageType) bool {
+ return msgt == pb.MsgAppResp || msgt == pb.MsgVoteResp || msgt == pb.MsgHeartbeatResp || msgt == pb.MsgUnreachable || msgt == pb.MsgPreVoteResp
+}
+
+// voteResponseType maps vote and prevote message types to their corresponding responses.
+func voteRespMsgType(msgt pb.MessageType) pb.MessageType {
+ switch msgt {
+ case pb.MsgVote:
+ return pb.MsgVoteResp
+ case pb.MsgPreVote:
+ return pb.MsgPreVoteResp
+ default:
+ panic(fmt.Sprintf("not a vote message: %s", msgt))
+ }
+}
+
+// EntryFormatter can be implemented by the application to provide human-readable formatting
+// of entry data. Nil is a valid EntryFormatter and will use a default format.
+type EntryFormatter func([]byte) string
+
+// DescribeMessage returns a concise human-readable description of a
+// Message for debugging.
+func DescribeMessage(m pb.Message, f EntryFormatter) string {
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "%x->%x %v Term:%d Log:%d/%d", m.From, m.To, m.Type, m.Term, m.LogTerm, m.Index)
+ if m.Reject {
+ fmt.Fprintf(&buf, " Rejected")
+ if m.RejectHint != 0 {
+ fmt.Fprintf(&buf, "(Hint:%d)", m.RejectHint)
+ }
+ }
+ if m.Commit != 0 {
+ fmt.Fprintf(&buf, " Commit:%d", m.Commit)
+ }
+ if len(m.Entries) > 0 {
+ fmt.Fprintf(&buf, " Entries:[")
+ for i, e := range m.Entries {
+ if i != 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(DescribeEntry(e, f))
+ }
+ fmt.Fprintf(&buf, "]")
+ }
+ if !IsEmptySnap(m.Snapshot) {
+ fmt.Fprintf(&buf, " Snapshot:%v", m.Snapshot)
+ }
+ return buf.String()
+}
+
+// DescribeEntry returns a concise human-readable description of an
+// Entry for debugging.
+func DescribeEntry(e pb.Entry, f EntryFormatter) string {
+ var formatted string
+ if e.Type == pb.EntryNormal && f != nil {
+ formatted = f(e.Data)
+ } else {
+ formatted = fmt.Sprintf("%q", e.Data)
+ }
+ return fmt.Sprintf("%d/%d %s %s", e.Term, e.Index, e.Type, formatted)
+}
+
+func limitSize(ents []pb.Entry, maxSize uint64) []pb.Entry {
+ if len(ents) == 0 {
+ return ents
+ }
+ size := ents[0].Size()
+ var limit int
+ for limit = 1; limit < len(ents); limit++ {
+ size += ents[limit].Size()
+ if uint64(size) > maxSize {
+ break
+ }
+ }
+ return ents[:limit]
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/coder.go b/vendor/github.com/coreos/etcd/rafthttp/coder.go
new file mode 100644
index 00000000..86ede972
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/coder.go
@@ -0,0 +1,27 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import "github.com/coreos/etcd/raft/raftpb"
+
+type encoder interface {
+ // encode encodes the given message to an output stream.
+ encode(m *raftpb.Message) error
+}
+
+type decoder interface {
+ // decode decodes the message from an input stream.
+ decode() (raftpb.Message, error)
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/doc.go b/vendor/github.com/coreos/etcd/rafthttp/doc.go
new file mode 100644
index 00000000..a9486a8b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package rafthttp implements HTTP transportation layer for etcd/raft pkg.
+package rafthttp
diff --git a/vendor/github.com/coreos/etcd/rafthttp/http.go b/vendor/github.com/coreos/etcd/rafthttp/http.go
new file mode 100644
index 00000000..cc89e171
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/http.go
@@ -0,0 +1,351 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "path"
+ "strings"
+
+ pioutil "github.com/coreos/etcd/pkg/ioutil"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/snap"
+ "github.com/coreos/etcd/version"
+)
+
+const (
+ // connReadLimitByte limits the number of bytes
+ // a single read can read out.
+ //
+ // 64KB should be large enough for not causing
+ // throughput bottleneck as well as small enough
+ // for not causing a read timeout.
+ connReadLimitByte = 64 * 1024
+)
+
+var (
+ RaftPrefix = "/raft"
+ ProbingPrefix = path.Join(RaftPrefix, "probing")
+ RaftStreamPrefix = path.Join(RaftPrefix, "stream")
+ RaftSnapshotPrefix = path.Join(RaftPrefix, "snapshot")
+
+ errIncompatibleVersion = errors.New("incompatible version")
+ errClusterIDMismatch = errors.New("cluster ID mismatch")
+)
+
+type peerGetter interface {
+ Get(id types.ID) Peer
+}
+
+type writerToResponse interface {
+ WriteTo(w http.ResponseWriter)
+}
+
+type pipelineHandler struct {
+ tr Transporter
+ r Raft
+ cid types.ID
+}
+
+// newPipelineHandler returns a handler for handling raft messages
+// from pipeline for RaftPrefix.
+//
+// The handler reads out the raft message from request body,
+// and forwards it to the given raft state machine for processing.
+func newPipelineHandler(tr Transporter, r Raft, cid types.ID) http.Handler {
+ return &pipelineHandler{
+ tr: tr,
+ r: r,
+ cid: cid,
+ }
+}
+
+func (h *pipelineHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "POST" {
+ w.Header().Set("Allow", "POST")
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ w.Header().Set("X-Etcd-Cluster-ID", h.cid.String())
+
+ if err := checkClusterCompatibilityFromHeader(r.Header, h.cid); err != nil {
+ http.Error(w, err.Error(), http.StatusPreconditionFailed)
+ return
+ }
+
+ addRemoteFromRequest(h.tr, r)
+
+ // Limit the data size that could be read from the request body, which ensures that read from
+ // connection will not time out accidentally due to possible blocking in underlying implementation.
+ limitedr := pioutil.NewLimitedBufferReader(r.Body, connReadLimitByte)
+ b, err := ioutil.ReadAll(limitedr)
+ if err != nil {
+ plog.Errorf("failed to read raft message (%v)", err)
+ http.Error(w, "error reading raft message", http.StatusBadRequest)
+ recvFailures.WithLabelValues(r.RemoteAddr).Inc()
+ return
+ }
+
+ var m raftpb.Message
+ if err := m.Unmarshal(b); err != nil {
+ plog.Errorf("failed to unmarshal raft message (%v)", err)
+ http.Error(w, "error unmarshaling raft message", http.StatusBadRequest)
+ recvFailures.WithLabelValues(r.RemoteAddr).Inc()
+ return
+ }
+
+ receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(len(b)))
+
+ if err := h.r.Process(context.TODO(), m); err != nil {
+ switch v := err.(type) {
+ case writerToResponse:
+ v.WriteTo(w)
+ default:
+ plog.Warningf("failed to process raft message (%v)", err)
+ http.Error(w, "error processing raft message", http.StatusInternalServerError)
+ w.(http.Flusher).Flush()
+ // disconnect the http stream
+ panic(err)
+ }
+ return
+ }
+
+ // Write StatusNoContent header after the message has been processed by
+ // raft, which facilitates the client to report MsgSnap status.
+ w.WriteHeader(http.StatusNoContent)
+}
+
+type snapshotHandler struct {
+ tr Transporter
+ r Raft
+ snapshotter *snap.Snapshotter
+ cid types.ID
+}
+
+func newSnapshotHandler(tr Transporter, r Raft, snapshotter *snap.Snapshotter, cid types.ID) http.Handler {
+ return &snapshotHandler{
+ tr: tr,
+ r: r,
+ snapshotter: snapshotter,
+ cid: cid,
+ }
+}
+
+// ServeHTTP serves HTTP request to receive and process snapshot message.
+//
+// If request sender dies without closing underlying TCP connection,
+// the handler will keep waiting for the request body until TCP keepalive
+// finds out that the connection is broken after several minutes.
+// This is acceptable because
+// 1. snapshot messages sent through other TCP connections could still be
+// received and processed.
+// 2. this case should happen rarely, so no further optimization is done.
+func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "POST" {
+ w.Header().Set("Allow", "POST")
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ w.Header().Set("X-Etcd-Cluster-ID", h.cid.String())
+
+ if err := checkClusterCompatibilityFromHeader(r.Header, h.cid); err != nil {
+ http.Error(w, err.Error(), http.StatusPreconditionFailed)
+ return
+ }
+
+ addRemoteFromRequest(h.tr, r)
+
+ dec := &messageDecoder{r: r.Body}
+ // let snapshots be very large since they can exceed 512MB for large installations
+ m, err := dec.decodeLimit(uint64(1 << 63))
+ if err != nil {
+ msg := fmt.Sprintf("failed to decode raft message (%v)", err)
+ plog.Errorf(msg)
+ http.Error(w, msg, http.StatusBadRequest)
+ recvFailures.WithLabelValues(r.RemoteAddr).Inc()
+ return
+ }
+
+ receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(m.Size()))
+
+ if m.Type != raftpb.MsgSnap {
+ plog.Errorf("unexpected raft message type %s on snapshot path", m.Type)
+ http.Error(w, "wrong raft message type", http.StatusBadRequest)
+ return
+ }
+
+ plog.Infof("receiving database snapshot [index:%d, from %s] ...", m.Snapshot.Metadata.Index, types.ID(m.From))
+ // save incoming database snapshot.
+ n, err := h.snapshotter.SaveDBFrom(r.Body, m.Snapshot.Metadata.Index)
+ if err != nil {
+ msg := fmt.Sprintf("failed to save KV snapshot (%v)", err)
+ plog.Error(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ return
+ }
+ receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(n))
+ plog.Infof("received and saved database snapshot [index: %d, from: %s] successfully", m.Snapshot.Metadata.Index, types.ID(m.From))
+
+ if err := h.r.Process(context.TODO(), m); err != nil {
+ switch v := err.(type) {
+ // Process may return writerToResponse error when doing some
+ // additional checks before calling raft.Node.Step.
+ case writerToResponse:
+ v.WriteTo(w)
+ default:
+ msg := fmt.Sprintf("failed to process raft message (%v)", err)
+ plog.Warningf(msg)
+ http.Error(w, msg, http.StatusInternalServerError)
+ }
+ return
+ }
+ // Write StatusNoContent header after the message has been processed by
+ // raft, which facilitates the client to report MsgSnap status.
+ w.WriteHeader(http.StatusNoContent)
+}
+
+type streamHandler struct {
+ tr *Transport
+ peerGetter peerGetter
+ r Raft
+ id types.ID
+ cid types.ID
+}
+
+func newStreamHandler(tr *Transport, pg peerGetter, r Raft, id, cid types.ID) http.Handler {
+ return &streamHandler{
+ tr: tr,
+ peerGetter: pg,
+ r: r,
+ id: id,
+ cid: cid,
+ }
+}
+
+func (h *streamHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "GET" {
+ w.Header().Set("Allow", "GET")
+ http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
+ return
+ }
+
+ w.Header().Set("X-Server-Version", version.Version)
+ w.Header().Set("X-Etcd-Cluster-ID", h.cid.String())
+
+ if err := checkClusterCompatibilityFromHeader(r.Header, h.cid); err != nil {
+ http.Error(w, err.Error(), http.StatusPreconditionFailed)
+ return
+ }
+
+ var t streamType
+ switch path.Dir(r.URL.Path) {
+ case streamTypeMsgAppV2.endpoint():
+ t = streamTypeMsgAppV2
+ case streamTypeMessage.endpoint():
+ t = streamTypeMessage
+ default:
+ plog.Debugf("ignored unexpected streaming request path %s", r.URL.Path)
+ http.Error(w, "invalid path", http.StatusNotFound)
+ return
+ }
+
+ fromStr := path.Base(r.URL.Path)
+ from, err := types.IDFromString(fromStr)
+ if err != nil {
+ plog.Errorf("failed to parse from %s into ID (%v)", fromStr, err)
+ http.Error(w, "invalid from", http.StatusNotFound)
+ return
+ }
+ if h.r.IsIDRemoved(uint64(from)) {
+ plog.Warningf("rejected the stream from peer %s since it was removed", from)
+ http.Error(w, "removed member", http.StatusGone)
+ return
+ }
+ p := h.peerGetter.Get(from)
+ if p == nil {
+ // This may happen in following cases:
+ // 1. user starts a remote peer that belongs to a different cluster
+ // with the same cluster ID.
+ // 2. local etcd falls behind of the cluster, and cannot recognize
+ // the members that joined after its current progress.
+ if urls := r.Header.Get("X-PeerURLs"); urls != "" {
+ h.tr.AddRemote(from, strings.Split(urls, ","))
+ }
+ plog.Errorf("failed to find member %s in cluster %s", from, h.cid)
+ http.Error(w, "error sender not found", http.StatusNotFound)
+ return
+ }
+
+ wto := h.id.String()
+ if gto := r.Header.Get("X-Raft-To"); gto != wto {
+ plog.Errorf("streaming request ignored (ID mismatch got %s want %s)", gto, wto)
+ http.Error(w, "to field mismatch", http.StatusPreconditionFailed)
+ return
+ }
+
+ w.WriteHeader(http.StatusOK)
+ w.(http.Flusher).Flush()
+
+ c := newCloseNotifier()
+ conn := &outgoingConn{
+ t: t,
+ Writer: w,
+ Flusher: w.(http.Flusher),
+ Closer: c,
+ }
+ p.attachOutgoingConn(conn)
+ <-c.closeNotify()
+}
+
+// checkClusterCompatibilityFromHeader checks the cluster compatibility of
+// the local member from the given header.
+// It checks whether the version of local member is compatible with
+// the versions in the header, and whether the cluster ID of local member
+// matches the one in the header.
+func checkClusterCompatibilityFromHeader(header http.Header, cid types.ID) error {
+ if err := checkVersionCompability(header.Get("X-Server-From"), serverVersion(header), minClusterVersion(header)); err != nil {
+ plog.Errorf("request version incompatibility (%v)", err)
+ return errIncompatibleVersion
+ }
+ if gcid := header.Get("X-Etcd-Cluster-ID"); gcid != cid.String() {
+ plog.Errorf("request cluster ID mismatch (got %s want %s)", gcid, cid)
+ return errClusterIDMismatch
+ }
+ return nil
+}
+
+type closeNotifier struct {
+ done chan struct{}
+}
+
+func newCloseNotifier() *closeNotifier {
+ return &closeNotifier{
+ done: make(chan struct{}),
+ }
+}
+
+func (n *closeNotifier) Close() error {
+ close(n.done)
+ return nil
+}
+
+func (n *closeNotifier) closeNotify() <-chan struct{} { return n.done }
diff --git a/vendor/github.com/coreos/etcd/rafthttp/metrics.go b/vendor/github.com/coreos/etcd/rafthttp/metrics.go
new file mode 100644
index 00000000..320bfe72
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/metrics.go
@@ -0,0 +1,73 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import "github.com/prometheus/client_golang/prometheus"
+
+var (
+ sentBytes = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "peer_sent_bytes_total",
+ Help: "The total number of bytes sent to peers.",
+ },
+ []string{"To"},
+ )
+
+ receivedBytes = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "peer_received_bytes_total",
+ Help: "The total number of bytes received from peers.",
+ },
+ []string{"From"},
+ )
+
+ sentFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "peer_sent_failures_total",
+ Help: "The total number of send failures from peers.",
+ },
+ []string{"To"},
+ )
+
+ recvFailures = prometheus.NewCounterVec(prometheus.CounterOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "peer_received_failures_total",
+ Help: "The total number of receive failures from peers.",
+ },
+ []string{"From"},
+ )
+
+ rtts = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "network",
+ Name: "peer_round_trip_time_seconds",
+ Help: "Round-Trip-Time histogram between peers.",
+ Buckets: prometheus.ExponentialBuckets(0.0001, 2, 14),
+ },
+ []string{"To"},
+ )
+)
+
+func init() {
+ prometheus.MustRegister(sentBytes)
+ prometheus.MustRegister(receivedBytes)
+ prometheus.MustRegister(sentFailures)
+ prometheus.MustRegister(recvFailures)
+ prometheus.MustRegister(rtts)
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/msg_codec.go b/vendor/github.com/coreos/etcd/rafthttp/msg_codec.go
new file mode 100644
index 00000000..ef59bc88
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/msg_codec.go
@@ -0,0 +1,68 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "encoding/binary"
+ "errors"
+ "io"
+
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/raft/raftpb"
+)
+
+// messageEncoder is a encoder that can encode all kinds of messages.
+// It MUST be used with a paired messageDecoder.
+type messageEncoder struct {
+ w io.Writer
+}
+
+func (enc *messageEncoder) encode(m *raftpb.Message) error {
+ if err := binary.Write(enc.w, binary.BigEndian, uint64(m.Size())); err != nil {
+ return err
+ }
+ _, err := enc.w.Write(pbutil.MustMarshal(m))
+ return err
+}
+
+// messageDecoder is a decoder that can decode all kinds of messages.
+type messageDecoder struct {
+ r io.Reader
+}
+
+var (
+ readBytesLimit uint64 = 512 * 1024 * 1024 // 512 MB
+ ErrExceedSizeLimit = errors.New("rafthttp: error limit exceeded")
+)
+
+func (dec *messageDecoder) decode() (raftpb.Message, error) {
+ return dec.decodeLimit(readBytesLimit)
+}
+
+func (dec *messageDecoder) decodeLimit(numBytes uint64) (raftpb.Message, error) {
+ var m raftpb.Message
+ var l uint64
+ if err := binary.Read(dec.r, binary.BigEndian, &l); err != nil {
+ return m, err
+ }
+ if l > numBytes {
+ return m, ErrExceedSizeLimit
+ }
+ buf := make([]byte, int(l))
+ if _, err := io.ReadFull(dec.r, buf); err != nil {
+ return m, err
+ }
+ return m, m.Unmarshal(buf)
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/msgappv2_codec.go b/vendor/github.com/coreos/etcd/rafthttp/msgappv2_codec.go
new file mode 100644
index 00000000..013ffe7c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/msgappv2_codec.go
@@ -0,0 +1,248 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/stats"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft/raftpb"
+)
+
+const (
+ msgTypeLinkHeartbeat uint8 = 0
+ msgTypeAppEntries uint8 = 1
+ msgTypeApp uint8 = 2
+
+ msgAppV2BufSize = 1024 * 1024
+)
+
+// msgappv2 stream sends three types of message: linkHeartbeatMessage,
+// AppEntries and MsgApp. AppEntries is the MsgApp that is sent in
+// replicate state in raft, whose index and term are fully predictable.
+//
+// Data format of linkHeartbeatMessage:
+// | offset | bytes | description |
+// +--------+-------+-------------+
+// | 0 | 1 | \x00 |
+//
+// Data format of AppEntries:
+// | offset | bytes | description |
+// +--------+-------+-------------+
+// | 0 | 1 | \x01 |
+// | 1 | 8 | length of entries |
+// | 9 | 8 | length of first entry |
+// | 17 | n1 | first entry |
+// ...
+// | x | 8 | length of k-th entry data |
+// | x+8 | nk | k-th entry data |
+// | x+8+nk | 8 | commit index |
+//
+// Data format of MsgApp:
+// | offset | bytes | description |
+// +--------+-------+-------------+
+// | 0 | 1 | \x02 |
+// | 1 | 8 | length of encoded message |
+// | 9 | n | encoded message |
+type msgAppV2Encoder struct {
+ w io.Writer
+ fs *stats.FollowerStats
+
+ term uint64
+ index uint64
+ buf []byte
+ uint64buf []byte
+ uint8buf []byte
+}
+
+func newMsgAppV2Encoder(w io.Writer, fs *stats.FollowerStats) *msgAppV2Encoder {
+ return &msgAppV2Encoder{
+ w: w,
+ fs: fs,
+ buf: make([]byte, msgAppV2BufSize),
+ uint64buf: make([]byte, 8),
+ uint8buf: make([]byte, 1),
+ }
+}
+
+func (enc *msgAppV2Encoder) encode(m *raftpb.Message) error {
+ start := time.Now()
+ switch {
+ case isLinkHeartbeatMessage(m):
+ enc.uint8buf[0] = byte(msgTypeLinkHeartbeat)
+ if _, err := enc.w.Write(enc.uint8buf); err != nil {
+ return err
+ }
+ case enc.index == m.Index && enc.term == m.LogTerm && m.LogTerm == m.Term:
+ enc.uint8buf[0] = byte(msgTypeAppEntries)
+ if _, err := enc.w.Write(enc.uint8buf); err != nil {
+ return err
+ }
+ // write length of entries
+ binary.BigEndian.PutUint64(enc.uint64buf, uint64(len(m.Entries)))
+ if _, err := enc.w.Write(enc.uint64buf); err != nil {
+ return err
+ }
+ for i := 0; i < len(m.Entries); i++ {
+ // write length of entry
+ binary.BigEndian.PutUint64(enc.uint64buf, uint64(m.Entries[i].Size()))
+ if _, err := enc.w.Write(enc.uint64buf); err != nil {
+ return err
+ }
+ if n := m.Entries[i].Size(); n < msgAppV2BufSize {
+ if _, err := m.Entries[i].MarshalTo(enc.buf); err != nil {
+ return err
+ }
+ if _, err := enc.w.Write(enc.buf[:n]); err != nil {
+ return err
+ }
+ } else {
+ if _, err := enc.w.Write(pbutil.MustMarshal(&m.Entries[i])); err != nil {
+ return err
+ }
+ }
+ enc.index++
+ }
+ // write commit index
+ binary.BigEndian.PutUint64(enc.uint64buf, m.Commit)
+ if _, err := enc.w.Write(enc.uint64buf); err != nil {
+ return err
+ }
+ enc.fs.Succ(time.Since(start))
+ default:
+ if err := binary.Write(enc.w, binary.BigEndian, msgTypeApp); err != nil {
+ return err
+ }
+ // write size of message
+ if err := binary.Write(enc.w, binary.BigEndian, uint64(m.Size())); err != nil {
+ return err
+ }
+ // write message
+ if _, err := enc.w.Write(pbutil.MustMarshal(m)); err != nil {
+ return err
+ }
+
+ enc.term = m.Term
+ enc.index = m.Index
+ if l := len(m.Entries); l > 0 {
+ enc.index = m.Entries[l-1].Index
+ }
+ enc.fs.Succ(time.Since(start))
+ }
+ return nil
+}
+
+type msgAppV2Decoder struct {
+ r io.Reader
+ local, remote types.ID
+
+ term uint64
+ index uint64
+ buf []byte
+ uint64buf []byte
+ uint8buf []byte
+}
+
+func newMsgAppV2Decoder(r io.Reader, local, remote types.ID) *msgAppV2Decoder {
+ return &msgAppV2Decoder{
+ r: r,
+ local: local,
+ remote: remote,
+ buf: make([]byte, msgAppV2BufSize),
+ uint64buf: make([]byte, 8),
+ uint8buf: make([]byte, 1),
+ }
+}
+
+func (dec *msgAppV2Decoder) decode() (raftpb.Message, error) {
+ var (
+ m raftpb.Message
+ typ uint8
+ )
+ if _, err := io.ReadFull(dec.r, dec.uint8buf); err != nil {
+ return m, err
+ }
+ typ = uint8(dec.uint8buf[0])
+ switch typ {
+ case msgTypeLinkHeartbeat:
+ return linkHeartbeatMessage, nil
+ case msgTypeAppEntries:
+ m = raftpb.Message{
+ Type: raftpb.MsgApp,
+ From: uint64(dec.remote),
+ To: uint64(dec.local),
+ Term: dec.term,
+ LogTerm: dec.term,
+ Index: dec.index,
+ }
+
+ // decode entries
+ if _, err := io.ReadFull(dec.r, dec.uint64buf); err != nil {
+ return m, err
+ }
+ l := binary.BigEndian.Uint64(dec.uint64buf)
+ m.Entries = make([]raftpb.Entry, int(l))
+ for i := 0; i < int(l); i++ {
+ if _, err := io.ReadFull(dec.r, dec.uint64buf); err != nil {
+ return m, err
+ }
+ size := binary.BigEndian.Uint64(dec.uint64buf)
+ var buf []byte
+ if size < msgAppV2BufSize {
+ buf = dec.buf[:size]
+ if _, err := io.ReadFull(dec.r, buf); err != nil {
+ return m, err
+ }
+ } else {
+ buf = make([]byte, int(size))
+ if _, err := io.ReadFull(dec.r, buf); err != nil {
+ return m, err
+ }
+ }
+ dec.index++
+ // 1 alloc
+ pbutil.MustUnmarshal(&m.Entries[i], buf)
+ }
+ // decode commit index
+ if _, err := io.ReadFull(dec.r, dec.uint64buf); err != nil {
+ return m, err
+ }
+ m.Commit = binary.BigEndian.Uint64(dec.uint64buf)
+ case msgTypeApp:
+ var size uint64
+ if err := binary.Read(dec.r, binary.BigEndian, &size); err != nil {
+ return m, err
+ }
+ buf := make([]byte, int(size))
+ if _, err := io.ReadFull(dec.r, buf); err != nil {
+ return m, err
+ }
+ pbutil.MustUnmarshal(&m, buf)
+
+ dec.term = m.Term
+ dec.index = m.Index
+ if l := len(m.Entries); l > 0 {
+ dec.index = m.Entries[l-1].Index
+ }
+ default:
+ return m, fmt.Errorf("failed to parse type %d in msgappv2 stream", typ)
+ }
+ return m, nil
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/peer.go b/vendor/github.com/coreos/etcd/rafthttp/peer.go
new file mode 100644
index 00000000..e9a25bb3
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/peer.go
@@ -0,0 +1,313 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/stats"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/snap"
+
+ "golang.org/x/time/rate"
+)
+
+const (
+ // ConnReadTimeout and ConnWriteTimeout are the i/o timeout set on each connection rafthttp pkg creates.
+ // A 5 seconds timeout is good enough for recycling bad connections. Or we have to wait for
+ // tcp keepalive failing to detect a bad connection, which is at minutes level.
+ // For long term streaming connections, rafthttp pkg sends application level linkHeartbeatMessage
+ // to keep the connection alive.
+ // For short term pipeline connections, the connection MUST be killed to avoid it being
+ // put back to http pkg connection pool.
+ ConnReadTimeout = 5 * time.Second
+ ConnWriteTimeout = 5 * time.Second
+
+ recvBufSize = 4096
+ // maxPendingProposals holds the proposals during one leader election process.
+ // Generally one leader election takes at most 1 sec. It should have
+ // 0-2 election conflicts, and each one takes 0.5 sec.
+ // We assume the number of concurrent proposers is smaller than 4096.
+ // One client blocks on its proposal for at least 1 sec, so 4096 is enough
+ // to hold all proposals.
+ maxPendingProposals = 4096
+
+ streamAppV2 = "streamMsgAppV2"
+ streamMsg = "streamMsg"
+ pipelineMsg = "pipeline"
+ sendSnap = "sendMsgSnap"
+)
+
+type Peer interface {
+ // send sends the message to the remote peer. The function is non-blocking
+ // and has no promise that the message will be received by the remote.
+ // When it fails to send message out, it will report the status to underlying
+ // raft.
+ send(m raftpb.Message)
+
+ // sendSnap sends the merged snapshot message to the remote peer. Its behavior
+ // is similar to send.
+ sendSnap(m snap.Message)
+
+ // update updates the urls of remote peer.
+ update(urls types.URLs)
+
+ // attachOutgoingConn attaches the outgoing connection to the peer for
+ // stream usage. After the call, the ownership of the outgoing
+ // connection hands over to the peer. The peer will close the connection
+ // when it is no longer used.
+ attachOutgoingConn(conn *outgoingConn)
+ // activeSince returns the time that the connection with the
+ // peer becomes active.
+ activeSince() time.Time
+ // stop performs any necessary finalization and terminates the peer
+ // elegantly.
+ stop()
+}
+
+// peer is the representative of a remote raft node. Local raft node sends
+// messages to the remote through peer.
+// Each peer has two underlying mechanisms to send out a message: stream and
+// pipeline.
+// A stream is a receiver initialized long-polling connection, which
+// is always open to transfer messages. Besides general stream, peer also has
+// a optimized stream for sending msgApp since msgApp accounts for large part
+// of all messages. Only raft leader uses the optimized stream to send msgApp
+// to the remote follower node.
+// A pipeline is a series of http clients that send http requests to the remote.
+// It is only used when the stream has not been established.
+type peer struct {
+ // id of the remote raft peer node
+ id types.ID
+ r Raft
+
+ status *peerStatus
+
+ picker *urlPicker
+
+ msgAppV2Writer *streamWriter
+ writer *streamWriter
+ pipeline *pipeline
+ snapSender *snapshotSender // snapshot sender to send v3 snapshot messages
+ msgAppV2Reader *streamReader
+ msgAppReader *streamReader
+
+ recvc chan raftpb.Message
+ propc chan raftpb.Message
+
+ mu sync.Mutex
+ paused bool
+
+ cancel context.CancelFunc // cancel pending works in go routine created by peer.
+ stopc chan struct{}
+}
+
+func startPeer(transport *Transport, urls types.URLs, peerID types.ID, fs *stats.FollowerStats) *peer {
+ plog.Infof("starting peer %s...", peerID)
+ defer plog.Infof("started peer %s", peerID)
+
+ status := newPeerStatus(peerID)
+ picker := newURLPicker(urls)
+ errorc := transport.ErrorC
+ r := transport.Raft
+ pipeline := &pipeline{
+ peerID: peerID,
+ tr: transport,
+ picker: picker,
+ status: status,
+ followerStats: fs,
+ raft: r,
+ errorc: errorc,
+ }
+ pipeline.start()
+
+ p := &peer{
+ id: peerID,
+ r: r,
+ status: status,
+ picker: picker,
+ msgAppV2Writer: startStreamWriter(peerID, status, fs, r),
+ writer: startStreamWriter(peerID, status, fs, r),
+ pipeline: pipeline,
+ snapSender: newSnapshotSender(transport, picker, peerID, status),
+ recvc: make(chan raftpb.Message, recvBufSize),
+ propc: make(chan raftpb.Message, maxPendingProposals),
+ stopc: make(chan struct{}),
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ p.cancel = cancel
+ go func() {
+ for {
+ select {
+ case mm := <-p.recvc:
+ if err := r.Process(ctx, mm); err != nil {
+ plog.Warningf("failed to process raft message (%v)", err)
+ }
+ case <-p.stopc:
+ return
+ }
+ }
+ }()
+
+ // r.Process might block for processing proposal when there is no leader.
+ // Thus propc must be put into a separate routine with recvc to avoid blocking
+ // processing other raft messages.
+ go func() {
+ for {
+ select {
+ case mm := <-p.propc:
+ if err := r.Process(ctx, mm); err != nil {
+ plog.Warningf("failed to process raft message (%v)", err)
+ }
+ case <-p.stopc:
+ return
+ }
+ }
+ }()
+
+ p.msgAppV2Reader = &streamReader{
+ peerID: peerID,
+ typ: streamTypeMsgAppV2,
+ tr: transport,
+ picker: picker,
+ status: status,
+ recvc: p.recvc,
+ propc: p.propc,
+ rl: rate.NewLimiter(transport.DialRetryFrequency, 1),
+ }
+ p.msgAppReader = &streamReader{
+ peerID: peerID,
+ typ: streamTypeMessage,
+ tr: transport,
+ picker: picker,
+ status: status,
+ recvc: p.recvc,
+ propc: p.propc,
+ rl: rate.NewLimiter(transport.DialRetryFrequency, 1),
+ }
+
+ p.msgAppV2Reader.start()
+ p.msgAppReader.start()
+
+ return p
+}
+
+func (p *peer) send(m raftpb.Message) {
+ p.mu.Lock()
+ paused := p.paused
+ p.mu.Unlock()
+
+ if paused {
+ return
+ }
+
+ writec, name := p.pick(m)
+ select {
+ case writec <- m:
+ default:
+ p.r.ReportUnreachable(m.To)
+ if isMsgSnap(m) {
+ p.r.ReportSnapshot(m.To, raft.SnapshotFailure)
+ }
+ if p.status.isActive() {
+ plog.MergeWarningf("dropped internal raft message to %s since %s's sending buffer is full (bad/overloaded network)", p.id, name)
+ }
+ plog.Debugf("dropped %s to %s since %s's sending buffer is full", m.Type, p.id, name)
+ sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
+ }
+}
+
+func (p *peer) sendSnap(m snap.Message) {
+ go p.snapSender.send(m)
+}
+
+func (p *peer) update(urls types.URLs) {
+ p.picker.update(urls)
+}
+
+func (p *peer) attachOutgoingConn(conn *outgoingConn) {
+ var ok bool
+ switch conn.t {
+ case streamTypeMsgAppV2:
+ ok = p.msgAppV2Writer.attach(conn)
+ case streamTypeMessage:
+ ok = p.writer.attach(conn)
+ default:
+ plog.Panicf("unhandled stream type %s", conn.t)
+ }
+ if !ok {
+ conn.Close()
+ }
+}
+
+func (p *peer) activeSince() time.Time { return p.status.activeSince() }
+
+// Pause pauses the peer. The peer will simply drops all incoming
+// messages without returning an error.
+func (p *peer) Pause() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ p.paused = true
+ p.msgAppReader.pause()
+ p.msgAppV2Reader.pause()
+}
+
+// Resume resumes a paused peer.
+func (p *peer) Resume() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ p.paused = false
+ p.msgAppReader.resume()
+ p.msgAppV2Reader.resume()
+}
+
+func (p *peer) stop() {
+ plog.Infof("stopping peer %s...", p.id)
+ defer plog.Infof("stopped peer %s", p.id)
+
+ close(p.stopc)
+ p.cancel()
+ p.msgAppV2Writer.stop()
+ p.writer.stop()
+ p.pipeline.stop()
+ p.snapSender.stop()
+ p.msgAppV2Reader.stop()
+ p.msgAppReader.stop()
+}
+
+// pick picks a chan for sending the given message. The picked chan and the picked chan
+// string name are returned.
+func (p *peer) pick(m raftpb.Message) (writec chan<- raftpb.Message, picked string) {
+ var ok bool
+ // Considering MsgSnap may have a big size, e.g., 1G, and will block
+ // stream for a long time, only use one of the N pipelines to send MsgSnap.
+ if isMsgSnap(m) {
+ return p.pipeline.msgc, pipelineMsg
+ } else if writec, ok = p.msgAppV2Writer.writec(); ok && isMsgApp(m) {
+ return writec, streamAppV2
+ } else if writec, ok = p.writer.writec(); ok {
+ return writec, streamMsg
+ }
+ return p.pipeline.msgc, pipelineMsg
+}
+
+func isMsgApp(m raftpb.Message) bool { return m.Type == raftpb.MsgApp }
+
+func isMsgSnap(m raftpb.Message) bool { return m.Type == raftpb.MsgSnap }
diff --git a/vendor/github.com/coreos/etcd/rafthttp/peer_status.go b/vendor/github.com/coreos/etcd/rafthttp/peer_status.go
new file mode 100644
index 00000000..706144f6
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/peer_status.go
@@ -0,0 +1,77 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/pkg/types"
+)
+
+type failureType struct {
+ source string
+ action string
+}
+
+type peerStatus struct {
+ id types.ID
+ mu sync.Mutex // protect variables below
+ active bool
+ since time.Time
+}
+
+func newPeerStatus(id types.ID) *peerStatus {
+ return &peerStatus{
+ id: id,
+ }
+}
+
+func (s *peerStatus) activate() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if !s.active {
+ plog.Infof("peer %s became active", s.id)
+ s.active = true
+ s.since = time.Now()
+ }
+}
+
+func (s *peerStatus) deactivate(failure failureType, reason string) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ msg := fmt.Sprintf("failed to %s %s on %s (%s)", failure.action, s.id, failure.source, reason)
+ if s.active {
+ plog.Errorf(msg)
+ plog.Infof("peer %s became inactive", s.id)
+ s.active = false
+ s.since = time.Time{}
+ return
+ }
+ plog.Debugf(msg)
+}
+
+func (s *peerStatus) isActive() bool {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.active
+}
+
+func (s *peerStatus) activeSince() time.Time {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.since
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/pipeline.go b/vendor/github.com/coreos/etcd/rafthttp/pipeline.go
new file mode 100644
index 00000000..d9f07c34
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/pipeline.go
@@ -0,0 +1,160 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "io/ioutil"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/stats"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+)
+
+const (
+ connPerPipeline = 4
+ // pipelineBufSize is the size of pipeline buffer, which helps hold the
+ // temporary network latency.
+ // The size ensures that pipeline does not drop messages when the network
+ // is out of work for less than 1 second in good path.
+ pipelineBufSize = 64
+)
+
+var errStopped = errors.New("stopped")
+
+type pipeline struct {
+ peerID types.ID
+
+ tr *Transport
+ picker *urlPicker
+ status *peerStatus
+ raft Raft
+ errorc chan error
+ // deprecate when we depercate v2 API
+ followerStats *stats.FollowerStats
+
+ msgc chan raftpb.Message
+ // wait for the handling routines
+ wg sync.WaitGroup
+ stopc chan struct{}
+}
+
+func (p *pipeline) start() {
+ p.stopc = make(chan struct{})
+ p.msgc = make(chan raftpb.Message, pipelineBufSize)
+ p.wg.Add(connPerPipeline)
+ for i := 0; i < connPerPipeline; i++ {
+ go p.handle()
+ }
+ plog.Infof("started HTTP pipelining with peer %s", p.peerID)
+}
+
+func (p *pipeline) stop() {
+ close(p.stopc)
+ p.wg.Wait()
+ plog.Infof("stopped HTTP pipelining with peer %s", p.peerID)
+}
+
+func (p *pipeline) handle() {
+ defer p.wg.Done()
+
+ for {
+ select {
+ case m := <-p.msgc:
+ start := time.Now()
+ err := p.post(pbutil.MustMarshal(&m))
+ end := time.Now()
+
+ if err != nil {
+ p.status.deactivate(failureType{source: pipelineMsg, action: "write"}, err.Error())
+
+ if m.Type == raftpb.MsgApp && p.followerStats != nil {
+ p.followerStats.Fail()
+ }
+ p.raft.ReportUnreachable(m.To)
+ if isMsgSnap(m) {
+ p.raft.ReportSnapshot(m.To, raft.SnapshotFailure)
+ }
+ sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
+ continue
+ }
+
+ p.status.activate()
+ if m.Type == raftpb.MsgApp && p.followerStats != nil {
+ p.followerStats.Succ(end.Sub(start))
+ }
+ if isMsgSnap(m) {
+ p.raft.ReportSnapshot(m.To, raft.SnapshotFinish)
+ }
+ sentBytes.WithLabelValues(types.ID(m.To).String()).Add(float64(m.Size()))
+ case <-p.stopc:
+ return
+ }
+ }
+}
+
+// post POSTs a data payload to a url. Returns nil if the POST succeeds,
+// error on any failure.
+func (p *pipeline) post(data []byte) (err error) {
+ u := p.picker.pick()
+ req := createPostRequest(u, RaftPrefix, bytes.NewBuffer(data), "application/protobuf", p.tr.URLs, p.tr.ID, p.tr.ClusterID)
+
+ done := make(chan struct{}, 1)
+ ctx, cancel := context.WithCancel(context.Background())
+ req = req.WithContext(ctx)
+ go func() {
+ select {
+ case <-done:
+ case <-p.stopc:
+ waitSchedule()
+ cancel()
+ }
+ }()
+
+ resp, err := p.tr.pipelineRt.RoundTrip(req)
+ done <- struct{}{}
+ if err != nil {
+ p.picker.unreachable(u)
+ return err
+ }
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ p.picker.unreachable(u)
+ return err
+ }
+ resp.Body.Close()
+
+ err = checkPostResponse(resp, b, req, p.peerID)
+ if err != nil {
+ p.picker.unreachable(u)
+ // errMemberRemoved is a critical error since a removed member should
+ // always be stopped. So we use reportCriticalError to report it to errorc.
+ if err == errMemberRemoved {
+ reportCriticalError(err, p.errorc)
+ }
+ return err
+ }
+
+ return nil
+}
+
+// waitSchedule waits other goroutines to be scheduled for a while
+func waitSchedule() { time.Sleep(time.Millisecond) }
diff --git a/vendor/github.com/coreos/etcd/rafthttp/probing_status.go b/vendor/github.com/coreos/etcd/rafthttp/probing_status.go
new file mode 100644
index 00000000..c7a3c7ab
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/probing_status.go
@@ -0,0 +1,67 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "time"
+
+ "github.com/xiang90/probing"
+)
+
+var (
+ // proberInterval must be shorter than read timeout.
+ // Or the connection will time-out.
+ proberInterval = ConnReadTimeout - time.Second
+ statusMonitoringInterval = 30 * time.Second
+ statusErrorInterval = 5 * time.Second
+)
+
+func addPeerToProber(p probing.Prober, id string, us []string) {
+ hus := make([]string, len(us))
+ for i := range us {
+ hus[i] = us[i] + ProbingPrefix
+ }
+
+ p.AddHTTP(id, proberInterval, hus)
+
+ s, err := p.Status(id)
+ if err != nil {
+ plog.Errorf("failed to add peer %s into prober", id)
+ } else {
+ go monitorProbingStatus(s, id)
+ }
+}
+
+func monitorProbingStatus(s probing.Status, id string) {
+ // set the first interval short to log error early.
+ interval := statusErrorInterval
+ for {
+ select {
+ case <-time.After(interval):
+ if !s.Health() {
+ plog.Warningf("health check for peer %s could not connect: %v", id, s.Err())
+ interval = statusErrorInterval
+ } else {
+ interval = statusMonitoringInterval
+ }
+ if s.ClockDiff() > time.Second {
+ plog.Warningf("the clock difference against peer %s is too high [%v > %v]", id, s.ClockDiff(), time.Second)
+ }
+ rtts.WithLabelValues(id).Observe(s.SRTT().Seconds())
+ case <-s.StopNotify():
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/remote.go b/vendor/github.com/coreos/etcd/rafthttp/remote.go
new file mode 100644
index 00000000..f7f9d2ce
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/remote.go
@@ -0,0 +1,70 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft/raftpb"
+)
+
+type remote struct {
+ id types.ID
+ status *peerStatus
+ pipeline *pipeline
+}
+
+func startRemote(tr *Transport, urls types.URLs, id types.ID) *remote {
+ picker := newURLPicker(urls)
+ status := newPeerStatus(id)
+ pipeline := &pipeline{
+ peerID: id,
+ tr: tr,
+ picker: picker,
+ status: status,
+ raft: tr.Raft,
+ errorc: tr.ErrorC,
+ }
+ pipeline.start()
+
+ return &remote{
+ id: id,
+ status: status,
+ pipeline: pipeline,
+ }
+}
+
+func (g *remote) send(m raftpb.Message) {
+ select {
+ case g.pipeline.msgc <- m:
+ default:
+ if g.status.isActive() {
+ plog.MergeWarningf("dropped internal raft message to %s since sending buffer is full (bad/overloaded network)", g.id)
+ }
+ plog.Debugf("dropped %s to %s since sending buffer is full", m.Type, g.id)
+ sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
+ }
+}
+
+func (g *remote) stop() {
+ g.pipeline.stop()
+}
+
+func (g *remote) Pause() {
+ g.stop()
+}
+
+func (g *remote) Resume() {
+ g.pipeline.start()
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/snapshot_sender.go b/vendor/github.com/coreos/etcd/rafthttp/snapshot_sender.go
new file mode 100644
index 00000000..52273c9d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/snapshot_sender.go
@@ -0,0 +1,157 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "bytes"
+ "context"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "time"
+
+ "github.com/coreos/etcd/pkg/httputil"
+ pioutil "github.com/coreos/etcd/pkg/ioutil"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/snap"
+)
+
+var (
+ // timeout for reading snapshot response body
+ snapResponseReadTimeout = 5 * time.Second
+)
+
+type snapshotSender struct {
+ from, to types.ID
+ cid types.ID
+
+ tr *Transport
+ picker *urlPicker
+ status *peerStatus
+ r Raft
+ errorc chan error
+
+ stopc chan struct{}
+}
+
+func newSnapshotSender(tr *Transport, picker *urlPicker, to types.ID, status *peerStatus) *snapshotSender {
+ return &snapshotSender{
+ from: tr.ID,
+ to: to,
+ cid: tr.ClusterID,
+ tr: tr,
+ picker: picker,
+ status: status,
+ r: tr.Raft,
+ errorc: tr.ErrorC,
+ stopc: make(chan struct{}),
+ }
+}
+
+func (s *snapshotSender) stop() { close(s.stopc) }
+
+func (s *snapshotSender) send(merged snap.Message) {
+ m := merged.Message
+
+ body := createSnapBody(merged)
+ defer body.Close()
+
+ u := s.picker.pick()
+ req := createPostRequest(u, RaftSnapshotPrefix, body, "application/octet-stream", s.tr.URLs, s.from, s.cid)
+
+ plog.Infof("start to send database snapshot [index: %d, to %s]...", m.Snapshot.Metadata.Index, types.ID(m.To))
+
+ err := s.post(req)
+ defer merged.CloseWithError(err)
+ if err != nil {
+ plog.Warningf("database snapshot [index: %d, to: %s] failed to be sent out (%v)", m.Snapshot.Metadata.Index, types.ID(m.To), err)
+
+ // errMemberRemoved is a critical error since a removed member should
+ // always be stopped. So we use reportCriticalError to report it to errorc.
+ if err == errMemberRemoved {
+ reportCriticalError(err, s.errorc)
+ }
+
+ s.picker.unreachable(u)
+ s.status.deactivate(failureType{source: sendSnap, action: "post"}, err.Error())
+ s.r.ReportUnreachable(m.To)
+ // report SnapshotFailure to raft state machine. After raft state
+ // machine knows about it, it would pause a while and retry sending
+ // new snapshot message.
+ s.r.ReportSnapshot(m.To, raft.SnapshotFailure)
+ sentFailures.WithLabelValues(types.ID(m.To).String()).Inc()
+ return
+ }
+ s.status.activate()
+ s.r.ReportSnapshot(m.To, raft.SnapshotFinish)
+ plog.Infof("database snapshot [index: %d, to: %s] sent out successfully", m.Snapshot.Metadata.Index, types.ID(m.To))
+
+ sentBytes.WithLabelValues(types.ID(m.To).String()).Add(float64(merged.TotalSize))
+}
+
+// post posts the given request.
+// It returns nil when request is sent out and processed successfully.
+func (s *snapshotSender) post(req *http.Request) (err error) {
+ ctx, cancel := context.WithCancel(context.Background())
+ req = req.WithContext(ctx)
+ defer cancel()
+
+ type responseAndError struct {
+ resp *http.Response
+ body []byte
+ err error
+ }
+ result := make(chan responseAndError, 1)
+
+ go func() {
+ resp, err := s.tr.pipelineRt.RoundTrip(req)
+ if err != nil {
+ result <- responseAndError{resp, nil, err}
+ return
+ }
+
+ // close the response body when timeouts.
+ // prevents from reading the body forever when the other side dies right after
+ // successfully receives the request body.
+ time.AfterFunc(snapResponseReadTimeout, func() { httputil.GracefulClose(resp) })
+ body, err := ioutil.ReadAll(resp.Body)
+ result <- responseAndError{resp, body, err}
+ }()
+
+ select {
+ case <-s.stopc:
+ return errStopped
+ case r := <-result:
+ if r.err != nil {
+ return r.err
+ }
+ return checkPostResponse(r.resp, r.body, req, s.to)
+ }
+}
+
+func createSnapBody(merged snap.Message) io.ReadCloser {
+ buf := new(bytes.Buffer)
+ enc := &messageEncoder{w: buf}
+ // encode raft message
+ if err := enc.encode(&merged.Message); err != nil {
+ plog.Panicf("encode message error (%v)", err)
+ }
+
+ return &pioutil.ReaderAndCloser{
+ Reader: io.MultiReader(buf, merged.ReadCloser),
+ Closer: merged.ReadCloser,
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/stream.go b/vendor/github.com/coreos/etcd/rafthttp/stream.go
new file mode 100644
index 00000000..af49c18b
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/stream.go
@@ -0,0 +1,533 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "path"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/time/rate"
+
+ "github.com/coreos/etcd/etcdserver/stats"
+ "github.com/coreos/etcd/pkg/httputil"
+ "github.com/coreos/etcd/pkg/transport"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/version"
+ "github.com/coreos/go-semver/semver"
+)
+
+const (
+ streamTypeMessage streamType = "message"
+ streamTypeMsgAppV2 streamType = "msgappv2"
+
+ streamBufSize = 4096
+)
+
+var (
+ errUnsupportedStreamType = fmt.Errorf("unsupported stream type")
+
+ // the key is in string format "major.minor.patch"
+ supportedStream = map[string][]streamType{
+ "2.0.0": {},
+ "2.1.0": {streamTypeMsgAppV2, streamTypeMessage},
+ "2.2.0": {streamTypeMsgAppV2, streamTypeMessage},
+ "2.3.0": {streamTypeMsgAppV2, streamTypeMessage},
+ "3.0.0": {streamTypeMsgAppV2, streamTypeMessage},
+ "3.1.0": {streamTypeMsgAppV2, streamTypeMessage},
+ "3.2.0": {streamTypeMsgAppV2, streamTypeMessage},
+ "3.3.0": {streamTypeMsgAppV2, streamTypeMessage},
+ }
+)
+
+type streamType string
+
+func (t streamType) endpoint() string {
+ switch t {
+ case streamTypeMsgAppV2:
+ return path.Join(RaftStreamPrefix, "msgapp")
+ case streamTypeMessage:
+ return path.Join(RaftStreamPrefix, "message")
+ default:
+ plog.Panicf("unhandled stream type %v", t)
+ return ""
+ }
+}
+
+func (t streamType) String() string {
+ switch t {
+ case streamTypeMsgAppV2:
+ return "stream MsgApp v2"
+ case streamTypeMessage:
+ return "stream Message"
+ default:
+ return "unknown stream"
+ }
+}
+
+var (
+ // linkHeartbeatMessage is a special message used as heartbeat message in
+ // link layer. It never conflicts with messages from raft because raft
+ // doesn't send out messages without From and To fields.
+ linkHeartbeatMessage = raftpb.Message{Type: raftpb.MsgHeartbeat}
+)
+
+func isLinkHeartbeatMessage(m *raftpb.Message) bool {
+ return m.Type == raftpb.MsgHeartbeat && m.From == 0 && m.To == 0
+}
+
+type outgoingConn struct {
+ t streamType
+ io.Writer
+ http.Flusher
+ io.Closer
+}
+
+// streamWriter writes messages to the attached outgoingConn.
+type streamWriter struct {
+ peerID types.ID
+ status *peerStatus
+ fs *stats.FollowerStats
+ r Raft
+
+ mu sync.Mutex // guard field working and closer
+ closer io.Closer
+ working bool
+
+ msgc chan raftpb.Message
+ connc chan *outgoingConn
+ stopc chan struct{}
+ done chan struct{}
+}
+
+// startStreamWriter creates a streamWrite and starts a long running go-routine that accepts
+// messages and writes to the attached outgoing connection.
+func startStreamWriter(id types.ID, status *peerStatus, fs *stats.FollowerStats, r Raft) *streamWriter {
+ w := &streamWriter{
+ peerID: id,
+ status: status,
+ fs: fs,
+ r: r,
+ msgc: make(chan raftpb.Message, streamBufSize),
+ connc: make(chan *outgoingConn),
+ stopc: make(chan struct{}),
+ done: make(chan struct{}),
+ }
+ go w.run()
+ return w
+}
+
+func (cw *streamWriter) run() {
+ var (
+ msgc chan raftpb.Message
+ heartbeatc <-chan time.Time
+ t streamType
+ enc encoder
+ flusher http.Flusher
+ batched int
+ )
+ tickc := time.NewTicker(ConnReadTimeout / 3)
+ defer tickc.Stop()
+ unflushed := 0
+
+ plog.Infof("started streaming with peer %s (writer)", cw.peerID)
+
+ for {
+ select {
+ case <-heartbeatc:
+ err := enc.encode(&linkHeartbeatMessage)
+ unflushed += linkHeartbeatMessage.Size()
+ if err == nil {
+ flusher.Flush()
+ batched = 0
+ sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
+ unflushed = 0
+ continue
+ }
+
+ cw.status.deactivate(failureType{source: t.String(), action: "heartbeat"}, err.Error())
+
+ sentFailures.WithLabelValues(cw.peerID.String()).Inc()
+ cw.close()
+ plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
+ heartbeatc, msgc = nil, nil
+
+ case m := <-msgc:
+ err := enc.encode(&m)
+ if err == nil {
+ unflushed += m.Size()
+
+ if len(msgc) == 0 || batched > streamBufSize/2 {
+ flusher.Flush()
+ sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
+ unflushed = 0
+ batched = 0
+ } else {
+ batched++
+ }
+
+ continue
+ }
+
+ cw.status.deactivate(failureType{source: t.String(), action: "write"}, err.Error())
+ cw.close()
+ plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
+ heartbeatc, msgc = nil, nil
+ cw.r.ReportUnreachable(m.To)
+ sentFailures.WithLabelValues(cw.peerID.String()).Inc()
+
+ case conn := <-cw.connc:
+ cw.mu.Lock()
+ closed := cw.closeUnlocked()
+ t = conn.t
+ switch conn.t {
+ case streamTypeMsgAppV2:
+ enc = newMsgAppV2Encoder(conn.Writer, cw.fs)
+ case streamTypeMessage:
+ enc = &messageEncoder{w: conn.Writer}
+ default:
+ plog.Panicf("unhandled stream type %s", conn.t)
+ }
+ flusher = conn.Flusher
+ unflushed = 0
+ cw.status.activate()
+ cw.closer = conn.Closer
+ cw.working = true
+ cw.mu.Unlock()
+
+ if closed {
+ plog.Warningf("closed an existing TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
+ }
+ plog.Infof("established a TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
+ heartbeatc, msgc = tickc.C, cw.msgc
+ case <-cw.stopc:
+ if cw.close() {
+ plog.Infof("closed the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
+ }
+ plog.Infof("stopped streaming with peer %s (writer)", cw.peerID)
+ close(cw.done)
+ return
+ }
+ }
+}
+
+func (cw *streamWriter) writec() (chan<- raftpb.Message, bool) {
+ cw.mu.Lock()
+ defer cw.mu.Unlock()
+ return cw.msgc, cw.working
+}
+
+func (cw *streamWriter) close() bool {
+ cw.mu.Lock()
+ defer cw.mu.Unlock()
+ return cw.closeUnlocked()
+}
+
+func (cw *streamWriter) closeUnlocked() bool {
+ if !cw.working {
+ return false
+ }
+ if err := cw.closer.Close(); err != nil {
+ plog.Errorf("peer %s (writer) connection close error: %v", cw.peerID, err)
+ }
+ if len(cw.msgc) > 0 {
+ cw.r.ReportUnreachable(uint64(cw.peerID))
+ }
+ cw.msgc = make(chan raftpb.Message, streamBufSize)
+ cw.working = false
+ return true
+}
+
+func (cw *streamWriter) attach(conn *outgoingConn) bool {
+ select {
+ case cw.connc <- conn:
+ return true
+ case <-cw.done:
+ return false
+ }
+}
+
+func (cw *streamWriter) stop() {
+ close(cw.stopc)
+ <-cw.done
+}
+
+// streamReader is a long-running go-routine that dials to the remote stream
+// endpoint and reads messages from the response body returned.
+type streamReader struct {
+ peerID types.ID
+ typ streamType
+
+ tr *Transport
+ picker *urlPicker
+ status *peerStatus
+ recvc chan<- raftpb.Message
+ propc chan<- raftpb.Message
+
+ rl *rate.Limiter // alters the frequency of dial retrial attempts
+
+ errorc chan<- error
+
+ mu sync.Mutex
+ paused bool
+ closer io.Closer
+
+ ctx context.Context
+ cancel context.CancelFunc
+ done chan struct{}
+}
+
+func (cr *streamReader) start() {
+ cr.done = make(chan struct{})
+ if cr.errorc == nil {
+ cr.errorc = cr.tr.ErrorC
+ }
+ if cr.ctx == nil {
+ cr.ctx, cr.cancel = context.WithCancel(context.Background())
+ }
+ go cr.run()
+}
+
+func (cr *streamReader) run() {
+ t := cr.typ
+ plog.Infof("started streaming with peer %s (%s reader)", cr.peerID, t)
+ for {
+ rc, err := cr.dial(t)
+ if err != nil {
+ if err != errUnsupportedStreamType {
+ cr.status.deactivate(failureType{source: t.String(), action: "dial"}, err.Error())
+ }
+ } else {
+ cr.status.activate()
+ plog.Infof("established a TCP streaming connection with peer %s (%s reader)", cr.peerID, cr.typ)
+ err = cr.decodeLoop(rc, t)
+ plog.Warningf("lost the TCP streaming connection with peer %s (%s reader)", cr.peerID, cr.typ)
+ switch {
+ // all data is read out
+ case err == io.EOF:
+ // connection is closed by the remote
+ case transport.IsClosedConnError(err):
+ default:
+ cr.status.deactivate(failureType{source: t.String(), action: "read"}, err.Error())
+ }
+ }
+ // Wait for a while before new dial attempt
+ err = cr.rl.Wait(cr.ctx)
+ if cr.ctx.Err() != nil {
+ plog.Infof("stopped streaming with peer %s (%s reader)", cr.peerID, t)
+ close(cr.done)
+ return
+ }
+ if err != nil {
+ plog.Errorf("streaming with peer %s (%s reader) rate limiter error: %v", cr.peerID, t, err)
+ }
+ }
+}
+
+func (cr *streamReader) decodeLoop(rc io.ReadCloser, t streamType) error {
+ var dec decoder
+ cr.mu.Lock()
+ switch t {
+ case streamTypeMsgAppV2:
+ dec = newMsgAppV2Decoder(rc, cr.tr.ID, cr.peerID)
+ case streamTypeMessage:
+ dec = &messageDecoder{r: rc}
+ default:
+ plog.Panicf("unhandled stream type %s", t)
+ }
+ select {
+ case <-cr.ctx.Done():
+ cr.mu.Unlock()
+ if err := rc.Close(); err != nil {
+ return err
+ }
+ return io.EOF
+ default:
+ cr.closer = rc
+ }
+ cr.mu.Unlock()
+
+ for {
+ m, err := dec.decode()
+ if err != nil {
+ cr.mu.Lock()
+ cr.close()
+ cr.mu.Unlock()
+ return err
+ }
+
+ receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(m.Size()))
+
+ cr.mu.Lock()
+ paused := cr.paused
+ cr.mu.Unlock()
+
+ if paused {
+ continue
+ }
+
+ if isLinkHeartbeatMessage(&m) {
+ // raft is not interested in link layer
+ // heartbeat message, so we should ignore
+ // it.
+ continue
+ }
+
+ recvc := cr.recvc
+ if m.Type == raftpb.MsgProp {
+ recvc = cr.propc
+ }
+
+ select {
+ case recvc <- m:
+ default:
+ if cr.status.isActive() {
+ plog.MergeWarningf("dropped internal raft message from %s since receiving buffer is full (overloaded network)", types.ID(m.From))
+ }
+ plog.Debugf("dropped %s from %s since receiving buffer is full", m.Type, types.ID(m.From))
+ recvFailures.WithLabelValues(types.ID(m.From).String()).Inc()
+ }
+ }
+}
+
+func (cr *streamReader) stop() {
+ cr.mu.Lock()
+ cr.cancel()
+ cr.close()
+ cr.mu.Unlock()
+ <-cr.done
+}
+
+func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
+ u := cr.picker.pick()
+ uu := u
+ uu.Path = path.Join(t.endpoint(), cr.tr.ID.String())
+
+ req, err := http.NewRequest("GET", uu.String(), nil)
+ if err != nil {
+ cr.picker.unreachable(u)
+ return nil, fmt.Errorf("failed to make http request to %v (%v)", u, err)
+ }
+ req.Header.Set("X-Server-From", cr.tr.ID.String())
+ req.Header.Set("X-Server-Version", version.Version)
+ req.Header.Set("X-Min-Cluster-Version", version.MinClusterVersion)
+ req.Header.Set("X-Etcd-Cluster-ID", cr.tr.ClusterID.String())
+ req.Header.Set("X-Raft-To", cr.peerID.String())
+
+ setPeerURLsHeader(req, cr.tr.URLs)
+
+ req = req.WithContext(cr.ctx)
+
+ cr.mu.Lock()
+ select {
+ case <-cr.ctx.Done():
+ cr.mu.Unlock()
+ return nil, fmt.Errorf("stream reader is stopped")
+ default:
+ }
+ cr.mu.Unlock()
+
+ resp, err := cr.tr.streamRt.RoundTrip(req)
+ if err != nil {
+ cr.picker.unreachable(u)
+ return nil, err
+ }
+
+ rv := serverVersion(resp.Header)
+ lv := semver.Must(semver.NewVersion(version.Version))
+ if compareMajorMinorVersion(rv, lv) == -1 && !checkStreamSupport(rv, t) {
+ httputil.GracefulClose(resp)
+ cr.picker.unreachable(u)
+ return nil, errUnsupportedStreamType
+ }
+
+ switch resp.StatusCode {
+ case http.StatusGone:
+ httputil.GracefulClose(resp)
+ cr.picker.unreachable(u)
+ reportCriticalError(errMemberRemoved, cr.errorc)
+ return nil, errMemberRemoved
+ case http.StatusOK:
+ return resp.Body, nil
+ case http.StatusNotFound:
+ httputil.GracefulClose(resp)
+ cr.picker.unreachable(u)
+ return nil, fmt.Errorf("peer %s failed to find local node %s", cr.peerID, cr.tr.ID)
+ case http.StatusPreconditionFailed:
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ cr.picker.unreachable(u)
+ return nil, err
+ }
+ httputil.GracefulClose(resp)
+ cr.picker.unreachable(u)
+
+ switch strings.TrimSuffix(string(b), "\n") {
+ case errIncompatibleVersion.Error():
+ plog.Errorf("request sent was ignored by peer %s (server version incompatible)", cr.peerID)
+ return nil, errIncompatibleVersion
+ case errClusterIDMismatch.Error():
+ plog.Errorf("request sent was ignored (cluster ID mismatch: peer[%s]=%s, local=%s)",
+ cr.peerID, resp.Header.Get("X-Etcd-Cluster-ID"), cr.tr.ClusterID)
+ return nil, errClusterIDMismatch
+ default:
+ return nil, fmt.Errorf("unhandled error %q when precondition failed", string(b))
+ }
+ default:
+ httputil.GracefulClose(resp)
+ cr.picker.unreachable(u)
+ return nil, fmt.Errorf("unhandled http status %d", resp.StatusCode)
+ }
+}
+
+func (cr *streamReader) close() {
+ if cr.closer != nil {
+ if err := cr.closer.Close(); err != nil {
+ plog.Errorf("peer %s (reader) connection close error: %v", cr.peerID, err)
+ }
+ }
+ cr.closer = nil
+}
+
+func (cr *streamReader) pause() {
+ cr.mu.Lock()
+ defer cr.mu.Unlock()
+ cr.paused = true
+}
+
+func (cr *streamReader) resume() {
+ cr.mu.Lock()
+ defer cr.mu.Unlock()
+ cr.paused = false
+}
+
+// checkStreamSupport checks whether the stream type is supported in the
+// given version.
+func checkStreamSupport(v *semver.Version, t streamType) bool {
+ nv := &semver.Version{Major: v.Major, Minor: v.Minor}
+ for _, s := range supportedStream[nv.String()] {
+ if s == t {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/transport.go b/vendor/github.com/coreos/etcd/rafthttp/transport.go
new file mode 100644
index 00000000..ce734330
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/transport.go
@@ -0,0 +1,432 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "context"
+ "net/http"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/etcdserver/stats"
+ "github.com/coreos/etcd/pkg/logutil"
+ "github.com/coreos/etcd/pkg/transport"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/snap"
+
+ "github.com/coreos/pkg/capnslog"
+ "github.com/xiang90/probing"
+ "golang.org/x/time/rate"
+)
+
+var plog = logutil.NewMergeLogger(capnslog.NewPackageLogger("github.com/coreos/etcd", "rafthttp"))
+
+type Raft interface {
+ Process(ctx context.Context, m raftpb.Message) error
+ IsIDRemoved(id uint64) bool
+ ReportUnreachable(id uint64)
+ ReportSnapshot(id uint64, status raft.SnapshotStatus)
+}
+
+type Transporter interface {
+ // Start starts the given Transporter.
+ // Start MUST be called before calling other functions in the interface.
+ Start() error
+ // Handler returns the HTTP handler of the transporter.
+ // A transporter HTTP handler handles the HTTP requests
+ // from remote peers.
+ // The handler MUST be used to handle RaftPrefix(/raft)
+ // endpoint.
+ Handler() http.Handler
+ // Send sends out the given messages to the remote peers.
+ // Each message has a To field, which is an id that maps
+ // to an existing peer in the transport.
+ // If the id cannot be found in the transport, the message
+ // will be ignored.
+ Send(m []raftpb.Message)
+ // SendSnapshot sends out the given snapshot message to a remote peer.
+ // The behavior of SendSnapshot is similar to Send.
+ SendSnapshot(m snap.Message)
+ // AddRemote adds a remote with given peer urls into the transport.
+ // A remote helps newly joined member to catch up the progress of cluster,
+ // and will not be used after that.
+ // It is the caller's responsibility to ensure the urls are all valid,
+ // or it panics.
+ AddRemote(id types.ID, urls []string)
+ // AddPeer adds a peer with given peer urls into the transport.
+ // It is the caller's responsibility to ensure the urls are all valid,
+ // or it panics.
+ // Peer urls are used to connect to the remote peer.
+ AddPeer(id types.ID, urls []string)
+ // RemovePeer removes the peer with given id.
+ RemovePeer(id types.ID)
+ // RemoveAllPeers removes all the existing peers in the transport.
+ RemoveAllPeers()
+ // UpdatePeer updates the peer urls of the peer with the given id.
+ // It is the caller's responsibility to ensure the urls are all valid,
+ // or it panics.
+ UpdatePeer(id types.ID, urls []string)
+ // ActiveSince returns the time that the connection with the peer
+ // of the given id becomes active.
+ // If the connection is active since peer was added, it returns the adding time.
+ // If the connection is currently inactive, it returns zero time.
+ ActiveSince(id types.ID) time.Time
+ // ActivePeers returns the number of active peers.
+ ActivePeers() int
+ // Stop closes the connections and stops the transporter.
+ Stop()
+}
+
+// Transport implements Transporter interface. It provides the functionality
+// to send raft messages to peers, and receive raft messages from peers.
+// User should call Handler method to get a handler to serve requests
+// received from peerURLs.
+// User needs to call Start before calling other functions, and call
+// Stop when the Transport is no longer used.
+type Transport struct {
+ DialTimeout time.Duration // maximum duration before timing out dial of the request
+ // DialRetryFrequency defines the frequency of streamReader dial retrial attempts;
+ // a distinct rate limiter is created per every peer (default value: 10 events/sec)
+ DialRetryFrequency rate.Limit
+
+ TLSInfo transport.TLSInfo // TLS information used when creating connection
+
+ ID types.ID // local member ID
+ URLs types.URLs // local peer URLs
+ ClusterID types.ID // raft cluster ID for request validation
+ Raft Raft // raft state machine, to which the Transport forwards received messages and reports status
+ Snapshotter *snap.Snapshotter
+ ServerStats *stats.ServerStats // used to record general transportation statistics
+ // used to record transportation statistics with followers when
+ // performing as leader in raft protocol
+ LeaderStats *stats.LeaderStats
+ // ErrorC is used to report detected critical errors, e.g.,
+ // the member has been permanently removed from the cluster
+ // When an error is received from ErrorC, user should stop raft state
+ // machine and thus stop the Transport.
+ ErrorC chan error
+
+ streamRt http.RoundTripper // roundTripper used by streams
+ pipelineRt http.RoundTripper // roundTripper used by pipelines
+
+ mu sync.RWMutex // protect the remote and peer map
+ remotes map[types.ID]*remote // remotes map that helps newly joined member to catch up
+ peers map[types.ID]Peer // peers map
+
+ prober probing.Prober
+}
+
+func (t *Transport) Start() error {
+ var err error
+ t.streamRt, err = newStreamRoundTripper(t.TLSInfo, t.DialTimeout)
+ if err != nil {
+ return err
+ }
+ t.pipelineRt, err = NewRoundTripper(t.TLSInfo, t.DialTimeout)
+ if err != nil {
+ return err
+ }
+ t.remotes = make(map[types.ID]*remote)
+ t.peers = make(map[types.ID]Peer)
+ t.prober = probing.NewProber(t.pipelineRt)
+
+ // If client didn't provide dial retry frequency, use the default
+ // (100ms backoff between attempts to create a new stream),
+ // so it doesn't bring too much overhead when retry.
+ if t.DialRetryFrequency == 0 {
+ t.DialRetryFrequency = rate.Every(100 * time.Millisecond)
+ }
+ return nil
+}
+
+func (t *Transport) Handler() http.Handler {
+ pipelineHandler := newPipelineHandler(t, t.Raft, t.ClusterID)
+ streamHandler := newStreamHandler(t, t, t.Raft, t.ID, t.ClusterID)
+ snapHandler := newSnapshotHandler(t, t.Raft, t.Snapshotter, t.ClusterID)
+ mux := http.NewServeMux()
+ mux.Handle(RaftPrefix, pipelineHandler)
+ mux.Handle(RaftStreamPrefix+"/", streamHandler)
+ mux.Handle(RaftSnapshotPrefix, snapHandler)
+ mux.Handle(ProbingPrefix, probing.NewHandler())
+ return mux
+}
+
+func (t *Transport) Get(id types.ID) Peer {
+ t.mu.RLock()
+ defer t.mu.RUnlock()
+ return t.peers[id]
+}
+
+func (t *Transport) Send(msgs []raftpb.Message) {
+ for _, m := range msgs {
+ if m.To == 0 {
+ // ignore intentionally dropped message
+ continue
+ }
+ to := types.ID(m.To)
+
+ t.mu.RLock()
+ p, pok := t.peers[to]
+ g, rok := t.remotes[to]
+ t.mu.RUnlock()
+
+ if pok {
+ if m.Type == raftpb.MsgApp {
+ t.ServerStats.SendAppendReq(m.Size())
+ }
+ p.send(m)
+ continue
+ }
+
+ if rok {
+ g.send(m)
+ continue
+ }
+
+ plog.Debugf("ignored message %s (sent to unknown peer %s)", m.Type, to)
+ }
+}
+
+func (t *Transport) Stop() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ for _, r := range t.remotes {
+ r.stop()
+ }
+ for _, p := range t.peers {
+ p.stop()
+ }
+ t.prober.RemoveAll()
+ if tr, ok := t.streamRt.(*http.Transport); ok {
+ tr.CloseIdleConnections()
+ }
+ if tr, ok := t.pipelineRt.(*http.Transport); ok {
+ tr.CloseIdleConnections()
+ }
+ t.peers = nil
+ t.remotes = nil
+}
+
+// CutPeer drops messages to the specified peer.
+func (t *Transport) CutPeer(id types.ID) {
+ t.mu.RLock()
+ p, pok := t.peers[id]
+ g, gok := t.remotes[id]
+ t.mu.RUnlock()
+
+ if pok {
+ p.(Pausable).Pause()
+ }
+ if gok {
+ g.Pause()
+ }
+}
+
+// MendPeer recovers the message dropping behavior of the given peer.
+func (t *Transport) MendPeer(id types.ID) {
+ t.mu.RLock()
+ p, pok := t.peers[id]
+ g, gok := t.remotes[id]
+ t.mu.RUnlock()
+
+ if pok {
+ p.(Pausable).Resume()
+ }
+ if gok {
+ g.Resume()
+ }
+}
+
+func (t *Transport) AddRemote(id types.ID, us []string) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.remotes == nil {
+ // there's no clean way to shutdown the golang http server
+ // (see: https://github.com/golang/go/issues/4674) before
+ // stopping the transport; ignore any new connections.
+ return
+ }
+ if _, ok := t.peers[id]; ok {
+ return
+ }
+ if _, ok := t.remotes[id]; ok {
+ return
+ }
+ urls, err := types.NewURLs(us)
+ if err != nil {
+ plog.Panicf("newURLs %+v should never fail: %+v", us, err)
+ }
+ t.remotes[id] = startRemote(t, urls, id)
+}
+
+func (t *Transport) AddPeer(id types.ID, us []string) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+
+ if t.peers == nil {
+ panic("transport stopped")
+ }
+ if _, ok := t.peers[id]; ok {
+ return
+ }
+ urls, err := types.NewURLs(us)
+ if err != nil {
+ plog.Panicf("newURLs %+v should never fail: %+v", us, err)
+ }
+ fs := t.LeaderStats.Follower(id.String())
+ t.peers[id] = startPeer(t, urls, id, fs)
+ addPeerToProber(t.prober, id.String(), us)
+
+ plog.Infof("added peer %s", id)
+}
+
+func (t *Transport) RemovePeer(id types.ID) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.removePeer(id)
+}
+
+func (t *Transport) RemoveAllPeers() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ for id := range t.peers {
+ t.removePeer(id)
+ }
+}
+
+// the caller of this function must have the peers mutex.
+func (t *Transport) removePeer(id types.ID) {
+ if peer, ok := t.peers[id]; ok {
+ peer.stop()
+ } else {
+ plog.Panicf("unexpected removal of unknown peer '%d'", id)
+ }
+ delete(t.peers, id)
+ delete(t.LeaderStats.Followers, id.String())
+ t.prober.Remove(id.String())
+ plog.Infof("removed peer %s", id)
+}
+
+func (t *Transport) UpdatePeer(id types.ID, us []string) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ // TODO: return error or just panic?
+ if _, ok := t.peers[id]; !ok {
+ return
+ }
+ urls, err := types.NewURLs(us)
+ if err != nil {
+ plog.Panicf("newURLs %+v should never fail: %+v", us, err)
+ }
+ t.peers[id].update(urls)
+
+ t.prober.Remove(id.String())
+ addPeerToProber(t.prober, id.String(), us)
+ plog.Infof("updated peer %s", id)
+}
+
+func (t *Transport) ActiveSince(id types.ID) time.Time {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if p, ok := t.peers[id]; ok {
+ return p.activeSince()
+ }
+ return time.Time{}
+}
+
+func (t *Transport) SendSnapshot(m snap.Message) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ p := t.peers[types.ID(m.To)]
+ if p == nil {
+ m.CloseWithError(errMemberNotFound)
+ return
+ }
+ p.sendSnap(m)
+}
+
+// Pausable is a testing interface for pausing transport traffic.
+type Pausable interface {
+ Pause()
+ Resume()
+}
+
+func (t *Transport) Pause() {
+ for _, p := range t.peers {
+ p.(Pausable).Pause()
+ }
+}
+
+func (t *Transport) Resume() {
+ for _, p := range t.peers {
+ p.(Pausable).Resume()
+ }
+}
+
+// ActivePeers returns a channel that closes when an initial
+// peer connection has been established. Use this to wait until the
+// first peer connection becomes active.
+func (t *Transport) ActivePeers() (cnt int) {
+ t.mu.RLock()
+ defer t.mu.RUnlock()
+ for _, p := range t.peers {
+ if !p.activeSince().IsZero() {
+ cnt++
+ }
+ }
+ return cnt
+}
+
+type nopTransporter struct{}
+
+func NewNopTransporter() Transporter {
+ return &nopTransporter{}
+}
+
+func (s *nopTransporter) Start() error { return nil }
+func (s *nopTransporter) Handler() http.Handler { return nil }
+func (s *nopTransporter) Send(m []raftpb.Message) {}
+func (s *nopTransporter) SendSnapshot(m snap.Message) {}
+func (s *nopTransporter) AddRemote(id types.ID, us []string) {}
+func (s *nopTransporter) AddPeer(id types.ID, us []string) {}
+func (s *nopTransporter) RemovePeer(id types.ID) {}
+func (s *nopTransporter) RemoveAllPeers() {}
+func (s *nopTransporter) UpdatePeer(id types.ID, us []string) {}
+func (s *nopTransporter) ActiveSince(id types.ID) time.Time { return time.Time{} }
+func (s *nopTransporter) ActivePeers() int { return 0 }
+func (s *nopTransporter) Stop() {}
+func (s *nopTransporter) Pause() {}
+func (s *nopTransporter) Resume() {}
+
+type snapTransporter struct {
+ nopTransporter
+ snapDoneC chan snap.Message
+ snapDir string
+}
+
+func NewSnapTransporter(snapDir string) (Transporter, <-chan snap.Message) {
+ ch := make(chan snap.Message, 1)
+ tr := &snapTransporter{snapDoneC: ch, snapDir: snapDir}
+ return tr, ch
+}
+
+func (s *snapTransporter) SendSnapshot(m snap.Message) {
+ ss := snap.New(s.snapDir)
+ ss.SaveDBFrom(m.ReadCloser, m.Snapshot.Metadata.Index+1)
+ m.CloseWithError(nil)
+ s.snapDoneC <- m
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/urlpick.go b/vendor/github.com/coreos/etcd/rafthttp/urlpick.go
new file mode 100644
index 00000000..61839dee
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/urlpick.go
@@ -0,0 +1,57 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "net/url"
+ "sync"
+
+ "github.com/coreos/etcd/pkg/types"
+)
+
+type urlPicker struct {
+ mu sync.Mutex // guards urls and picked
+ urls types.URLs
+ picked int
+}
+
+func newURLPicker(urls types.URLs) *urlPicker {
+ return &urlPicker{
+ urls: urls,
+ }
+}
+
+func (p *urlPicker) update(urls types.URLs) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ p.urls = urls
+ p.picked = 0
+}
+
+func (p *urlPicker) pick() url.URL {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ return p.urls[p.picked]
+}
+
+// unreachable notices the picker that the given url is unreachable,
+// and it should use other possible urls.
+func (p *urlPicker) unreachable(u url.URL) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if u == p.urls[p.picked] {
+ p.picked = (p.picked + 1) % len(p.urls)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/rafthttp/util.go b/vendor/github.com/coreos/etcd/rafthttp/util.go
new file mode 100644
index 00000000..6ec3641a
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/rafthttp/util.go
@@ -0,0 +1,186 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rafthttp
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "github.com/coreos/etcd/pkg/transport"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/coreos/etcd/version"
+ "github.com/coreos/go-semver/semver"
+)
+
+var (
+ errMemberRemoved = fmt.Errorf("the member has been permanently removed from the cluster")
+ errMemberNotFound = fmt.Errorf("member not found")
+)
+
+// NewListener returns a listener for raft message transfer between peers.
+// It uses timeout listener to identify broken streams promptly.
+func NewListener(u url.URL, tlsinfo *transport.TLSInfo) (net.Listener, error) {
+ return transport.NewTimeoutListener(u.Host, u.Scheme, tlsinfo, ConnReadTimeout, ConnWriteTimeout)
+}
+
+// NewRoundTripper returns a roundTripper used to send requests
+// to rafthttp listener of remote peers.
+func NewRoundTripper(tlsInfo transport.TLSInfo, dialTimeout time.Duration) (http.RoundTripper, error) {
+ // It uses timeout transport to pair with remote timeout listeners.
+ // It sets no read/write timeout, because message in requests may
+ // take long time to write out before reading out the response.
+ return transport.NewTimeoutTransport(tlsInfo, dialTimeout, 0, 0)
+}
+
+// newStreamRoundTripper returns a roundTripper used to send stream requests
+// to rafthttp listener of remote peers.
+// Read/write timeout is set for stream roundTripper to promptly
+// find out broken status, which minimizes the number of messages
+// sent on broken connection.
+func newStreamRoundTripper(tlsInfo transport.TLSInfo, dialTimeout time.Duration) (http.RoundTripper, error) {
+ return transport.NewTimeoutTransport(tlsInfo, dialTimeout, ConnReadTimeout, ConnWriteTimeout)
+}
+
+// createPostRequest creates a HTTP POST request that sends raft message.
+func createPostRequest(u url.URL, path string, body io.Reader, ct string, urls types.URLs, from, cid types.ID) *http.Request {
+ uu := u
+ uu.Path = path
+ req, err := http.NewRequest("POST", uu.String(), body)
+ if err != nil {
+ plog.Panicf("unexpected new request error (%v)", err)
+ }
+ req.Header.Set("Content-Type", ct)
+ req.Header.Set("X-Server-From", from.String())
+ req.Header.Set("X-Server-Version", version.Version)
+ req.Header.Set("X-Min-Cluster-Version", version.MinClusterVersion)
+ req.Header.Set("X-Etcd-Cluster-ID", cid.String())
+ setPeerURLsHeader(req, urls)
+
+ return req
+}
+
+// checkPostResponse checks the response of the HTTP POST request that sends
+// raft message.
+func checkPostResponse(resp *http.Response, body []byte, req *http.Request, to types.ID) error {
+ switch resp.StatusCode {
+ case http.StatusPreconditionFailed:
+ switch strings.TrimSuffix(string(body), "\n") {
+ case errIncompatibleVersion.Error():
+ plog.Errorf("request sent was ignored by peer %s (server version incompatible)", to)
+ return errIncompatibleVersion
+ case errClusterIDMismatch.Error():
+ plog.Errorf("request sent was ignored (cluster ID mismatch: remote[%s]=%s, local=%s)",
+ to, resp.Header.Get("X-Etcd-Cluster-ID"), req.Header.Get("X-Etcd-Cluster-ID"))
+ return errClusterIDMismatch
+ default:
+ return fmt.Errorf("unhandled error %q when precondition failed", string(body))
+ }
+ case http.StatusForbidden:
+ return errMemberRemoved
+ case http.StatusNoContent:
+ return nil
+ default:
+ return fmt.Errorf("unexpected http status %s while posting to %q", http.StatusText(resp.StatusCode), req.URL.String())
+ }
+}
+
+// reportCriticalError reports the given error through sending it into
+// the given error channel.
+// If the error channel is filled up when sending error, it drops the error
+// because the fact that error has happened is reported, which is
+// good enough.
+func reportCriticalError(err error, errc chan<- error) {
+ select {
+ case errc <- err:
+ default:
+ }
+}
+
+// compareMajorMinorVersion returns an integer comparing two versions based on
+// their major and minor version. The result will be 0 if a==b, -1 if a < b,
+// and 1 if a > b.
+func compareMajorMinorVersion(a, b *semver.Version) int {
+ na := &semver.Version{Major: a.Major, Minor: a.Minor}
+ nb := &semver.Version{Major: b.Major, Minor: b.Minor}
+ switch {
+ case na.LessThan(*nb):
+ return -1
+ case nb.LessThan(*na):
+ return 1
+ default:
+ return 0
+ }
+}
+
+// serverVersion returns the server version from the given header.
+func serverVersion(h http.Header) *semver.Version {
+ verStr := h.Get("X-Server-Version")
+ // backward compatibility with etcd 2.0
+ if verStr == "" {
+ verStr = "2.0.0"
+ }
+ return semver.Must(semver.NewVersion(verStr))
+}
+
+// serverVersion returns the min cluster version from the given header.
+func minClusterVersion(h http.Header) *semver.Version {
+ verStr := h.Get("X-Min-Cluster-Version")
+ // backward compatibility with etcd 2.0
+ if verStr == "" {
+ verStr = "2.0.0"
+ }
+ return semver.Must(semver.NewVersion(verStr))
+}
+
+// checkVersionCompability checks whether the given version is compatible
+// with the local version.
+func checkVersionCompability(name string, server, minCluster *semver.Version) error {
+ localServer := semver.Must(semver.NewVersion(version.Version))
+ localMinCluster := semver.Must(semver.NewVersion(version.MinClusterVersion))
+ if compareMajorMinorVersion(server, localMinCluster) == -1 {
+ return fmt.Errorf("remote version is too low: remote[%s]=%s, local=%s", name, server, localServer)
+ }
+ if compareMajorMinorVersion(minCluster, localServer) == 1 {
+ return fmt.Errorf("local version is too low: remote[%s]=%s, local=%s", name, server, localServer)
+ }
+ return nil
+}
+
+// setPeerURLsHeader reports local urls for peer discovery
+func setPeerURLsHeader(req *http.Request, urls types.URLs) {
+ if urls == nil {
+ // often not set in unit tests
+ return
+ }
+ peerURLs := make([]string, urls.Len())
+ for i := range urls {
+ peerURLs[i] = urls[i].String()
+ }
+ req.Header.Set("X-PeerURLs", strings.Join(peerURLs, ","))
+}
+
+// addRemoteFromRequest adds a remote peer according to an http request header
+func addRemoteFromRequest(tr Transporter, r *http.Request) {
+ if from, err := types.IDFromString(r.Header.Get("X-Server-From")); err == nil {
+ if urls := r.Header.Get("X-PeerURLs"); urls != "" {
+ tr.AddRemote(from, strings.Split(urls, ","))
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/snap/db.go b/vendor/github.com/coreos/etcd/snap/db.go
new file mode 100644
index 00000000..01d897ae
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/snap/db.go
@@ -0,0 +1,77 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package snap
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+
+ "github.com/coreos/etcd/pkg/fileutil"
+)
+
+var ErrNoDBSnapshot = errors.New("snap: snapshot file doesn't exist")
+
+// SaveDBFrom saves snapshot of the database from the given reader. It
+// guarantees the save operation is atomic.
+func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
+ f, err := ioutil.TempFile(s.dir, "tmp")
+ if err != nil {
+ return 0, err
+ }
+ var n int64
+ n, err = io.Copy(f, r)
+ if err == nil {
+ err = fileutil.Fsync(f)
+ }
+ f.Close()
+ if err != nil {
+ os.Remove(f.Name())
+ return n, err
+ }
+ fn := s.dbFilePath(id)
+ if fileutil.Exist(fn) {
+ os.Remove(f.Name())
+ return n, nil
+ }
+ err = os.Rename(f.Name(), fn)
+ if err != nil {
+ os.Remove(f.Name())
+ return n, err
+ }
+
+ plog.Infof("saved database snapshot to disk [total bytes: %d]", n)
+
+ return n, nil
+}
+
+// DBFilePath returns the file path for the snapshot of the database with
+// given id. If the snapshot does not exist, it returns error.
+func (s *Snapshotter) DBFilePath(id uint64) (string, error) {
+ if _, err := fileutil.ReadDir(s.dir); err != nil {
+ return "", err
+ }
+ if fn := s.dbFilePath(id); fileutil.Exist(fn) {
+ return fn, nil
+ }
+ return "", ErrNoDBSnapshot
+}
+
+func (s *Snapshotter) dbFilePath(id uint64) string {
+ return filepath.Join(s.dir, fmt.Sprintf("%016x.snap.db", id))
+}
diff --git a/vendor/github.com/coreos/etcd/snap/message.go b/vendor/github.com/coreos/etcd/snap/message.go
new file mode 100644
index 00000000..d73713ff
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/snap/message.go
@@ -0,0 +1,64 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package snap
+
+import (
+ "io"
+
+ "github.com/coreos/etcd/pkg/ioutil"
+ "github.com/coreos/etcd/raft/raftpb"
+)
+
+// Message is a struct that contains a raft Message and a ReadCloser. The type
+// of raft message MUST be MsgSnap, which contains the raft meta-data and an
+// additional data []byte field that contains the snapshot of the actual state
+// machine.
+// Message contains the ReadCloser field for handling large snapshot. This avoid
+// copying the entire snapshot into a byte array, which consumes a lot of memory.
+//
+// User of Message should close the Message after sending it.
+type Message struct {
+ raftpb.Message
+ ReadCloser io.ReadCloser
+ TotalSize int64
+ closeC chan bool
+}
+
+func NewMessage(rs raftpb.Message, rc io.ReadCloser, rcSize int64) *Message {
+ return &Message{
+ Message: rs,
+ ReadCloser: ioutil.NewExactReadCloser(rc, rcSize),
+ TotalSize: int64(rs.Size()) + rcSize,
+ closeC: make(chan bool, 1),
+ }
+}
+
+// CloseNotify returns a channel that receives a single value
+// when the message sent is finished. true indicates the sent
+// is successful.
+func (m Message) CloseNotify() <-chan bool {
+ return m.closeC
+}
+
+func (m Message) CloseWithError(err error) {
+ if cerr := m.ReadCloser.Close(); cerr != nil {
+ err = cerr
+ }
+ if err == nil {
+ m.closeC <- true
+ } else {
+ m.closeC <- false
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/snap/metrics.go b/vendor/github.com/coreos/etcd/snap/metrics.go
new file mode 100644
index 00000000..433ef09d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/snap/metrics.go
@@ -0,0 +1,41 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package snap
+
+import "github.com/prometheus/client_golang/prometheus"
+
+var (
+ // TODO: save_fsync latency?
+ saveDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "snap",
+ Name: "save_total_duration_seconds",
+ Help: "The total latency distributions of save called by snapshot.",
+ Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
+ })
+
+ marshallingDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "snap",
+ Name: "save_marshalling_duration_seconds",
+ Help: "The marshalling cost distributions of save called by snapshot.",
+ Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
+ })
+)
+
+func init() {
+ prometheus.MustRegister(saveDurations)
+ prometheus.MustRegister(marshallingDurations)
+}
diff --git a/vendor/github.com/coreos/etcd/snap/snappb/snap.pb.go b/vendor/github.com/coreos/etcd/snap/snappb/snap.pb.go
new file mode 100644
index 00000000..e72b577f
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/snap/snappb/snap.pb.go
@@ -0,0 +1,336 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: snap.proto
+
+/*
+ Package snappb is a generated protocol buffer package.
+
+ It is generated from these files:
+ snap.proto
+
+ It has these top-level messages:
+ Snapshot
+*/
+package snappb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Snapshot struct {
+ Crc uint32 `protobuf:"varint,1,opt,name=crc" json:"crc"`
+ Data []byte `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Snapshot) Reset() { *m = Snapshot{} }
+func (m *Snapshot) String() string { return proto.CompactTextString(m) }
+func (*Snapshot) ProtoMessage() {}
+func (*Snapshot) Descriptor() ([]byte, []int) { return fileDescriptorSnap, []int{0} }
+
+func init() {
+ proto.RegisterType((*Snapshot)(nil), "snappb.snapshot")
+}
+func (m *Snapshot) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintSnap(dAtA, i, uint64(m.Crc))
+ if m.Data != nil {
+ dAtA[i] = 0x12
+ i++
+ i = encodeVarintSnap(dAtA, i, uint64(len(m.Data)))
+ i += copy(dAtA[i:], m.Data)
+ }
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func encodeVarintSnap(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Snapshot) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovSnap(uint64(m.Crc))
+ if m.Data != nil {
+ l = len(m.Data)
+ n += 1 + l + sovSnap(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovSnap(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozSnap(x uint64) (n int) {
+ return sovSnap(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Snapshot) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSnap
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: snapshot: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Crc", wireType)
+ }
+ m.Crc = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSnap
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Crc |= (uint32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowSnap
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthSnap
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipSnap(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthSnap
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipSnap(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSnap
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSnap
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSnap
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthSnap
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowSnap
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipSnap(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthSnap = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowSnap = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("snap.proto", fileDescriptorSnap) }
+
+var fileDescriptorSnap = []byte{
+ // 126 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xce, 0x4b, 0x2c,
+ 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x03, 0xb1, 0x0b, 0x92, 0xa4, 0x44, 0xd2, 0xf3,
+ 0xd3, 0xf3, 0xc1, 0x42, 0xfa, 0x20, 0x16, 0x44, 0x56, 0xc9, 0x8c, 0x8b, 0x03, 0x24, 0x5f, 0x9c,
+ 0x91, 0x5f, 0x22, 0x24, 0xc6, 0xc5, 0x9c, 0x5c, 0x94, 0x2c, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xeb,
+ 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x48, 0x40, 0x48, 0x88, 0x8b, 0x25, 0x25, 0xb1, 0x24,
+ 0x51, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xcc, 0x76, 0x12, 0x39, 0xf1, 0x50, 0x8e, 0xe1,
+ 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf1, 0x58, 0x8e,
+ 0x01, 0x10, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x0f, 0x32, 0xb2, 0x78, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/etcd/snap/snapshotter.go b/vendor/github.com/coreos/etcd/snap/snapshotter.go
new file mode 100644
index 00000000..00755592
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/snap/snapshotter.go
@@ -0,0 +1,204 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package snap stores raft nodes' states with snapshots.
+package snap
+
+import (
+ "errors"
+ "fmt"
+ "hash/crc32"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ pioutil "github.com/coreos/etcd/pkg/ioutil"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/snap/snappb"
+
+ "github.com/coreos/pkg/capnslog"
+)
+
+const (
+ snapSuffix = ".snap"
+)
+
+var (
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "snap")
+
+ ErrNoSnapshot = errors.New("snap: no available snapshot")
+ ErrEmptySnapshot = errors.New("snap: empty snapshot")
+ ErrCRCMismatch = errors.New("snap: crc mismatch")
+ crcTable = crc32.MakeTable(crc32.Castagnoli)
+
+ // A map of valid files that can be present in the snap folder.
+ validFiles = map[string]bool{
+ "db": true,
+ }
+)
+
+type Snapshotter struct {
+ dir string
+}
+
+func New(dir string) *Snapshotter {
+ return &Snapshotter{
+ dir: dir,
+ }
+}
+
+func (s *Snapshotter) SaveSnap(snapshot raftpb.Snapshot) error {
+ if raft.IsEmptySnap(snapshot) {
+ return nil
+ }
+ return s.save(&snapshot)
+}
+
+func (s *Snapshotter) save(snapshot *raftpb.Snapshot) error {
+ start := time.Now()
+
+ fname := fmt.Sprintf("%016x-%016x%s", snapshot.Metadata.Term, snapshot.Metadata.Index, snapSuffix)
+ b := pbutil.MustMarshal(snapshot)
+ crc := crc32.Update(0, crcTable, b)
+ snap := snappb.Snapshot{Crc: crc, Data: b}
+ d, err := snap.Marshal()
+ if err != nil {
+ return err
+ } else {
+ marshallingDurations.Observe(float64(time.Since(start)) / float64(time.Second))
+ }
+
+ err = pioutil.WriteAndSyncFile(filepath.Join(s.dir, fname), d, 0666)
+ if err == nil {
+ saveDurations.Observe(float64(time.Since(start)) / float64(time.Second))
+ } else {
+ err1 := os.Remove(filepath.Join(s.dir, fname))
+ if err1 != nil {
+ plog.Errorf("failed to remove broken snapshot file %s", filepath.Join(s.dir, fname))
+ }
+ }
+ return err
+}
+
+func (s *Snapshotter) Load() (*raftpb.Snapshot, error) {
+ names, err := s.snapNames()
+ if err != nil {
+ return nil, err
+ }
+ var snap *raftpb.Snapshot
+ for _, name := range names {
+ if snap, err = loadSnap(s.dir, name); err == nil {
+ break
+ }
+ }
+ if err != nil {
+ return nil, ErrNoSnapshot
+ }
+ return snap, nil
+}
+
+func loadSnap(dir, name string) (*raftpb.Snapshot, error) {
+ fpath := filepath.Join(dir, name)
+ snap, err := Read(fpath)
+ if err != nil {
+ renameBroken(fpath)
+ }
+ return snap, err
+}
+
+// Read reads the snapshot named by snapname and returns the snapshot.
+func Read(snapname string) (*raftpb.Snapshot, error) {
+ b, err := ioutil.ReadFile(snapname)
+ if err != nil {
+ plog.Errorf("cannot read file %v: %v", snapname, err)
+ return nil, err
+ }
+
+ if len(b) == 0 {
+ plog.Errorf("unexpected empty snapshot")
+ return nil, ErrEmptySnapshot
+ }
+
+ var serializedSnap snappb.Snapshot
+ if err = serializedSnap.Unmarshal(b); err != nil {
+ plog.Errorf("corrupted snapshot file %v: %v", snapname, err)
+ return nil, err
+ }
+
+ if len(serializedSnap.Data) == 0 || serializedSnap.Crc == 0 {
+ plog.Errorf("unexpected empty snapshot")
+ return nil, ErrEmptySnapshot
+ }
+
+ crc := crc32.Update(0, crcTable, serializedSnap.Data)
+ if crc != serializedSnap.Crc {
+ plog.Errorf("corrupted snapshot file %v: crc mismatch", snapname)
+ return nil, ErrCRCMismatch
+ }
+
+ var snap raftpb.Snapshot
+ if err = snap.Unmarshal(serializedSnap.Data); err != nil {
+ plog.Errorf("corrupted snapshot file %v: %v", snapname, err)
+ return nil, err
+ }
+ return &snap, nil
+}
+
+// snapNames returns the filename of the snapshots in logical time order (from newest to oldest).
+// If there is no available snapshots, an ErrNoSnapshot will be returned.
+func (s *Snapshotter) snapNames() ([]string, error) {
+ dir, err := os.Open(s.dir)
+ if err != nil {
+ return nil, err
+ }
+ defer dir.Close()
+ names, err := dir.Readdirnames(-1)
+ if err != nil {
+ return nil, err
+ }
+ snaps := checkSuffix(names)
+ if len(snaps) == 0 {
+ return nil, ErrNoSnapshot
+ }
+ sort.Sort(sort.Reverse(sort.StringSlice(snaps)))
+ return snaps, nil
+}
+
+func checkSuffix(names []string) []string {
+ snaps := []string{}
+ for i := range names {
+ if strings.HasSuffix(names[i], snapSuffix) {
+ snaps = append(snaps, names[i])
+ } else {
+ // If we find a file which is not a snapshot then check if it's
+ // a vaild file. If not throw out a warning.
+ if _, ok := validFiles[names[i]]; !ok {
+ plog.Warningf("skipped unexpected non snapshot file %v", names[i])
+ }
+ }
+ }
+ return snaps
+}
+
+func renameBroken(path string) {
+ brokenPath := path + ".broken"
+ if err := os.Rename(path, brokenPath); err != nil {
+ plog.Warningf("cannot rename broken snapshot file %v to %v: %v", path, brokenPath, err)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/store/doc.go b/vendor/github.com/coreos/etcd/store/doc.go
new file mode 100644
index 00000000..612df927
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package store defines etcd's in-memory key/value store.
+package store
diff --git a/vendor/github.com/coreos/etcd/store/event.go b/vendor/github.com/coreos/etcd/store/event.go
new file mode 100644
index 00000000..efcddb0e
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/event.go
@@ -0,0 +1,71 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+const (
+ Get = "get"
+ Create = "create"
+ Set = "set"
+ Update = "update"
+ Delete = "delete"
+ CompareAndSwap = "compareAndSwap"
+ CompareAndDelete = "compareAndDelete"
+ Expire = "expire"
+)
+
+type Event struct {
+ Action string `json:"action"`
+ Node *NodeExtern `json:"node,omitempty"`
+ PrevNode *NodeExtern `json:"prevNode,omitempty"`
+ EtcdIndex uint64 `json:"-"`
+ Refresh bool `json:"refresh,omitempty"`
+}
+
+func newEvent(action string, key string, modifiedIndex, createdIndex uint64) *Event {
+ n := &NodeExtern{
+ Key: key,
+ ModifiedIndex: modifiedIndex,
+ CreatedIndex: createdIndex,
+ }
+
+ return &Event{
+ Action: action,
+ Node: n,
+ }
+}
+
+func (e *Event) IsCreated() bool {
+ if e.Action == Create {
+ return true
+ }
+ return e.Action == Set && e.PrevNode == nil
+}
+
+func (e *Event) Index() uint64 {
+ return e.Node.ModifiedIndex
+}
+
+func (e *Event) Clone() *Event {
+ return &Event{
+ Action: e.Action,
+ EtcdIndex: e.EtcdIndex,
+ Node: e.Node.Clone(),
+ PrevNode: e.PrevNode.Clone(),
+ }
+}
+
+func (e *Event) SetRefresh() {
+ e.Refresh = true
+}
diff --git a/vendor/github.com/coreos/etcd/store/event_history.go b/vendor/github.com/coreos/etcd/store/event_history.go
new file mode 100644
index 00000000..235d87a2
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/event_history.go
@@ -0,0 +1,129 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "fmt"
+ "path"
+ "strings"
+ "sync"
+
+ etcdErr "github.com/coreos/etcd/error"
+)
+
+type EventHistory struct {
+ Queue eventQueue
+ StartIndex uint64
+ LastIndex uint64
+ rwl sync.RWMutex
+}
+
+func newEventHistory(capacity int) *EventHistory {
+ return &EventHistory{
+ Queue: eventQueue{
+ Capacity: capacity,
+ Events: make([]*Event, capacity),
+ },
+ }
+}
+
+// addEvent function adds event into the eventHistory
+func (eh *EventHistory) addEvent(e *Event) *Event {
+ eh.rwl.Lock()
+ defer eh.rwl.Unlock()
+
+ eh.Queue.insert(e)
+
+ eh.LastIndex = e.Index()
+
+ eh.StartIndex = eh.Queue.Events[eh.Queue.Front].Index()
+
+ return e
+}
+
+// scan enumerates events from the index history and stops at the first point
+// where the key matches.
+func (eh *EventHistory) scan(key string, recursive bool, index uint64) (*Event, *etcdErr.Error) {
+ eh.rwl.RLock()
+ defer eh.rwl.RUnlock()
+
+ // index should be after the event history's StartIndex
+ if index < eh.StartIndex {
+ return nil,
+ etcdErr.NewError(etcdErr.EcodeEventIndexCleared,
+ fmt.Sprintf("the requested history has been cleared [%v/%v]",
+ eh.StartIndex, index), 0)
+ }
+
+ // the index should come before the size of the queue minus the duplicate count
+ if index > eh.LastIndex { // future index
+ return nil, nil
+ }
+
+ offset := index - eh.StartIndex
+ i := (eh.Queue.Front + int(offset)) % eh.Queue.Capacity
+
+ for {
+ e := eh.Queue.Events[i]
+
+ if !e.Refresh {
+ ok := (e.Node.Key == key)
+
+ if recursive {
+ // add tailing slash
+ nkey := path.Clean(key)
+ if nkey[len(nkey)-1] != '/' {
+ nkey = nkey + "/"
+ }
+
+ ok = ok || strings.HasPrefix(e.Node.Key, nkey)
+ }
+
+ if (e.Action == Delete || e.Action == Expire) && e.PrevNode != nil && e.PrevNode.Dir {
+ ok = ok || strings.HasPrefix(key, e.PrevNode.Key)
+ }
+
+ if ok {
+ return e, nil
+ }
+ }
+
+ i = (i + 1) % eh.Queue.Capacity
+
+ if i == eh.Queue.Back {
+ return nil, nil
+ }
+ }
+}
+
+// clone will be protected by a stop-world lock
+// do not need to obtain internal lock
+func (eh *EventHistory) clone() *EventHistory {
+ clonedQueue := eventQueue{
+ Capacity: eh.Queue.Capacity,
+ Events: make([]*Event, eh.Queue.Capacity),
+ Size: eh.Queue.Size,
+ Front: eh.Queue.Front,
+ Back: eh.Queue.Back,
+ }
+
+ copy(clonedQueue.Events, eh.Queue.Events)
+ return &EventHistory{
+ StartIndex: eh.StartIndex,
+ Queue: clonedQueue,
+ LastIndex: eh.LastIndex,
+ }
+
+}
diff --git a/vendor/github.com/coreos/etcd/store/event_queue.go b/vendor/github.com/coreos/etcd/store/event_queue.go
new file mode 100644
index 00000000..767b8359
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/event_queue.go
@@ -0,0 +1,34 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+type eventQueue struct {
+ Events []*Event
+ Size int
+ Front int
+ Back int
+ Capacity int
+}
+
+func (eq *eventQueue) insert(e *Event) {
+ eq.Events[eq.Back] = e
+ eq.Back = (eq.Back + 1) % eq.Capacity
+
+ if eq.Size == eq.Capacity { //dequeue
+ eq.Front = (eq.Front + 1) % eq.Capacity
+ } else {
+ eq.Size++
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/store/metrics.go b/vendor/github.com/coreos/etcd/store/metrics.go
new file mode 100644
index 00000000..077c0fa2
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/metrics.go
@@ -0,0 +1,132 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// Set of raw Prometheus metrics.
+// Labels
+// * action = declared in event.go
+// * outcome = Outcome
+// Do not increment directly, use Report* methods.
+var (
+ readCounter = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "store",
+ Name: "reads_total",
+ Help: "Total number of reads action by (get/getRecursive), local to this member.",
+ }, []string{"action"})
+
+ writeCounter = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "store",
+ Name: "writes_total",
+ Help: "Total number of writes (e.g. set/compareAndDelete) seen by this member.",
+ }, []string{"action"})
+
+ readFailedCounter = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "store",
+ Name: "reads_failed_total",
+ Help: "Failed read actions by (get/getRecursive), local to this member.",
+ }, []string{"action"})
+
+ writeFailedCounter = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "store",
+ Name: "writes_failed_total",
+ Help: "Failed write actions (e.g. set/compareAndDelete), seen by this member.",
+ }, []string{"action"})
+
+ expireCounter = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "store",
+ Name: "expires_total",
+ Help: "Total number of expired keys.",
+ })
+
+ watchRequests = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "store",
+ Name: "watch_requests_total",
+ Help: "Total number of incoming watch requests (new or reestablished).",
+ })
+
+ watcherCount = prometheus.NewGauge(
+ prometheus.GaugeOpts{
+ Namespace: "etcd_debugging",
+ Subsystem: "store",
+ Name: "watchers",
+ Help: "Count of currently active watchers.",
+ })
+)
+
+const (
+ GetRecursive = "getRecursive"
+)
+
+func init() {
+ if prometheus.Register(readCounter) != nil {
+ // Tests will try to double register since the tests use both
+ // store and store_test packages; ignore second attempts.
+ return
+ }
+ prometheus.MustRegister(writeCounter)
+ prometheus.MustRegister(expireCounter)
+ prometheus.MustRegister(watchRequests)
+ prometheus.MustRegister(watcherCount)
+}
+
+func reportReadSuccess(read_action string) {
+ readCounter.WithLabelValues(read_action).Inc()
+}
+
+func reportReadFailure(read_action string) {
+ readCounter.WithLabelValues(read_action).Inc()
+ readFailedCounter.WithLabelValues(read_action).Inc()
+}
+
+func reportWriteSuccess(write_action string) {
+ writeCounter.WithLabelValues(write_action).Inc()
+}
+
+func reportWriteFailure(write_action string) {
+ writeCounter.WithLabelValues(write_action).Inc()
+ writeFailedCounter.WithLabelValues(write_action).Inc()
+}
+
+func reportExpiredKey() {
+ expireCounter.Inc()
+}
+
+func reportWatchRequest() {
+ watchRequests.Inc()
+}
+
+func reportWatcherAdded() {
+ watcherCount.Inc()
+}
+
+func reportWatcherRemoved() {
+ watcherCount.Dec()
+}
diff --git a/vendor/github.com/coreos/etcd/store/node.go b/vendor/github.com/coreos/etcd/store/node.go
new file mode 100644
index 00000000..c3c87431
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/node.go
@@ -0,0 +1,395 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "path"
+ "sort"
+ "time"
+
+ etcdErr "github.com/coreos/etcd/error"
+ "github.com/jonboulle/clockwork"
+)
+
+// explanations of Compare function result
+const (
+ CompareMatch = iota
+ CompareIndexNotMatch
+ CompareValueNotMatch
+ CompareNotMatch
+)
+
+var Permanent time.Time
+
+// node is the basic element in the store system.
+// A key-value pair will have a string value
+// A directory will have a children map
+type node struct {
+ Path string
+
+ CreatedIndex uint64
+ ModifiedIndex uint64
+
+ Parent *node `json:"-"` // should not encode this field! avoid circular dependency.
+
+ ExpireTime time.Time
+ Value string // for key-value pair
+ Children map[string]*node // for directory
+
+ // A reference to the store this node is attached to.
+ store *store
+}
+
+// newKV creates a Key-Value pair
+func newKV(store *store, nodePath string, value string, createdIndex uint64, parent *node, expireTime time.Time) *node {
+ return &node{
+ Path: nodePath,
+ CreatedIndex: createdIndex,
+ ModifiedIndex: createdIndex,
+ Parent: parent,
+ store: store,
+ ExpireTime: expireTime,
+ Value: value,
+ }
+}
+
+// newDir creates a directory
+func newDir(store *store, nodePath string, createdIndex uint64, parent *node, expireTime time.Time) *node {
+ return &node{
+ Path: nodePath,
+ CreatedIndex: createdIndex,
+ ModifiedIndex: createdIndex,
+ Parent: parent,
+ ExpireTime: expireTime,
+ Children: make(map[string]*node),
+ store: store,
+ }
+}
+
+// IsHidden function checks if the node is a hidden node. A hidden node
+// will begin with '_'
+// A hidden node will not be shown via get command under a directory
+// For example if we have /foo/_hidden and /foo/notHidden, get "/foo"
+// will only return /foo/notHidden
+func (n *node) IsHidden() bool {
+ _, name := path.Split(n.Path)
+
+ return name[0] == '_'
+}
+
+// IsPermanent function checks if the node is a permanent one.
+func (n *node) IsPermanent() bool {
+ // we use a uninitialized time.Time to indicate the node is a
+ // permanent one.
+ // the uninitialized time.Time should equal zero.
+ return n.ExpireTime.IsZero()
+}
+
+// IsDir function checks whether the node is a directory.
+// If the node is a directory, the function will return true.
+// Otherwise the function will return false.
+func (n *node) IsDir() bool {
+ return n.Children != nil
+}
+
+// Read function gets the value of the node.
+// If the receiver node is not a key-value pair, a "Not A File" error will be returned.
+func (n *node) Read() (string, *etcdErr.Error) {
+ if n.IsDir() {
+ return "", etcdErr.NewError(etcdErr.EcodeNotFile, "", n.store.CurrentIndex)
+ }
+
+ return n.Value, nil
+}
+
+// Write function set the value of the node to the given value.
+// If the receiver node is a directory, a "Not A File" error will be returned.
+func (n *node) Write(value string, index uint64) *etcdErr.Error {
+ if n.IsDir() {
+ return etcdErr.NewError(etcdErr.EcodeNotFile, "", n.store.CurrentIndex)
+ }
+
+ n.Value = value
+ n.ModifiedIndex = index
+
+ return nil
+}
+
+func (n *node) expirationAndTTL(clock clockwork.Clock) (*time.Time, int64) {
+ if !n.IsPermanent() {
+ /* compute ttl as:
+ ceiling( (expireTime - timeNow) / nanosecondsPerSecond )
+ which ranges from 1..n
+ rather than as:
+ ( (expireTime - timeNow) / nanosecondsPerSecond ) + 1
+ which ranges 1..n+1
+ */
+ ttlN := n.ExpireTime.Sub(clock.Now())
+ ttl := ttlN / time.Second
+ if (ttlN % time.Second) > 0 {
+ ttl++
+ }
+ t := n.ExpireTime.UTC()
+ return &t, int64(ttl)
+ }
+ return nil, 0
+}
+
+// List function return a slice of nodes under the receiver node.
+// If the receiver node is not a directory, a "Not A Directory" error will be returned.
+func (n *node) List() ([]*node, *etcdErr.Error) {
+ if !n.IsDir() {
+ return nil, etcdErr.NewError(etcdErr.EcodeNotDir, "", n.store.CurrentIndex)
+ }
+
+ nodes := make([]*node, len(n.Children))
+
+ i := 0
+ for _, node := range n.Children {
+ nodes[i] = node
+ i++
+ }
+
+ return nodes, nil
+}
+
+// GetChild function returns the child node under the directory node.
+// On success, it returns the file node
+func (n *node) GetChild(name string) (*node, *etcdErr.Error) {
+ if !n.IsDir() {
+ return nil, etcdErr.NewError(etcdErr.EcodeNotDir, n.Path, n.store.CurrentIndex)
+ }
+
+ child, ok := n.Children[name]
+
+ if ok {
+ return child, nil
+ }
+
+ return nil, nil
+}
+
+// Add function adds a node to the receiver node.
+// If the receiver is not a directory, a "Not A Directory" error will be returned.
+// If there is an existing node with the same name under the directory, a "Already Exist"
+// error will be returned
+func (n *node) Add(child *node) *etcdErr.Error {
+ if !n.IsDir() {
+ return etcdErr.NewError(etcdErr.EcodeNotDir, "", n.store.CurrentIndex)
+ }
+
+ _, name := path.Split(child.Path)
+
+ if _, ok := n.Children[name]; ok {
+ return etcdErr.NewError(etcdErr.EcodeNodeExist, "", n.store.CurrentIndex)
+ }
+
+ n.Children[name] = child
+
+ return nil
+}
+
+// Remove function remove the node.
+func (n *node) Remove(dir, recursive bool, callback func(path string)) *etcdErr.Error {
+ if !n.IsDir() { // key-value pair
+ _, name := path.Split(n.Path)
+
+ // find its parent and remove the node from the map
+ if n.Parent != nil && n.Parent.Children[name] == n {
+ delete(n.Parent.Children, name)
+ }
+
+ if callback != nil {
+ callback(n.Path)
+ }
+
+ if !n.IsPermanent() {
+ n.store.ttlKeyHeap.remove(n)
+ }
+
+ return nil
+ }
+
+ if !dir {
+ // cannot delete a directory without dir set to true
+ return etcdErr.NewError(etcdErr.EcodeNotFile, n.Path, n.store.CurrentIndex)
+ }
+
+ if len(n.Children) != 0 && !recursive {
+ // cannot delete a directory if it is not empty and the operation
+ // is not recursive
+ return etcdErr.NewError(etcdErr.EcodeDirNotEmpty, n.Path, n.store.CurrentIndex)
+ }
+
+ for _, child := range n.Children { // delete all children
+ child.Remove(true, true, callback)
+ }
+
+ // delete self
+ _, name := path.Split(n.Path)
+ if n.Parent != nil && n.Parent.Children[name] == n {
+ delete(n.Parent.Children, name)
+
+ if callback != nil {
+ callback(n.Path)
+ }
+
+ if !n.IsPermanent() {
+ n.store.ttlKeyHeap.remove(n)
+ }
+ }
+
+ return nil
+}
+
+func (n *node) Repr(recursive, sorted bool, clock clockwork.Clock) *NodeExtern {
+ if n.IsDir() {
+ node := &NodeExtern{
+ Key: n.Path,
+ Dir: true,
+ ModifiedIndex: n.ModifiedIndex,
+ CreatedIndex: n.CreatedIndex,
+ }
+ node.Expiration, node.TTL = n.expirationAndTTL(clock)
+
+ if !recursive {
+ return node
+ }
+
+ children, _ := n.List()
+ node.Nodes = make(NodeExterns, len(children))
+
+ // we do not use the index in the children slice directly
+ // we need to skip the hidden one
+ i := 0
+
+ for _, child := range children {
+
+ if child.IsHidden() { // get will not list hidden node
+ continue
+ }
+
+ node.Nodes[i] = child.Repr(recursive, sorted, clock)
+
+ i++
+ }
+
+ // eliminate hidden nodes
+ node.Nodes = node.Nodes[:i]
+ if sorted {
+ sort.Sort(node.Nodes)
+ }
+
+ return node
+ }
+
+ // since n.Value could be changed later, so we need to copy the value out
+ value := n.Value
+ node := &NodeExtern{
+ Key: n.Path,
+ Value: &value,
+ ModifiedIndex: n.ModifiedIndex,
+ CreatedIndex: n.CreatedIndex,
+ }
+ node.Expiration, node.TTL = n.expirationAndTTL(clock)
+ return node
+}
+
+func (n *node) UpdateTTL(expireTime time.Time) {
+ if !n.IsPermanent() {
+ if expireTime.IsZero() {
+ // from ttl to permanent
+ n.ExpireTime = expireTime
+ // remove from ttl heap
+ n.store.ttlKeyHeap.remove(n)
+ return
+ }
+
+ // update ttl
+ n.ExpireTime = expireTime
+ // update ttl heap
+ n.store.ttlKeyHeap.update(n)
+ return
+ }
+
+ if expireTime.IsZero() {
+ return
+ }
+
+ // from permanent to ttl
+ n.ExpireTime = expireTime
+ // push into ttl heap
+ n.store.ttlKeyHeap.push(n)
+}
+
+// Compare function compares node index and value with provided ones.
+// second result value explains result and equals to one of Compare.. constants
+func (n *node) Compare(prevValue string, prevIndex uint64) (ok bool, which int) {
+ indexMatch := (prevIndex == 0 || n.ModifiedIndex == prevIndex)
+ valueMatch := (prevValue == "" || n.Value == prevValue)
+ ok = valueMatch && indexMatch
+ switch {
+ case valueMatch && indexMatch:
+ which = CompareMatch
+ case indexMatch && !valueMatch:
+ which = CompareValueNotMatch
+ case valueMatch && !indexMatch:
+ which = CompareIndexNotMatch
+ default:
+ which = CompareNotMatch
+ }
+ return ok, which
+}
+
+// Clone function clone the node recursively and return the new node.
+// If the node is a directory, it will clone all the content under this directory.
+// If the node is a key-value pair, it will clone the pair.
+func (n *node) Clone() *node {
+ if !n.IsDir() {
+ newkv := newKV(n.store, n.Path, n.Value, n.CreatedIndex, n.Parent, n.ExpireTime)
+ newkv.ModifiedIndex = n.ModifiedIndex
+ return newkv
+ }
+
+ clone := newDir(n.store, n.Path, n.CreatedIndex, n.Parent, n.ExpireTime)
+ clone.ModifiedIndex = n.ModifiedIndex
+
+ for key, child := range n.Children {
+ clone.Children[key] = child.Clone()
+ }
+
+ return clone
+}
+
+// recoverAndclean function help to do recovery.
+// Two things need to be done: 1. recovery structure; 2. delete expired nodes
+//
+// If the node is a directory, it will help recover children's parent pointer and recursively
+// call this function on its children.
+// We check the expire last since we need to recover the whole structure first and add all the
+// notifications into the event history.
+func (n *node) recoverAndclean() {
+ if n.IsDir() {
+ for _, child := range n.Children {
+ child.Parent = n
+ child.store = n.store
+ child.recoverAndclean()
+ }
+ }
+
+ if !n.ExpireTime.IsZero() {
+ n.store.ttlKeyHeap.push(n)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/store/node_extern.go b/vendor/github.com/coreos/etcd/store/node_extern.go
new file mode 100644
index 00000000..7ba870cb
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/node_extern.go
@@ -0,0 +1,116 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "sort"
+ "time"
+
+ "github.com/jonboulle/clockwork"
+)
+
+// NodeExtern is the external representation of the
+// internal node with additional fields
+// PrevValue is the previous value of the node
+// TTL is time to live in second
+type NodeExtern struct {
+ Key string `json:"key,omitempty"`
+ Value *string `json:"value,omitempty"`
+ Dir bool `json:"dir,omitempty"`
+ Expiration *time.Time `json:"expiration,omitempty"`
+ TTL int64 `json:"ttl,omitempty"`
+ Nodes NodeExterns `json:"nodes,omitempty"`
+ ModifiedIndex uint64 `json:"modifiedIndex,omitempty"`
+ CreatedIndex uint64 `json:"createdIndex,omitempty"`
+}
+
+func (eNode *NodeExtern) loadInternalNode(n *node, recursive, sorted bool, clock clockwork.Clock) {
+ if n.IsDir() { // node is a directory
+ eNode.Dir = true
+
+ children, _ := n.List()
+ eNode.Nodes = make(NodeExterns, len(children))
+
+ // we do not use the index in the children slice directly
+ // we need to skip the hidden one
+ i := 0
+
+ for _, child := range children {
+ if child.IsHidden() { // get will not return hidden nodes
+ continue
+ }
+
+ eNode.Nodes[i] = child.Repr(recursive, sorted, clock)
+ i++
+ }
+
+ // eliminate hidden nodes
+ eNode.Nodes = eNode.Nodes[:i]
+
+ if sorted {
+ sort.Sort(eNode.Nodes)
+ }
+
+ } else { // node is a file
+ value, _ := n.Read()
+ eNode.Value = &value
+ }
+
+ eNode.Expiration, eNode.TTL = n.expirationAndTTL(clock)
+}
+
+func (eNode *NodeExtern) Clone() *NodeExtern {
+ if eNode == nil {
+ return nil
+ }
+ nn := &NodeExtern{
+ Key: eNode.Key,
+ Dir: eNode.Dir,
+ TTL: eNode.TTL,
+ ModifiedIndex: eNode.ModifiedIndex,
+ CreatedIndex: eNode.CreatedIndex,
+ }
+ if eNode.Value != nil {
+ s := *eNode.Value
+ nn.Value = &s
+ }
+ if eNode.Expiration != nil {
+ t := *eNode.Expiration
+ nn.Expiration = &t
+ }
+ if eNode.Nodes != nil {
+ nn.Nodes = make(NodeExterns, len(eNode.Nodes))
+ for i, n := range eNode.Nodes {
+ nn.Nodes[i] = n.Clone()
+ }
+ }
+ return nn
+}
+
+type NodeExterns []*NodeExtern
+
+// interfaces for sorting
+
+func (ns NodeExterns) Len() int {
+ return len(ns)
+}
+
+func (ns NodeExterns) Less(i, j int) bool {
+ return ns[i].Key < ns[j].Key
+}
+
+func (ns NodeExterns) Swap(i, j int) {
+ ns[i], ns[j] = ns[j], ns[i]
+}
diff --git a/vendor/github.com/coreos/etcd/store/stats.go b/vendor/github.com/coreos/etcd/store/stats.go
new file mode 100644
index 00000000..ce464dda
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/stats.go
@@ -0,0 +1,145 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "encoding/json"
+ "sync/atomic"
+)
+
+const (
+ SetSuccess = iota
+ SetFail
+ DeleteSuccess
+ DeleteFail
+ CreateSuccess
+ CreateFail
+ UpdateSuccess
+ UpdateFail
+ CompareAndSwapSuccess
+ CompareAndSwapFail
+ GetSuccess
+ GetFail
+ ExpireCount
+ CompareAndDeleteSuccess
+ CompareAndDeleteFail
+)
+
+type Stats struct {
+ // Number of get requests
+
+ GetSuccess uint64 `json:"getsSuccess"`
+ GetFail uint64 `json:"getsFail"`
+
+ // Number of sets requests
+
+ SetSuccess uint64 `json:"setsSuccess"`
+ SetFail uint64 `json:"setsFail"`
+
+ // Number of delete requests
+
+ DeleteSuccess uint64 `json:"deleteSuccess"`
+ DeleteFail uint64 `json:"deleteFail"`
+
+ // Number of update requests
+
+ UpdateSuccess uint64 `json:"updateSuccess"`
+ UpdateFail uint64 `json:"updateFail"`
+
+ // Number of create requests
+
+ CreateSuccess uint64 `json:"createSuccess"`
+ CreateFail uint64 `json:"createFail"`
+
+ // Number of testAndSet requests
+
+ CompareAndSwapSuccess uint64 `json:"compareAndSwapSuccess"`
+ CompareAndSwapFail uint64 `json:"compareAndSwapFail"`
+
+ // Number of compareAndDelete requests
+
+ CompareAndDeleteSuccess uint64 `json:"compareAndDeleteSuccess"`
+ CompareAndDeleteFail uint64 `json:"compareAndDeleteFail"`
+
+ ExpireCount uint64 `json:"expireCount"`
+
+ Watchers uint64 `json:"watchers"`
+}
+
+func newStats() *Stats {
+ s := new(Stats)
+ return s
+}
+
+func (s *Stats) clone() *Stats {
+ return &Stats{
+ GetSuccess: s.GetSuccess,
+ GetFail: s.GetFail,
+ SetSuccess: s.SetSuccess,
+ SetFail: s.SetFail,
+ DeleteSuccess: s.DeleteSuccess,
+ DeleteFail: s.DeleteFail,
+ UpdateSuccess: s.UpdateSuccess,
+ UpdateFail: s.UpdateFail,
+ CreateSuccess: s.CreateSuccess,
+ CreateFail: s.CreateFail,
+ CompareAndSwapSuccess: s.CompareAndSwapSuccess,
+ CompareAndSwapFail: s.CompareAndSwapFail,
+ CompareAndDeleteSuccess: s.CompareAndDeleteSuccess,
+ CompareAndDeleteFail: s.CompareAndDeleteFail,
+ ExpireCount: s.ExpireCount,
+ Watchers: s.Watchers,
+ }
+}
+
+func (s *Stats) toJson() []byte {
+ b, _ := json.Marshal(s)
+ return b
+}
+
+func (s *Stats) Inc(field int) {
+ switch field {
+ case SetSuccess:
+ atomic.AddUint64(&s.SetSuccess, 1)
+ case SetFail:
+ atomic.AddUint64(&s.SetFail, 1)
+ case CreateSuccess:
+ atomic.AddUint64(&s.CreateSuccess, 1)
+ case CreateFail:
+ atomic.AddUint64(&s.CreateFail, 1)
+ case DeleteSuccess:
+ atomic.AddUint64(&s.DeleteSuccess, 1)
+ case DeleteFail:
+ atomic.AddUint64(&s.DeleteFail, 1)
+ case GetSuccess:
+ atomic.AddUint64(&s.GetSuccess, 1)
+ case GetFail:
+ atomic.AddUint64(&s.GetFail, 1)
+ case UpdateSuccess:
+ atomic.AddUint64(&s.UpdateSuccess, 1)
+ case UpdateFail:
+ atomic.AddUint64(&s.UpdateFail, 1)
+ case CompareAndSwapSuccess:
+ atomic.AddUint64(&s.CompareAndSwapSuccess, 1)
+ case CompareAndSwapFail:
+ atomic.AddUint64(&s.CompareAndSwapFail, 1)
+ case CompareAndDeleteSuccess:
+ atomic.AddUint64(&s.CompareAndDeleteSuccess, 1)
+ case CompareAndDeleteFail:
+ atomic.AddUint64(&s.CompareAndDeleteFail, 1)
+ case ExpireCount:
+ atomic.AddUint64(&s.ExpireCount, 1)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/store/store.go b/vendor/github.com/coreos/etcd/store/store.go
new file mode 100644
index 00000000..edf7f219
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/store.go
@@ -0,0 +1,791 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "encoding/json"
+ "fmt"
+ "path"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ etcdErr "github.com/coreos/etcd/error"
+ "github.com/coreos/etcd/pkg/types"
+ "github.com/jonboulle/clockwork"
+)
+
+// The default version to set when the store is first initialized.
+const defaultVersion = 2
+
+var minExpireTime time.Time
+
+func init() {
+ minExpireTime, _ = time.Parse(time.RFC3339, "2000-01-01T00:00:00Z")
+}
+
+type Store interface {
+ Version() int
+ Index() uint64
+
+ Get(nodePath string, recursive, sorted bool) (*Event, error)
+ Set(nodePath string, dir bool, value string, expireOpts TTLOptionSet) (*Event, error)
+ Update(nodePath string, newValue string, expireOpts TTLOptionSet) (*Event, error)
+ Create(nodePath string, dir bool, value string, unique bool,
+ expireOpts TTLOptionSet) (*Event, error)
+ CompareAndSwap(nodePath string, prevValue string, prevIndex uint64,
+ value string, expireOpts TTLOptionSet) (*Event, error)
+ Delete(nodePath string, dir, recursive bool) (*Event, error)
+ CompareAndDelete(nodePath string, prevValue string, prevIndex uint64) (*Event, error)
+
+ Watch(prefix string, recursive, stream bool, sinceIndex uint64) (Watcher, error)
+
+ Save() ([]byte, error)
+ Recovery(state []byte) error
+
+ Clone() Store
+ SaveNoCopy() ([]byte, error)
+
+ JsonStats() []byte
+ DeleteExpiredKeys(cutoff time.Time)
+
+ HasTTLKeys() bool
+}
+
+type TTLOptionSet struct {
+ ExpireTime time.Time
+ Refresh bool
+}
+
+type store struct {
+ Root *node
+ WatcherHub *watcherHub
+ CurrentIndex uint64
+ Stats *Stats
+ CurrentVersion int
+ ttlKeyHeap *ttlKeyHeap // need to recovery manually
+ worldLock sync.RWMutex // stop the world lock
+ clock clockwork.Clock
+ readonlySet types.Set
+}
+
+// New creates a store where the given namespaces will be created as initial directories.
+func New(namespaces ...string) Store {
+ s := newStore(namespaces...)
+ s.clock = clockwork.NewRealClock()
+ return s
+}
+
+func newStore(namespaces ...string) *store {
+ s := new(store)
+ s.CurrentVersion = defaultVersion
+ s.Root = newDir(s, "/", s.CurrentIndex, nil, Permanent)
+ for _, namespace := range namespaces {
+ s.Root.Add(newDir(s, namespace, s.CurrentIndex, s.Root, Permanent))
+ }
+ s.Stats = newStats()
+ s.WatcherHub = newWatchHub(1000)
+ s.ttlKeyHeap = newTtlKeyHeap()
+ s.readonlySet = types.NewUnsafeSet(append(namespaces, "/")...)
+ return s
+}
+
+// Version retrieves current version of the store.
+func (s *store) Version() int {
+ return s.CurrentVersion
+}
+
+// Index retrieves the current index of the store.
+func (s *store) Index() uint64 {
+ s.worldLock.RLock()
+ defer s.worldLock.RUnlock()
+ return s.CurrentIndex
+}
+
+// Get returns a get event.
+// If recursive is true, it will return all the content under the node path.
+// If sorted is true, it will sort the content by keys.
+func (s *store) Get(nodePath string, recursive, sorted bool) (*Event, error) {
+ var err *etcdErr.Error
+
+ s.worldLock.RLock()
+ defer s.worldLock.RUnlock()
+
+ defer func() {
+ if err == nil {
+ s.Stats.Inc(GetSuccess)
+ if recursive {
+ reportReadSuccess(GetRecursive)
+ } else {
+ reportReadSuccess(Get)
+ }
+ return
+ }
+
+ s.Stats.Inc(GetFail)
+ if recursive {
+ reportReadFailure(GetRecursive)
+ } else {
+ reportReadFailure(Get)
+ }
+ }()
+
+ n, err := s.internalGet(nodePath)
+ if err != nil {
+ return nil, err
+ }
+
+ e := newEvent(Get, nodePath, n.ModifiedIndex, n.CreatedIndex)
+ e.EtcdIndex = s.CurrentIndex
+ e.Node.loadInternalNode(n, recursive, sorted, s.clock)
+
+ return e, nil
+}
+
+// Create creates the node at nodePath. Create will help to create intermediate directories with no ttl.
+// If the node has already existed, create will fail.
+// If any node on the path is a file, create will fail.
+func (s *store) Create(nodePath string, dir bool, value string, unique bool, expireOpts TTLOptionSet) (*Event, error) {
+ var err *etcdErr.Error
+
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+
+ defer func() {
+ if err == nil {
+ s.Stats.Inc(CreateSuccess)
+ reportWriteSuccess(Create)
+ return
+ }
+
+ s.Stats.Inc(CreateFail)
+ reportWriteFailure(Create)
+ }()
+
+ e, err := s.internalCreate(nodePath, dir, value, unique, false, expireOpts.ExpireTime, Create)
+ if err != nil {
+ return nil, err
+ }
+
+ e.EtcdIndex = s.CurrentIndex
+ s.WatcherHub.notify(e)
+
+ return e, nil
+}
+
+// Set creates or replace the node at nodePath.
+func (s *store) Set(nodePath string, dir bool, value string, expireOpts TTLOptionSet) (*Event, error) {
+ var err *etcdErr.Error
+
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+
+ defer func() {
+ if err == nil {
+ s.Stats.Inc(SetSuccess)
+ reportWriteSuccess(Set)
+ return
+ }
+
+ s.Stats.Inc(SetFail)
+ reportWriteFailure(Set)
+ }()
+
+ // Get prevNode value
+ n, getErr := s.internalGet(nodePath)
+ if getErr != nil && getErr.ErrorCode != etcdErr.EcodeKeyNotFound {
+ err = getErr
+ return nil, err
+ }
+
+ if expireOpts.Refresh {
+ if getErr != nil {
+ err = getErr
+ return nil, err
+ } else {
+ value = n.Value
+ }
+ }
+
+ // Set new value
+ e, err := s.internalCreate(nodePath, dir, value, false, true, expireOpts.ExpireTime, Set)
+ if err != nil {
+ return nil, err
+ }
+ e.EtcdIndex = s.CurrentIndex
+
+ // Put prevNode into event
+ if getErr == nil {
+ prev := newEvent(Get, nodePath, n.ModifiedIndex, n.CreatedIndex)
+ prev.Node.loadInternalNode(n, false, false, s.clock)
+ e.PrevNode = prev.Node
+ }
+
+ if !expireOpts.Refresh {
+ s.WatcherHub.notify(e)
+ } else {
+ e.SetRefresh()
+ s.WatcherHub.add(e)
+ }
+
+ return e, nil
+}
+
+// returns user-readable cause of failed comparison
+func getCompareFailCause(n *node, which int, prevValue string, prevIndex uint64) string {
+ switch which {
+ case CompareIndexNotMatch:
+ return fmt.Sprintf("[%v != %v]", prevIndex, n.ModifiedIndex)
+ case CompareValueNotMatch:
+ return fmt.Sprintf("[%v != %v]", prevValue, n.Value)
+ default:
+ return fmt.Sprintf("[%v != %v] [%v != %v]", prevValue, n.Value, prevIndex, n.ModifiedIndex)
+ }
+}
+
+func (s *store) CompareAndSwap(nodePath string, prevValue string, prevIndex uint64,
+ value string, expireOpts TTLOptionSet) (*Event, error) {
+
+ var err *etcdErr.Error
+
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+
+ defer func() {
+ if err == nil {
+ s.Stats.Inc(CompareAndSwapSuccess)
+ reportWriteSuccess(CompareAndSwap)
+ return
+ }
+
+ s.Stats.Inc(CompareAndSwapFail)
+ reportWriteFailure(CompareAndSwap)
+ }()
+
+ nodePath = path.Clean(path.Join("/", nodePath))
+ // we do not allow the user to change "/"
+ if s.readonlySet.Contains(nodePath) {
+ return nil, etcdErr.NewError(etcdErr.EcodeRootROnly, "/", s.CurrentIndex)
+ }
+
+ n, err := s.internalGet(nodePath)
+ if err != nil {
+ return nil, err
+ }
+ if n.IsDir() { // can only compare and swap file
+ err = etcdErr.NewError(etcdErr.EcodeNotFile, nodePath, s.CurrentIndex)
+ return nil, err
+ }
+
+ // If both of the prevValue and prevIndex are given, we will test both of them.
+ // Command will be executed, only if both of the tests are successful.
+ if ok, which := n.Compare(prevValue, prevIndex); !ok {
+ cause := getCompareFailCause(n, which, prevValue, prevIndex)
+ err = etcdErr.NewError(etcdErr.EcodeTestFailed, cause, s.CurrentIndex)
+ return nil, err
+ }
+
+ if expireOpts.Refresh {
+ value = n.Value
+ }
+
+ // update etcd index
+ s.CurrentIndex++
+
+ e := newEvent(CompareAndSwap, nodePath, s.CurrentIndex, n.CreatedIndex)
+ e.EtcdIndex = s.CurrentIndex
+ e.PrevNode = n.Repr(false, false, s.clock)
+ eNode := e.Node
+
+ // if test succeed, write the value
+ n.Write(value, s.CurrentIndex)
+ n.UpdateTTL(expireOpts.ExpireTime)
+
+ // copy the value for safety
+ valueCopy := value
+ eNode.Value = &valueCopy
+ eNode.Expiration, eNode.TTL = n.expirationAndTTL(s.clock)
+
+ if !expireOpts.Refresh {
+ s.WatcherHub.notify(e)
+ } else {
+ e.SetRefresh()
+ s.WatcherHub.add(e)
+ }
+
+ return e, nil
+}
+
+// Delete deletes the node at the given path.
+// If the node is a directory, recursive must be true to delete it.
+func (s *store) Delete(nodePath string, dir, recursive bool) (*Event, error) {
+ var err *etcdErr.Error
+
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+
+ defer func() {
+ if err == nil {
+ s.Stats.Inc(DeleteSuccess)
+ reportWriteSuccess(Delete)
+ return
+ }
+
+ s.Stats.Inc(DeleteFail)
+ reportWriteFailure(Delete)
+ }()
+
+ nodePath = path.Clean(path.Join("/", nodePath))
+ // we do not allow the user to change "/"
+ if s.readonlySet.Contains(nodePath) {
+ return nil, etcdErr.NewError(etcdErr.EcodeRootROnly, "/", s.CurrentIndex)
+ }
+
+ // recursive implies dir
+ if recursive {
+ dir = true
+ }
+
+ n, err := s.internalGet(nodePath)
+ if err != nil { // if the node does not exist, return error
+ return nil, err
+ }
+
+ nextIndex := s.CurrentIndex + 1
+ e := newEvent(Delete, nodePath, nextIndex, n.CreatedIndex)
+ e.EtcdIndex = nextIndex
+ e.PrevNode = n.Repr(false, false, s.clock)
+ eNode := e.Node
+
+ if n.IsDir() {
+ eNode.Dir = true
+ }
+
+ callback := func(path string) { // notify function
+ // notify the watchers with deleted set true
+ s.WatcherHub.notifyWatchers(e, path, true)
+ }
+
+ err = n.Remove(dir, recursive, callback)
+ if err != nil {
+ return nil, err
+ }
+
+ // update etcd index
+ s.CurrentIndex++
+
+ s.WatcherHub.notify(e)
+
+ return e, nil
+}
+
+func (s *store) CompareAndDelete(nodePath string, prevValue string, prevIndex uint64) (*Event, error) {
+ var err *etcdErr.Error
+
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+
+ defer func() {
+ if err == nil {
+ s.Stats.Inc(CompareAndDeleteSuccess)
+ reportWriteSuccess(CompareAndDelete)
+ return
+ }
+
+ s.Stats.Inc(CompareAndDeleteFail)
+ reportWriteFailure(CompareAndDelete)
+ }()
+
+ nodePath = path.Clean(path.Join("/", nodePath))
+
+ n, err := s.internalGet(nodePath)
+ if err != nil { // if the node does not exist, return error
+ return nil, err
+ }
+ if n.IsDir() { // can only compare and delete file
+ return nil, etcdErr.NewError(etcdErr.EcodeNotFile, nodePath, s.CurrentIndex)
+ }
+
+ // If both of the prevValue and prevIndex are given, we will test both of them.
+ // Command will be executed, only if both of the tests are successful.
+ if ok, which := n.Compare(prevValue, prevIndex); !ok {
+ cause := getCompareFailCause(n, which, prevValue, prevIndex)
+ return nil, etcdErr.NewError(etcdErr.EcodeTestFailed, cause, s.CurrentIndex)
+ }
+
+ // update etcd index
+ s.CurrentIndex++
+
+ e := newEvent(CompareAndDelete, nodePath, s.CurrentIndex, n.CreatedIndex)
+ e.EtcdIndex = s.CurrentIndex
+ e.PrevNode = n.Repr(false, false, s.clock)
+
+ callback := func(path string) { // notify function
+ // notify the watchers with deleted set true
+ s.WatcherHub.notifyWatchers(e, path, true)
+ }
+
+ err = n.Remove(false, false, callback)
+ if err != nil {
+ return nil, err
+ }
+
+ s.WatcherHub.notify(e)
+
+ return e, nil
+}
+
+func (s *store) Watch(key string, recursive, stream bool, sinceIndex uint64) (Watcher, error) {
+ s.worldLock.RLock()
+ defer s.worldLock.RUnlock()
+
+ key = path.Clean(path.Join("/", key))
+ if sinceIndex == 0 {
+ sinceIndex = s.CurrentIndex + 1
+ }
+ // WatcherHub does not know about the current index, so we need to pass it in
+ w, err := s.WatcherHub.watch(key, recursive, stream, sinceIndex, s.CurrentIndex)
+ if err != nil {
+ return nil, err
+ }
+
+ return w, nil
+}
+
+// walk walks all the nodePath and apply the walkFunc on each directory
+func (s *store) walk(nodePath string, walkFunc func(prev *node, component string) (*node, *etcdErr.Error)) (*node, *etcdErr.Error) {
+ components := strings.Split(nodePath, "/")
+
+ curr := s.Root
+ var err *etcdErr.Error
+
+ for i := 1; i < len(components); i++ {
+ if len(components[i]) == 0 { // ignore empty string
+ return curr, nil
+ }
+
+ curr, err = walkFunc(curr, components[i])
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return curr, nil
+}
+
+// Update updates the value/ttl of the node.
+// If the node is a file, the value and the ttl can be updated.
+// If the node is a directory, only the ttl can be updated.
+func (s *store) Update(nodePath string, newValue string, expireOpts TTLOptionSet) (*Event, error) {
+ var err *etcdErr.Error
+
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+
+ defer func() {
+ if err == nil {
+ s.Stats.Inc(UpdateSuccess)
+ reportWriteSuccess(Update)
+ return
+ }
+
+ s.Stats.Inc(UpdateFail)
+ reportWriteFailure(Update)
+ }()
+
+ nodePath = path.Clean(path.Join("/", nodePath))
+ // we do not allow the user to change "/"
+ if s.readonlySet.Contains(nodePath) {
+ return nil, etcdErr.NewError(etcdErr.EcodeRootROnly, "/", s.CurrentIndex)
+ }
+
+ currIndex, nextIndex := s.CurrentIndex, s.CurrentIndex+1
+
+ n, err := s.internalGet(nodePath)
+ if err != nil { // if the node does not exist, return error
+ return nil, err
+ }
+ if n.IsDir() && len(newValue) != 0 {
+ // if the node is a directory, we cannot update value to non-empty
+ return nil, etcdErr.NewError(etcdErr.EcodeNotFile, nodePath, currIndex)
+ }
+
+ if expireOpts.Refresh {
+ newValue = n.Value
+ }
+
+ e := newEvent(Update, nodePath, nextIndex, n.CreatedIndex)
+ e.EtcdIndex = nextIndex
+ e.PrevNode = n.Repr(false, false, s.clock)
+ eNode := e.Node
+
+ n.Write(newValue, nextIndex)
+
+ if n.IsDir() {
+ eNode.Dir = true
+ } else {
+ // copy the value for safety
+ newValueCopy := newValue
+ eNode.Value = &newValueCopy
+ }
+
+ // update ttl
+ n.UpdateTTL(expireOpts.ExpireTime)
+
+ eNode.Expiration, eNode.TTL = n.expirationAndTTL(s.clock)
+
+ if !expireOpts.Refresh {
+ s.WatcherHub.notify(e)
+ } else {
+ e.SetRefresh()
+ s.WatcherHub.add(e)
+ }
+
+ s.CurrentIndex = nextIndex
+
+ return e, nil
+}
+
+func (s *store) internalCreate(nodePath string, dir bool, value string, unique, replace bool,
+ expireTime time.Time, action string) (*Event, *etcdErr.Error) {
+
+ currIndex, nextIndex := s.CurrentIndex, s.CurrentIndex+1
+
+ if unique { // append unique item under the node path
+ nodePath += "/" + fmt.Sprintf("%020s", strconv.FormatUint(nextIndex, 10))
+ }
+
+ nodePath = path.Clean(path.Join("/", nodePath))
+
+ // we do not allow the user to change "/"
+ if s.readonlySet.Contains(nodePath) {
+ return nil, etcdErr.NewError(etcdErr.EcodeRootROnly, "/", currIndex)
+ }
+
+ // Assume expire times that are way in the past are
+ // This can occur when the time is serialized to JS
+ if expireTime.Before(minExpireTime) {
+ expireTime = Permanent
+ }
+
+ dirName, nodeName := path.Split(nodePath)
+
+ // walk through the nodePath, create dirs and get the last directory node
+ d, err := s.walk(dirName, s.checkDir)
+
+ if err != nil {
+ s.Stats.Inc(SetFail)
+ reportWriteFailure(action)
+ err.Index = currIndex
+ return nil, err
+ }
+
+ e := newEvent(action, nodePath, nextIndex, nextIndex)
+ eNode := e.Node
+
+ n, _ := d.GetChild(nodeName)
+
+ // force will try to replace an existing file
+ if n != nil {
+ if replace {
+ if n.IsDir() {
+ return nil, etcdErr.NewError(etcdErr.EcodeNotFile, nodePath, currIndex)
+ }
+ e.PrevNode = n.Repr(false, false, s.clock)
+
+ n.Remove(false, false, nil)
+ } else {
+ return nil, etcdErr.NewError(etcdErr.EcodeNodeExist, nodePath, currIndex)
+ }
+ }
+
+ if !dir { // create file
+ // copy the value for safety
+ valueCopy := value
+ eNode.Value = &valueCopy
+
+ n = newKV(s, nodePath, value, nextIndex, d, expireTime)
+
+ } else { // create directory
+ eNode.Dir = true
+
+ n = newDir(s, nodePath, nextIndex, d, expireTime)
+ }
+
+ // we are sure d is a directory and does not have the children with name n.Name
+ d.Add(n)
+
+ // node with TTL
+ if !n.IsPermanent() {
+ s.ttlKeyHeap.push(n)
+
+ eNode.Expiration, eNode.TTL = n.expirationAndTTL(s.clock)
+ }
+
+ s.CurrentIndex = nextIndex
+
+ return e, nil
+}
+
+// InternalGet gets the node of the given nodePath.
+func (s *store) internalGet(nodePath string) (*node, *etcdErr.Error) {
+ nodePath = path.Clean(path.Join("/", nodePath))
+
+ walkFunc := func(parent *node, name string) (*node, *etcdErr.Error) {
+
+ if !parent.IsDir() {
+ err := etcdErr.NewError(etcdErr.EcodeNotDir, parent.Path, s.CurrentIndex)
+ return nil, err
+ }
+
+ child, ok := parent.Children[name]
+ if ok {
+ return child, nil
+ }
+
+ return nil, etcdErr.NewError(etcdErr.EcodeKeyNotFound, path.Join(parent.Path, name), s.CurrentIndex)
+ }
+
+ f, err := s.walk(nodePath, walkFunc)
+
+ if err != nil {
+ return nil, err
+ }
+ return f, nil
+}
+
+// DeleteExpiredKeys will delete all expired keys
+func (s *store) DeleteExpiredKeys(cutoff time.Time) {
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+
+ for {
+ node := s.ttlKeyHeap.top()
+ if node == nil || node.ExpireTime.After(cutoff) {
+ break
+ }
+
+ s.CurrentIndex++
+ e := newEvent(Expire, node.Path, s.CurrentIndex, node.CreatedIndex)
+ e.EtcdIndex = s.CurrentIndex
+ e.PrevNode = node.Repr(false, false, s.clock)
+ if node.IsDir() {
+ e.Node.Dir = true
+ }
+
+ callback := func(path string) { // notify function
+ // notify the watchers with deleted set true
+ s.WatcherHub.notifyWatchers(e, path, true)
+ }
+
+ s.ttlKeyHeap.pop()
+ node.Remove(true, true, callback)
+
+ reportExpiredKey()
+ s.Stats.Inc(ExpireCount)
+
+ s.WatcherHub.notify(e)
+ }
+
+}
+
+// checkDir will check whether the component is a directory under parent node.
+// If it is a directory, this function will return the pointer to that node.
+// If it does not exist, this function will create a new directory and return the pointer to that node.
+// If it is a file, this function will return error.
+func (s *store) checkDir(parent *node, dirName string) (*node, *etcdErr.Error) {
+ node, ok := parent.Children[dirName]
+
+ if ok {
+ if node.IsDir() {
+ return node, nil
+ }
+
+ return nil, etcdErr.NewError(etcdErr.EcodeNotDir, node.Path, s.CurrentIndex)
+ }
+
+ n := newDir(s, path.Join(parent.Path, dirName), s.CurrentIndex+1, parent, Permanent)
+
+ parent.Children[dirName] = n
+
+ return n, nil
+}
+
+// Save saves the static state of the store system.
+// It will not be able to save the state of watchers.
+// It will not save the parent field of the node. Or there will
+// be cyclic dependencies issue for the json package.
+func (s *store) Save() ([]byte, error) {
+ b, err := json.Marshal(s.Clone())
+ if err != nil {
+ return nil, err
+ }
+
+ return b, nil
+}
+
+func (s *store) SaveNoCopy() ([]byte, error) {
+ b, err := json.Marshal(s)
+ if err != nil {
+ return nil, err
+ }
+
+ return b, nil
+}
+
+func (s *store) Clone() Store {
+ s.worldLock.Lock()
+
+ clonedStore := newStore()
+ clonedStore.CurrentIndex = s.CurrentIndex
+ clonedStore.Root = s.Root.Clone()
+ clonedStore.WatcherHub = s.WatcherHub.clone()
+ clonedStore.Stats = s.Stats.clone()
+ clonedStore.CurrentVersion = s.CurrentVersion
+
+ s.worldLock.Unlock()
+ return clonedStore
+}
+
+// Recovery recovers the store system from a static state
+// It needs to recover the parent field of the nodes.
+// It needs to delete the expired nodes since the saved time and also
+// needs to create monitoring go routines.
+func (s *store) Recovery(state []byte) error {
+ s.worldLock.Lock()
+ defer s.worldLock.Unlock()
+ err := json.Unmarshal(state, s)
+
+ if err != nil {
+ return err
+ }
+
+ s.ttlKeyHeap = newTtlKeyHeap()
+
+ s.Root.recoverAndclean()
+ return nil
+}
+
+func (s *store) JsonStats() []byte {
+ s.Stats.Watchers = uint64(s.WatcherHub.count)
+ return s.Stats.toJson()
+}
+
+func (s *store) HasTTLKeys() bool {
+ s.worldLock.RLock()
+ defer s.worldLock.RUnlock()
+ return s.ttlKeyHeap.Len() != 0
+}
diff --git a/vendor/github.com/coreos/etcd/store/ttl_key_heap.go b/vendor/github.com/coreos/etcd/store/ttl_key_heap.go
new file mode 100644
index 00000000..21ae9b7c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/ttl_key_heap.go
@@ -0,0 +1,99 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "container/heap"
+)
+
+// An TTLKeyHeap is a min-heap of TTLKeys order by expiration time
+type ttlKeyHeap struct {
+ array []*node
+ keyMap map[*node]int
+}
+
+func newTtlKeyHeap() *ttlKeyHeap {
+ h := &ttlKeyHeap{keyMap: make(map[*node]int)}
+ heap.Init(h)
+ return h
+}
+
+func (h ttlKeyHeap) Len() int {
+ return len(h.array)
+}
+
+func (h ttlKeyHeap) Less(i, j int) bool {
+ return h.array[i].ExpireTime.Before(h.array[j].ExpireTime)
+}
+
+func (h ttlKeyHeap) Swap(i, j int) {
+ // swap node
+ h.array[i], h.array[j] = h.array[j], h.array[i]
+
+ // update map
+ h.keyMap[h.array[i]] = i
+ h.keyMap[h.array[j]] = j
+}
+
+func (h *ttlKeyHeap) Push(x interface{}) {
+ n, _ := x.(*node)
+ h.keyMap[n] = len(h.array)
+ h.array = append(h.array, n)
+}
+
+func (h *ttlKeyHeap) Pop() interface{} {
+ old := h.array
+ n := len(old)
+ x := old[n-1]
+ // Set slice element to nil, so GC can recycle the node.
+ // This is due to golang GC doesn't support partial recycling:
+ // https://github.com/golang/go/issues/9618
+ old[n-1] = nil
+ h.array = old[0 : n-1]
+ delete(h.keyMap, x)
+ return x
+}
+
+func (h *ttlKeyHeap) top() *node {
+ if h.Len() != 0 {
+ return h.array[0]
+ }
+ return nil
+}
+
+func (h *ttlKeyHeap) pop() *node {
+ x := heap.Pop(h)
+ n, _ := x.(*node)
+ return n
+}
+
+func (h *ttlKeyHeap) push(x interface{}) {
+ heap.Push(h, x)
+}
+
+func (h *ttlKeyHeap) update(n *node) {
+ index, ok := h.keyMap[n]
+ if ok {
+ heap.Remove(h, index)
+ heap.Push(h, n)
+ }
+}
+
+func (h *ttlKeyHeap) remove(n *node) {
+ index, ok := h.keyMap[n]
+ if ok {
+ heap.Remove(h, index)
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/store/watcher.go b/vendor/github.com/coreos/etcd/store/watcher.go
new file mode 100644
index 00000000..a236ec77
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/watcher.go
@@ -0,0 +1,95 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+type Watcher interface {
+ EventChan() chan *Event
+ StartIndex() uint64 // The EtcdIndex at which the Watcher was created
+ Remove()
+}
+
+type watcher struct {
+ eventChan chan *Event
+ stream bool
+ recursive bool
+ sinceIndex uint64
+ startIndex uint64
+ hub *watcherHub
+ removed bool
+ remove func()
+}
+
+func (w *watcher) EventChan() chan *Event {
+ return w.eventChan
+}
+
+func (w *watcher) StartIndex() uint64 {
+ return w.startIndex
+}
+
+// notify function notifies the watcher. If the watcher interests in the given path,
+// the function will return true.
+func (w *watcher) notify(e *Event, originalPath bool, deleted bool) bool {
+ // watcher is interested the path in three cases and under one condition
+ // the condition is that the event happens after the watcher's sinceIndex
+
+ // 1. the path at which the event happens is the path the watcher is watching at.
+ // For example if the watcher is watching at "/foo" and the event happens at "/foo",
+ // the watcher must be interested in that event.
+
+ // 2. the watcher is a recursive watcher, it interests in the event happens after
+ // its watching path. For example if watcher A watches at "/foo" and it is a recursive
+ // one, it will interest in the event happens at "/foo/bar".
+
+ // 3. when we delete a directory, we need to force notify all the watchers who watches
+ // at the file we need to delete.
+ // For example a watcher is watching at "/foo/bar". And we deletes "/foo". The watcher
+ // should get notified even if "/foo" is not the path it is watching.
+ if (w.recursive || originalPath || deleted) && e.Index() >= w.sinceIndex {
+ // We cannot block here if the eventChan capacity is full, otherwise
+ // etcd will hang. eventChan capacity is full when the rate of
+ // notifications are higher than our send rate.
+ // If this happens, we close the channel.
+ select {
+ case w.eventChan <- e:
+ default:
+ // We have missed a notification. Remove the watcher.
+ // Removing the watcher also closes the eventChan.
+ w.remove()
+ }
+ return true
+ }
+ return false
+}
+
+// Remove removes the watcher from watcherHub
+// The actual remove function is guaranteed to only be executed once
+func (w *watcher) Remove() {
+ w.hub.mutex.Lock()
+ defer w.hub.mutex.Unlock()
+
+ close(w.eventChan)
+ if w.remove != nil {
+ w.remove()
+ }
+}
+
+// nopWatcher is a watcher that receives nothing, always blocking.
+type nopWatcher struct{}
+
+func NewNopWatcher() Watcher { return &nopWatcher{} }
+func (w *nopWatcher) EventChan() chan *Event { return nil }
+func (w *nopWatcher) StartIndex() uint64 { return 0 }
+func (w *nopWatcher) Remove() {}
diff --git a/vendor/github.com/coreos/etcd/store/watcher_hub.go b/vendor/github.com/coreos/etcd/store/watcher_hub.go
new file mode 100644
index 00000000..13c23e39
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/store/watcher_hub.go
@@ -0,0 +1,200 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package store
+
+import (
+ "container/list"
+ "path"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ etcdErr "github.com/coreos/etcd/error"
+)
+
+// A watcherHub contains all subscribed watchers
+// watchers is a map with watched path as key and watcher as value
+// EventHistory keeps the old events for watcherHub. It is used to help
+// watcher to get a continuous event history. Or a watcher might miss the
+// event happens between the end of the first watch command and the start
+// of the second command.
+type watcherHub struct {
+ // count must be the first element to keep 64-bit alignment for atomic
+ // access
+
+ count int64 // current number of watchers.
+
+ mutex sync.Mutex
+ watchers map[string]*list.List
+ EventHistory *EventHistory
+}
+
+// newWatchHub creates a watcherHub. The capacity determines how many events we will
+// keep in the eventHistory.
+// Typically, we only need to keep a small size of history[smaller than 20K].
+// Ideally, it should smaller than 20K/s[max throughput] * 2 * 50ms[RTT] = 2000
+func newWatchHub(capacity int) *watcherHub {
+ return &watcherHub{
+ watchers: make(map[string]*list.List),
+ EventHistory: newEventHistory(capacity),
+ }
+}
+
+// Watch function returns a Watcher.
+// If recursive is true, the first change after index under key will be sent to the event channel of the watcher.
+// If recursive is false, the first change after index at key will be sent to the event channel of the watcher.
+// If index is zero, watch will start from the current index + 1.
+func (wh *watcherHub) watch(key string, recursive, stream bool, index, storeIndex uint64) (Watcher, *etcdErr.Error) {
+ reportWatchRequest()
+ event, err := wh.EventHistory.scan(key, recursive, index)
+
+ if err != nil {
+ err.Index = storeIndex
+ return nil, err
+ }
+
+ w := &watcher{
+ eventChan: make(chan *Event, 100), // use a buffered channel
+ recursive: recursive,
+ stream: stream,
+ sinceIndex: index,
+ startIndex: storeIndex,
+ hub: wh,
+ }
+
+ wh.mutex.Lock()
+ defer wh.mutex.Unlock()
+ // If the event exists in the known history, append the EtcdIndex and return immediately
+ if event != nil {
+ ne := event.Clone()
+ ne.EtcdIndex = storeIndex
+ w.eventChan <- ne
+ return w, nil
+ }
+
+ l, ok := wh.watchers[key]
+
+ var elem *list.Element
+
+ if ok { // add the new watcher to the back of the list
+ elem = l.PushBack(w)
+ } else { // create a new list and add the new watcher
+ l = list.New()
+ elem = l.PushBack(w)
+ wh.watchers[key] = l
+ }
+
+ w.remove = func() {
+ if w.removed { // avoid removing it twice
+ return
+ }
+ w.removed = true
+ l.Remove(elem)
+ atomic.AddInt64(&wh.count, -1)
+ reportWatcherRemoved()
+ if l.Len() == 0 {
+ delete(wh.watchers, key)
+ }
+ }
+
+ atomic.AddInt64(&wh.count, 1)
+ reportWatcherAdded()
+
+ return w, nil
+}
+
+func (wh *watcherHub) add(e *Event) {
+ wh.EventHistory.addEvent(e)
+}
+
+// notify function accepts an event and notify to the watchers.
+func (wh *watcherHub) notify(e *Event) {
+ e = wh.EventHistory.addEvent(e) // add event into the eventHistory
+
+ segments := strings.Split(e.Node.Key, "/")
+
+ currPath := "/"
+
+ // walk through all the segments of the path and notify the watchers
+ // if the path is "/foo/bar", it will notify watchers with path "/",
+ // "/foo" and "/foo/bar"
+
+ for _, segment := range segments {
+ currPath = path.Join(currPath, segment)
+ // notify the watchers who interests in the changes of current path
+ wh.notifyWatchers(e, currPath, false)
+ }
+}
+
+func (wh *watcherHub) notifyWatchers(e *Event, nodePath string, deleted bool) {
+ wh.mutex.Lock()
+ defer wh.mutex.Unlock()
+
+ l, ok := wh.watchers[nodePath]
+ if ok {
+ curr := l.Front()
+
+ for curr != nil {
+ next := curr.Next() // save reference to the next one in the list
+
+ w, _ := curr.Value.(*watcher)
+
+ originalPath := (e.Node.Key == nodePath)
+ if (originalPath || !isHidden(nodePath, e.Node.Key)) && w.notify(e, originalPath, deleted) {
+ if !w.stream { // do not remove the stream watcher
+ // if we successfully notify a watcher
+ // we need to remove the watcher from the list
+ // and decrease the counter
+ w.removed = true
+ l.Remove(curr)
+ atomic.AddInt64(&wh.count, -1)
+ reportWatcherRemoved()
+ }
+ }
+
+ curr = next // update current to the next element in the list
+ }
+
+ if l.Len() == 0 {
+ // if we have notified all watcher in the list
+ // we can delete the list
+ delete(wh.watchers, nodePath)
+ }
+ }
+}
+
+// clone function clones the watcherHub and return the cloned one.
+// only clone the static content. do not clone the current watchers.
+func (wh *watcherHub) clone() *watcherHub {
+ clonedHistory := wh.EventHistory.clone()
+
+ return &watcherHub{
+ EventHistory: clonedHistory,
+ }
+}
+
+// isHidden checks to see if key path is considered hidden to watch path i.e. the
+// last element is hidden or it's within a hidden directory
+func isHidden(watchPath, keyPath string) bool {
+ // When deleting a directory, watchPath might be deeper than the actual keyPath
+ // For example, when deleting /foo we also need to notify watchers on /foo/bar.
+ if len(watchPath) > len(keyPath) {
+ return false
+ }
+ // if watch path is just a "/", after path will start without "/"
+ // add a "/" to deal with the special case when watchPath is "/"
+ afterPath := path.Clean("/" + keyPath[len(watchPath):])
+ return strings.Contains(afterPath, "/_")
+}
diff --git a/vendor/github.com/coreos/etcd/version/version.go b/vendor/github.com/coreos/etcd/version/version.go
new file mode 100644
index 00000000..156e0f11
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/version/version.go
@@ -0,0 +1,56 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package version implements etcd version parsing and contains latest version
+// information.
+package version
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/coreos/go-semver/semver"
+)
+
+var (
+ // MinClusterVersion is the min cluster version this etcd binary is compatible with.
+ MinClusterVersion = "3.0.0"
+ Version = "3.3.9"
+ APIVersion = "unknown"
+
+ // Git SHA Value will be set during build
+ GitSHA = "Not provided (use ./build instead of go build)"
+)
+
+func init() {
+ ver, err := semver.NewVersion(Version)
+ if err == nil {
+ APIVersion = fmt.Sprintf("%d.%d", ver.Major, ver.Minor)
+ }
+}
+
+type Versions struct {
+ Server string `json:"etcdserver"`
+ Cluster string `json:"etcdcluster"`
+ // TODO: raft state machine version
+}
+
+// Cluster only keeps the major.minor.
+func Cluster(v string) string {
+ vs := strings.Split(v, ".")
+ if len(vs) <= 2 {
+ return v
+ }
+ return fmt.Sprintf("%s.%s", vs[0], vs[1])
+}
diff --git a/vendor/github.com/coreos/etcd/wal/decoder.go b/vendor/github.com/coreos/etcd/wal/decoder.go
new file mode 100644
index 00000000..6a217f89
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/decoder.go
@@ -0,0 +1,188 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wal
+
+import (
+ "bufio"
+ "encoding/binary"
+ "hash"
+ "io"
+ "sync"
+
+ "github.com/coreos/etcd/pkg/crc"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/wal/walpb"
+)
+
+const minSectorSize = 512
+
+// frameSizeBytes is frame size in bytes, including record size and padding size.
+const frameSizeBytes = 8
+
+type decoder struct {
+ mu sync.Mutex
+ brs []*bufio.Reader
+
+ // lastValidOff file offset following the last valid decoded record
+ lastValidOff int64
+ crc hash.Hash32
+}
+
+func newDecoder(r ...io.Reader) *decoder {
+ readers := make([]*bufio.Reader, len(r))
+ for i := range r {
+ readers[i] = bufio.NewReader(r[i])
+ }
+ return &decoder{
+ brs: readers,
+ crc: crc.New(0, crcTable),
+ }
+}
+
+func (d *decoder) decode(rec *walpb.Record) error {
+ rec.Reset()
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ return d.decodeRecord(rec)
+}
+
+func (d *decoder) decodeRecord(rec *walpb.Record) error {
+ if len(d.brs) == 0 {
+ return io.EOF
+ }
+
+ l, err := readInt64(d.brs[0])
+ if err == io.EOF || (err == nil && l == 0) {
+ // hit end of file or preallocated space
+ d.brs = d.brs[1:]
+ if len(d.brs) == 0 {
+ return io.EOF
+ }
+ d.lastValidOff = 0
+ return d.decodeRecord(rec)
+ }
+ if err != nil {
+ return err
+ }
+
+ recBytes, padBytes := decodeFrameSize(l)
+
+ data := make([]byte, recBytes+padBytes)
+ if _, err = io.ReadFull(d.brs[0], data); err != nil {
+ // ReadFull returns io.EOF only if no bytes were read
+ // the decoder should treat this as an ErrUnexpectedEOF instead.
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return err
+ }
+ if err := rec.Unmarshal(data[:recBytes]); err != nil {
+ if d.isTornEntry(data) {
+ return io.ErrUnexpectedEOF
+ }
+ return err
+ }
+
+ // skip crc checking if the record type is crcType
+ if rec.Type != crcType {
+ d.crc.Write(rec.Data)
+ if err := rec.Validate(d.crc.Sum32()); err != nil {
+ if d.isTornEntry(data) {
+ return io.ErrUnexpectedEOF
+ }
+ return err
+ }
+ }
+ // record decoded as valid; point last valid offset to end of record
+ d.lastValidOff += frameSizeBytes + recBytes + padBytes
+ return nil
+}
+
+func decodeFrameSize(lenField int64) (recBytes int64, padBytes int64) {
+ // the record size is stored in the lower 56 bits of the 64-bit length
+ recBytes = int64(uint64(lenField) & ^(uint64(0xff) << 56))
+ // non-zero padding is indicated by set MSb / a negative length
+ if lenField < 0 {
+ // padding is stored in lower 3 bits of length MSB
+ padBytes = int64((uint64(lenField) >> 56) & 0x7)
+ }
+ return recBytes, padBytes
+}
+
+// isTornEntry determines whether the last entry of the WAL was partially written
+// and corrupted because of a torn write.
+func (d *decoder) isTornEntry(data []byte) bool {
+ if len(d.brs) != 1 {
+ return false
+ }
+
+ fileOff := d.lastValidOff + frameSizeBytes
+ curOff := 0
+ chunks := [][]byte{}
+ // split data on sector boundaries
+ for curOff < len(data) {
+ chunkLen := int(minSectorSize - (fileOff % minSectorSize))
+ if chunkLen > len(data)-curOff {
+ chunkLen = len(data) - curOff
+ }
+ chunks = append(chunks, data[curOff:curOff+chunkLen])
+ fileOff += int64(chunkLen)
+ curOff += chunkLen
+ }
+
+ // if any data for a sector chunk is all 0, it's a torn write
+ for _, sect := range chunks {
+ isZero := true
+ for _, v := range sect {
+ if v != 0 {
+ isZero = false
+ break
+ }
+ }
+ if isZero {
+ return true
+ }
+ }
+ return false
+}
+
+func (d *decoder) updateCRC(prevCrc uint32) {
+ d.crc = crc.New(prevCrc, crcTable)
+}
+
+func (d *decoder) lastCRC() uint32 {
+ return d.crc.Sum32()
+}
+
+func (d *decoder) lastOffset() int64 { return d.lastValidOff }
+
+func mustUnmarshalEntry(d []byte) raftpb.Entry {
+ var e raftpb.Entry
+ pbutil.MustUnmarshal(&e, d)
+ return e
+}
+
+func mustUnmarshalState(d []byte) raftpb.HardState {
+ var s raftpb.HardState
+ pbutil.MustUnmarshal(&s, d)
+ return s
+}
+
+func readInt64(r io.Reader) (int64, error) {
+ var n int64
+ err := binary.Read(r, binary.LittleEndian, &n)
+ return n, err
+}
diff --git a/vendor/github.com/coreos/etcd/wal/doc.go b/vendor/github.com/coreos/etcd/wal/doc.go
new file mode 100644
index 00000000..a3abd696
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/doc.go
@@ -0,0 +1,75 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+Package wal provides an implementation of a write ahead log that is used by
+etcd.
+
+A WAL is created at a particular directory and is made up of a number of
+segmented WAL files. Inside of each file the raft state and entries are appended
+to it with the Save method:
+
+ metadata := []byte{}
+ w, err := wal.Create("/var/lib/etcd", metadata)
+ ...
+ err := w.Save(s, ents)
+
+After saving a raft snapshot to disk, SaveSnapshot method should be called to
+record it. So WAL can match with the saved snapshot when restarting.
+
+ err := w.SaveSnapshot(walpb.Snapshot{Index: 10, Term: 2})
+
+When a user has finished using a WAL it must be closed:
+
+ w.Close()
+
+Each WAL file is a stream of WAL records. A WAL record is a length field and a wal record
+protobuf. The record protobuf contains a CRC, a type, and a data payload. The length field is a
+64-bit packed structure holding the length of the remaining logical record data in its lower
+56 bits and its physical padding in the first three bits of the most significant byte. Each
+record is 8-byte aligned so that the length field is never torn. The CRC contains the CRC32
+value of all record protobufs preceding the current record.
+
+WAL files are placed inside of the directory in the following format:
+$seq-$index.wal
+
+The first WAL file to be created will be 0000000000000000-0000000000000000.wal
+indicating an initial sequence of 0 and an initial raft index of 0. The first
+entry written to WAL MUST have raft index 0.
+
+WAL will cut its current tail wal file if its size exceeds 64MB. This will increment an internal
+sequence number and cause a new file to be created. If the last raft index saved
+was 0x20 and this is the first time cut has been called on this WAL then the sequence will
+increment from 0x0 to 0x1. The new file will be: 0000000000000001-0000000000000021.wal.
+If a second cut issues 0x10 entries with incremental index later then the file will be called:
+0000000000000002-0000000000000031.wal.
+
+At a later time a WAL can be opened at a particular snapshot. If there is no
+snapshot, an empty snapshot should be passed in.
+
+ w, err := wal.Open("/var/lib/etcd", walpb.Snapshot{Index: 10, Term: 2})
+ ...
+
+The snapshot must have been written to the WAL.
+
+Additional items cannot be Saved to this WAL until all of the items from the given
+snapshot to the end of the WAL are read first:
+
+ metadata, state, ents, err := w.ReadAll()
+
+This will give you the metadata, the last raft.State and the slice of
+raft.Entry items in the log.
+
+*/
+package wal
diff --git a/vendor/github.com/coreos/etcd/wal/encoder.go b/vendor/github.com/coreos/etcd/wal/encoder.go
new file mode 100644
index 00000000..e8040b8d
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/encoder.go
@@ -0,0 +1,120 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wal
+
+import (
+ "encoding/binary"
+ "hash"
+ "io"
+ "os"
+ "sync"
+
+ "github.com/coreos/etcd/pkg/crc"
+ "github.com/coreos/etcd/pkg/ioutil"
+ "github.com/coreos/etcd/wal/walpb"
+)
+
+// walPageBytes is the alignment for flushing records to the backing Writer.
+// It should be a multiple of the minimum sector size so that WAL can safely
+// distinguish between torn writes and ordinary data corruption.
+const walPageBytes = 8 * minSectorSize
+
+type encoder struct {
+ mu sync.Mutex
+ bw *ioutil.PageWriter
+
+ crc hash.Hash32
+ buf []byte
+ uint64buf []byte
+}
+
+func newEncoder(w io.Writer, prevCrc uint32, pageOffset int) *encoder {
+ return &encoder{
+ bw: ioutil.NewPageWriter(w, walPageBytes, pageOffset),
+ crc: crc.New(prevCrc, crcTable),
+ // 1MB buffer
+ buf: make([]byte, 1024*1024),
+ uint64buf: make([]byte, 8),
+ }
+}
+
+// newFileEncoder creates a new encoder with current file offset for the page writer.
+func newFileEncoder(f *os.File, prevCrc uint32) (*encoder, error) {
+ offset, err := f.Seek(0, io.SeekCurrent)
+ if err != nil {
+ return nil, err
+ }
+ return newEncoder(f, prevCrc, int(offset)), nil
+}
+
+func (e *encoder) encode(rec *walpb.Record) error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ e.crc.Write(rec.Data)
+ rec.Crc = e.crc.Sum32()
+ var (
+ data []byte
+ err error
+ n int
+ )
+
+ if rec.Size() > len(e.buf) {
+ data, err = rec.Marshal()
+ if err != nil {
+ return err
+ }
+ } else {
+ n, err = rec.MarshalTo(e.buf)
+ if err != nil {
+ return err
+ }
+ data = e.buf[:n]
+ }
+
+ lenField, padBytes := encodeFrameSize(len(data))
+ if err = writeUint64(e.bw, lenField, e.uint64buf); err != nil {
+ return err
+ }
+
+ if padBytes != 0 {
+ data = append(data, make([]byte, padBytes)...)
+ }
+ _, err = e.bw.Write(data)
+ return err
+}
+
+func encodeFrameSize(dataBytes int) (lenField uint64, padBytes int) {
+ lenField = uint64(dataBytes)
+ // force 8 byte alignment so length never gets a torn write
+ padBytes = (8 - (dataBytes % 8)) % 8
+ if padBytes != 0 {
+ lenField |= uint64(0x80|padBytes) << 56
+ }
+ return lenField, padBytes
+}
+
+func (e *encoder) flush() error {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+ return e.bw.Flush()
+}
+
+func writeUint64(w io.Writer, n uint64, buf []byte) error {
+ // http://golang.org/src/encoding/binary/binary.go
+ binary.LittleEndian.PutUint64(buf, n)
+ _, err := w.Write(buf)
+ return err
+}
diff --git a/vendor/github.com/coreos/etcd/wal/file_pipeline.go b/vendor/github.com/coreos/etcd/wal/file_pipeline.go
new file mode 100644
index 00000000..3a1c57c1
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/file_pipeline.go
@@ -0,0 +1,97 @@
+// Copyright 2016 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wal
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+
+ "github.com/coreos/etcd/pkg/fileutil"
+)
+
+// filePipeline pipelines allocating disk space
+type filePipeline struct {
+ // dir to put files
+ dir string
+ // size of files to make, in bytes
+ size int64
+ // count number of files generated
+ count int
+
+ filec chan *fileutil.LockedFile
+ errc chan error
+ donec chan struct{}
+}
+
+func newFilePipeline(dir string, fileSize int64) *filePipeline {
+ fp := &filePipeline{
+ dir: dir,
+ size: fileSize,
+ filec: make(chan *fileutil.LockedFile),
+ errc: make(chan error, 1),
+ donec: make(chan struct{}),
+ }
+ go fp.run()
+ return fp
+}
+
+// Open returns a fresh file for writing. Rename the file before calling
+// Open again or there will be file collisions.
+func (fp *filePipeline) Open() (f *fileutil.LockedFile, err error) {
+ select {
+ case f = <-fp.filec:
+ case err = <-fp.errc:
+ }
+ return f, err
+}
+
+func (fp *filePipeline) Close() error {
+ close(fp.donec)
+ return <-fp.errc
+}
+
+func (fp *filePipeline) alloc() (f *fileutil.LockedFile, err error) {
+ // count % 2 so this file isn't the same as the one last published
+ fpath := filepath.Join(fp.dir, fmt.Sprintf("%d.tmp", fp.count%2))
+ if f, err = fileutil.LockFile(fpath, os.O_CREATE|os.O_WRONLY, fileutil.PrivateFileMode); err != nil {
+ return nil, err
+ }
+ if err = fileutil.Preallocate(f.File, fp.size, true); err != nil {
+ plog.Errorf("failed to allocate space when creating new wal file (%v)", err)
+ f.Close()
+ return nil, err
+ }
+ fp.count++
+ return f, nil
+}
+
+func (fp *filePipeline) run() {
+ defer close(fp.errc)
+ for {
+ f, err := fp.alloc()
+ if err != nil {
+ fp.errc <- err
+ return
+ }
+ select {
+ case fp.filec <- f:
+ case <-fp.donec:
+ os.Remove(f.Name())
+ f.Close()
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/coreos/etcd/wal/metrics.go b/vendor/github.com/coreos/etcd/wal/metrics.go
new file mode 100644
index 00000000..9e089d38
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/metrics.go
@@ -0,0 +1,31 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wal
+
+import "github.com/prometheus/client_golang/prometheus"
+
+var (
+ syncDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "etcd",
+ Subsystem: "disk",
+ Name: "wal_fsync_duration_seconds",
+ Help: "The latency distributions of fsync called by wal.",
+ Buckets: prometheus.ExponentialBuckets(0.001, 2, 14),
+ })
+)
+
+func init() {
+ prometheus.MustRegister(syncDurations)
+}
diff --git a/vendor/github.com/coreos/etcd/wal/repair.go b/vendor/github.com/coreos/etcd/wal/repair.go
new file mode 100644
index 00000000..091036b5
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/repair.go
@@ -0,0 +1,99 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wal
+
+import (
+ "io"
+ "os"
+ "path/filepath"
+
+ "github.com/coreos/etcd/pkg/fileutil"
+ "github.com/coreos/etcd/wal/walpb"
+)
+
+// Repair tries to repair ErrUnexpectedEOF in the
+// last wal file by truncating.
+func Repair(dirpath string) bool {
+ f, err := openLast(dirpath)
+ if err != nil {
+ return false
+ }
+ defer f.Close()
+
+ rec := &walpb.Record{}
+ decoder := newDecoder(f)
+ for {
+ lastOffset := decoder.lastOffset()
+ err := decoder.decode(rec)
+ switch err {
+ case nil:
+ // update crc of the decoder when necessary
+ switch rec.Type {
+ case crcType:
+ crc := decoder.crc.Sum32()
+ // current crc of decoder must match the crc of the record.
+ // do no need to match 0 crc, since the decoder is a new one at this case.
+ if crc != 0 && rec.Validate(crc) != nil {
+ return false
+ }
+ decoder.updateCRC(rec.Crc)
+ }
+ continue
+ case io.EOF:
+ return true
+ case io.ErrUnexpectedEOF:
+ plog.Noticef("repairing %v", f.Name())
+ bf, bferr := os.Create(f.Name() + ".broken")
+ if bferr != nil {
+ plog.Errorf("could not repair %v, failed to create backup file", f.Name())
+ return false
+ }
+ defer bf.Close()
+
+ if _, err = f.Seek(0, io.SeekStart); err != nil {
+ plog.Errorf("could not repair %v, failed to read file", f.Name())
+ return false
+ }
+
+ if _, err = io.Copy(bf, f); err != nil {
+ plog.Errorf("could not repair %v, failed to copy file", f.Name())
+ return false
+ }
+
+ if err = f.Truncate(int64(lastOffset)); err != nil {
+ plog.Errorf("could not repair %v, failed to truncate file", f.Name())
+ return false
+ }
+ if err = fileutil.Fsync(f.File); err != nil {
+ plog.Errorf("could not repair %v, failed to sync file", f.Name())
+ return false
+ }
+ return true
+ default:
+ plog.Errorf("could not repair error (%v)", err)
+ return false
+ }
+ }
+}
+
+// openLast opens the last wal file for read and write.
+func openLast(dirpath string) (*fileutil.LockedFile, error) {
+ names, err := readWalNames(dirpath)
+ if err != nil {
+ return nil, err
+ }
+ last := filepath.Join(dirpath, names[len(names)-1])
+ return fileutil.LockFile(last, os.O_RDWR, fileutil.PrivateFileMode)
+}
diff --git a/vendor/github.com/coreos/etcd/wal/util.go b/vendor/github.com/coreos/etcd/wal/util.go
new file mode 100644
index 00000000..5c56e228
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/util.go
@@ -0,0 +1,107 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wal
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/coreos/etcd/pkg/fileutil"
+)
+
+var (
+ badWalName = errors.New("bad wal name")
+)
+
+func Exist(dirpath string) bool {
+ names, err := fileutil.ReadDir(dirpath)
+ if err != nil {
+ return false
+ }
+ return len(names) != 0
+}
+
+// searchIndex returns the last array index of names whose raft index section is
+// equal to or smaller than the given index.
+// The given names MUST be sorted.
+func searchIndex(names []string, index uint64) (int, bool) {
+ for i := len(names) - 1; i >= 0; i-- {
+ name := names[i]
+ _, curIndex, err := parseWalName(name)
+ if err != nil {
+ plog.Panicf("parse correct name should never fail: %v", err)
+ }
+ if index >= curIndex {
+ return i, true
+ }
+ }
+ return -1, false
+}
+
+// names should have been sorted based on sequence number.
+// isValidSeq checks whether seq increases continuously.
+func isValidSeq(names []string) bool {
+ var lastSeq uint64
+ for _, name := range names {
+ curSeq, _, err := parseWalName(name)
+ if err != nil {
+ plog.Panicf("parse correct name should never fail: %v", err)
+ }
+ if lastSeq != 0 && lastSeq != curSeq-1 {
+ return false
+ }
+ lastSeq = curSeq
+ }
+ return true
+}
+func readWalNames(dirpath string) ([]string, error) {
+ names, err := fileutil.ReadDir(dirpath)
+ if err != nil {
+ return nil, err
+ }
+ wnames := checkWalNames(names)
+ if len(wnames) == 0 {
+ return nil, ErrFileNotFound
+ }
+ return wnames, nil
+}
+
+func checkWalNames(names []string) []string {
+ wnames := make([]string, 0)
+ for _, name := range names {
+ if _, _, err := parseWalName(name); err != nil {
+ // don't complain about left over tmp files
+ if !strings.HasSuffix(name, ".tmp") {
+ plog.Warningf("ignored file %v in wal", name)
+ }
+ continue
+ }
+ wnames = append(wnames, name)
+ }
+ return wnames
+}
+
+func parseWalName(str string) (seq, index uint64, err error) {
+ if !strings.HasSuffix(str, ".wal") {
+ return 0, 0, badWalName
+ }
+ _, err = fmt.Sscanf(str, "%016x-%016x.wal", &seq, &index)
+ return seq, index, err
+}
+
+func walName(seq, index uint64) string {
+ return fmt.Sprintf("%016x-%016x.wal", seq, index)
+}
diff --git a/vendor/github.com/coreos/etcd/wal/wal.go b/vendor/github.com/coreos/etcd/wal/wal.go
new file mode 100644
index 00000000..96d01a23
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/wal.go
@@ -0,0 +1,675 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package wal
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "hash/crc32"
+ "io"
+ "os"
+ "path/filepath"
+ "sync"
+ "time"
+
+ "github.com/coreos/etcd/pkg/fileutil"
+ "github.com/coreos/etcd/pkg/pbutil"
+ "github.com/coreos/etcd/raft"
+ "github.com/coreos/etcd/raft/raftpb"
+ "github.com/coreos/etcd/wal/walpb"
+
+ "github.com/coreos/pkg/capnslog"
+)
+
+const (
+ metadataType int64 = iota + 1
+ entryType
+ stateType
+ crcType
+ snapshotType
+
+ // warnSyncDuration is the amount of time allotted to an fsync before
+ // logging a warning
+ warnSyncDuration = time.Second
+)
+
+var (
+ // SegmentSizeBytes is the preallocated size of each wal segment file.
+ // The actual size might be larger than this. In general, the default
+ // value should be used, but this is defined as an exported variable
+ // so that tests can set a different segment size.
+ SegmentSizeBytes int64 = 64 * 1000 * 1000 // 64MB
+
+ plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "wal")
+
+ ErrMetadataConflict = errors.New("wal: conflicting metadata found")
+ ErrFileNotFound = errors.New("wal: file not found")
+ ErrCRCMismatch = errors.New("wal: crc mismatch")
+ ErrSnapshotMismatch = errors.New("wal: snapshot mismatch")
+ ErrSnapshotNotFound = errors.New("wal: snapshot not found")
+ crcTable = crc32.MakeTable(crc32.Castagnoli)
+)
+
+// WAL is a logical representation of the stable storage.
+// WAL is either in read mode or append mode but not both.
+// A newly created WAL is in append mode, and ready for appending records.
+// A just opened WAL is in read mode, and ready for reading records.
+// The WAL will be ready for appending after reading out all the previous records.
+type WAL struct {
+ dir string // the living directory of the underlay files
+
+ // dirFile is a fd for the wal directory for syncing on Rename
+ dirFile *os.File
+
+ metadata []byte // metadata recorded at the head of each WAL
+ state raftpb.HardState // hardstate recorded at the head of WAL
+
+ start walpb.Snapshot // snapshot to start reading
+ decoder *decoder // decoder to decode records
+ readClose func() error // closer for decode reader
+
+ mu sync.Mutex
+ enti uint64 // index of the last entry saved to the wal
+ encoder *encoder // encoder to encode records
+
+ locks []*fileutil.LockedFile // the locked files the WAL holds (the name is increasing)
+ fp *filePipeline
+}
+
+// Create creates a WAL ready for appending records. The given metadata is
+// recorded at the head of each WAL file, and can be retrieved with ReadAll.
+func Create(dirpath string, metadata []byte) (*WAL, error) {
+ if Exist(dirpath) {
+ return nil, os.ErrExist
+ }
+
+ // keep temporary wal directory so WAL initialization appears atomic
+ tmpdirpath := filepath.Clean(dirpath) + ".tmp"
+ if fileutil.Exist(tmpdirpath) {
+ if err := os.RemoveAll(tmpdirpath); err != nil {
+ return nil, err
+ }
+ }
+ if err := fileutil.CreateDirAll(tmpdirpath); err != nil {
+ return nil, err
+ }
+
+ p := filepath.Join(tmpdirpath, walName(0, 0))
+ f, err := fileutil.LockFile(p, os.O_WRONLY|os.O_CREATE, fileutil.PrivateFileMode)
+ if err != nil {
+ return nil, err
+ }
+ if _, err = f.Seek(0, io.SeekEnd); err != nil {
+ return nil, err
+ }
+ if err = fileutil.Preallocate(f.File, SegmentSizeBytes, true); err != nil {
+ return nil, err
+ }
+
+ w := &WAL{
+ dir: dirpath,
+ metadata: metadata,
+ }
+ w.encoder, err = newFileEncoder(f.File, 0)
+ if err != nil {
+ return nil, err
+ }
+ w.locks = append(w.locks, f)
+ if err = w.saveCrc(0); err != nil {
+ return nil, err
+ }
+ if err = w.encoder.encode(&walpb.Record{Type: metadataType, Data: metadata}); err != nil {
+ return nil, err
+ }
+ if err = w.SaveSnapshot(walpb.Snapshot{}); err != nil {
+ return nil, err
+ }
+
+ if w, err = w.renameWal(tmpdirpath); err != nil {
+ return nil, err
+ }
+
+ // directory was renamed; sync parent dir to persist rename
+ pdir, perr := fileutil.OpenDir(filepath.Dir(w.dir))
+ if perr != nil {
+ return nil, perr
+ }
+ if perr = fileutil.Fsync(pdir); perr != nil {
+ return nil, perr
+ }
+ if perr = pdir.Close(); err != nil {
+ return nil, perr
+ }
+
+ return w, nil
+}
+
+func (w *WAL) renameWal(tmpdirpath string) (*WAL, error) {
+ if err := os.RemoveAll(w.dir); err != nil {
+ return nil, err
+ }
+ // On non-Windows platforms, hold the lock while renaming. Releasing
+ // the lock and trying to reacquire it quickly can be flaky because
+ // it's possible the process will fork to spawn a process while this is
+ // happening. The fds are set up as close-on-exec by the Go runtime,
+ // but there is a window between the fork and the exec where another
+ // process holds the lock.
+ if err := os.Rename(tmpdirpath, w.dir); err != nil {
+ if _, ok := err.(*os.LinkError); ok {
+ return w.renameWalUnlock(tmpdirpath)
+ }
+ return nil, err
+ }
+ w.fp = newFilePipeline(w.dir, SegmentSizeBytes)
+ df, err := fileutil.OpenDir(w.dir)
+ w.dirFile = df
+ return w, err
+}
+
+func (w *WAL) renameWalUnlock(tmpdirpath string) (*WAL, error) {
+ // rename of directory with locked files doesn't work on windows/cifs;
+ // close the WAL to release the locks so the directory can be renamed.
+ plog.Infof("releasing file lock to rename %q to %q", tmpdirpath, w.dir)
+ w.Close()
+ if err := os.Rename(tmpdirpath, w.dir); err != nil {
+ return nil, err
+ }
+ // reopen and relock
+ newWAL, oerr := Open(w.dir, walpb.Snapshot{})
+ if oerr != nil {
+ return nil, oerr
+ }
+ if _, _, _, err := newWAL.ReadAll(); err != nil {
+ newWAL.Close()
+ return nil, err
+ }
+ return newWAL, nil
+}
+
+// Open opens the WAL at the given snap.
+// The snap SHOULD have been previously saved to the WAL, or the following
+// ReadAll will fail.
+// The returned WAL is ready to read and the first record will be the one after
+// the given snap. The WAL cannot be appended to before reading out all of its
+// previous records.
+func Open(dirpath string, snap walpb.Snapshot) (*WAL, error) {
+ w, err := openAtIndex(dirpath, snap, true)
+ if err != nil {
+ return nil, err
+ }
+ if w.dirFile, err = fileutil.OpenDir(w.dir); err != nil {
+ return nil, err
+ }
+ return w, nil
+}
+
+// OpenForRead only opens the wal files for read.
+// Write on a read only wal panics.
+func OpenForRead(dirpath string, snap walpb.Snapshot) (*WAL, error) {
+ return openAtIndex(dirpath, snap, false)
+}
+
+func openAtIndex(dirpath string, snap walpb.Snapshot, write bool) (*WAL, error) {
+ names, err := readWalNames(dirpath)
+ if err != nil {
+ return nil, err
+ }
+
+ nameIndex, ok := searchIndex(names, snap.Index)
+ if !ok || !isValidSeq(names[nameIndex:]) {
+ return nil, ErrFileNotFound
+ }
+
+ // open the wal files
+ rcs := make([]io.ReadCloser, 0)
+ rs := make([]io.Reader, 0)
+ ls := make([]*fileutil.LockedFile, 0)
+ for _, name := range names[nameIndex:] {
+ p := filepath.Join(dirpath, name)
+ if write {
+ l, err := fileutil.TryLockFile(p, os.O_RDWR, fileutil.PrivateFileMode)
+ if err != nil {
+ closeAll(rcs...)
+ return nil, err
+ }
+ ls = append(ls, l)
+ rcs = append(rcs, l)
+ } else {
+ rf, err := os.OpenFile(p, os.O_RDONLY, fileutil.PrivateFileMode)
+ if err != nil {
+ closeAll(rcs...)
+ return nil, err
+ }
+ ls = append(ls, nil)
+ rcs = append(rcs, rf)
+ }
+ rs = append(rs, rcs[len(rcs)-1])
+ }
+
+ closer := func() error { return closeAll(rcs...) }
+
+ // create a WAL ready for reading
+ w := &WAL{
+ dir: dirpath,
+ start: snap,
+ decoder: newDecoder(rs...),
+ readClose: closer,
+ locks: ls,
+ }
+
+ if write {
+ // write reuses the file descriptors from read; don't close so
+ // WAL can append without dropping the file lock
+ w.readClose = nil
+ if _, _, err := parseWalName(filepath.Base(w.tail().Name())); err != nil {
+ closer()
+ return nil, err
+ }
+ w.fp = newFilePipeline(w.dir, SegmentSizeBytes)
+ }
+
+ return w, nil
+}
+
+// ReadAll reads out records of the current WAL.
+// If opened in write mode, it must read out all records until EOF. Or an error
+// will be returned.
+// If opened in read mode, it will try to read all records if possible.
+// If it cannot read out the expected snap, it will return ErrSnapshotNotFound.
+// If loaded snap doesn't match with the expected one, it will return
+// all the records and error ErrSnapshotMismatch.
+// TODO: detect not-last-snap error.
+// TODO: maybe loose the checking of match.
+// After ReadAll, the WAL will be ready for appending new records.
+func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.Entry, err error) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ rec := &walpb.Record{}
+ decoder := w.decoder
+
+ var match bool
+ for err = decoder.decode(rec); err == nil; err = decoder.decode(rec) {
+ switch rec.Type {
+ case entryType:
+ e := mustUnmarshalEntry(rec.Data)
+ if e.Index > w.start.Index {
+ ents = append(ents[:e.Index-w.start.Index-1], e)
+ }
+ w.enti = e.Index
+ case stateType:
+ state = mustUnmarshalState(rec.Data)
+ case metadataType:
+ if metadata != nil && !bytes.Equal(metadata, rec.Data) {
+ state.Reset()
+ return nil, state, nil, ErrMetadataConflict
+ }
+ metadata = rec.Data
+ case crcType:
+ crc := decoder.crc.Sum32()
+ // current crc of decoder must match the crc of the record.
+ // do no need to match 0 crc, since the decoder is a new one at this case.
+ if crc != 0 && rec.Validate(crc) != nil {
+ state.Reset()
+ return nil, state, nil, ErrCRCMismatch
+ }
+ decoder.updateCRC(rec.Crc)
+ case snapshotType:
+ var snap walpb.Snapshot
+ pbutil.MustUnmarshal(&snap, rec.Data)
+ if snap.Index == w.start.Index {
+ if snap.Term != w.start.Term {
+ state.Reset()
+ return nil, state, nil, ErrSnapshotMismatch
+ }
+ match = true
+ }
+ default:
+ state.Reset()
+ return nil, state, nil, fmt.Errorf("unexpected block type %d", rec.Type)
+ }
+ }
+
+ switch w.tail() {
+ case nil:
+ // We do not have to read out all entries in read mode.
+ // The last record maybe a partial written one, so
+ // ErrunexpectedEOF might be returned.
+ if err != io.EOF && err != io.ErrUnexpectedEOF {
+ state.Reset()
+ return nil, state, nil, err
+ }
+ default:
+ // We must read all of the entries if WAL is opened in write mode.
+ if err != io.EOF {
+ state.Reset()
+ return nil, state, nil, err
+ }
+ // decodeRecord() will return io.EOF if it detects a zero record,
+ // but this zero record may be followed by non-zero records from
+ // a torn write. Overwriting some of these non-zero records, but
+ // not all, will cause CRC errors on WAL open. Since the records
+ // were never fully synced to disk in the first place, it's safe
+ // to zero them out to avoid any CRC errors from new writes.
+ if _, err = w.tail().Seek(w.decoder.lastOffset(), io.SeekStart); err != nil {
+ return nil, state, nil, err
+ }
+ if err = fileutil.ZeroToEnd(w.tail().File); err != nil {
+ return nil, state, nil, err
+ }
+ }
+
+ err = nil
+ if !match {
+ err = ErrSnapshotNotFound
+ }
+
+ // close decoder, disable reading
+ if w.readClose != nil {
+ w.readClose()
+ w.readClose = nil
+ }
+ w.start = walpb.Snapshot{}
+
+ w.metadata = metadata
+
+ if w.tail() != nil {
+ // create encoder (chain crc with the decoder), enable appending
+ w.encoder, err = newFileEncoder(w.tail().File, w.decoder.lastCRC())
+ if err != nil {
+ return
+ }
+ }
+ w.decoder = nil
+
+ return metadata, state, ents, err
+}
+
+// cut closes current file written and creates a new one ready to append.
+// cut first creates a temp wal file and writes necessary headers into it.
+// Then cut atomically rename temp wal file to a wal file.
+func (w *WAL) cut() error {
+ // close old wal file; truncate to avoid wasting space if an early cut
+ off, serr := w.tail().Seek(0, io.SeekCurrent)
+ if serr != nil {
+ return serr
+ }
+ if err := w.tail().Truncate(off); err != nil {
+ return err
+ }
+ if err := w.sync(); err != nil {
+ return err
+ }
+
+ fpath := filepath.Join(w.dir, walName(w.seq()+1, w.enti+1))
+
+ // create a temp wal file with name sequence + 1, or truncate the existing one
+ newTail, err := w.fp.Open()
+ if err != nil {
+ return err
+ }
+
+ // update writer and save the previous crc
+ w.locks = append(w.locks, newTail)
+ prevCrc := w.encoder.crc.Sum32()
+ w.encoder, err = newFileEncoder(w.tail().File, prevCrc)
+ if err != nil {
+ return err
+ }
+ if err = w.saveCrc(prevCrc); err != nil {
+ return err
+ }
+ if err = w.encoder.encode(&walpb.Record{Type: metadataType, Data: w.metadata}); err != nil {
+ return err
+ }
+ if err = w.saveState(&w.state); err != nil {
+ return err
+ }
+ // atomically move temp wal file to wal file
+ if err = w.sync(); err != nil {
+ return err
+ }
+
+ off, err = w.tail().Seek(0, io.SeekCurrent)
+ if err != nil {
+ return err
+ }
+
+ if err = os.Rename(newTail.Name(), fpath); err != nil {
+ return err
+ }
+ if err = fileutil.Fsync(w.dirFile); err != nil {
+ return err
+ }
+
+ // reopen newTail with its new path so calls to Name() match the wal filename format
+ newTail.Close()
+
+ if newTail, err = fileutil.LockFile(fpath, os.O_WRONLY, fileutil.PrivateFileMode); err != nil {
+ return err
+ }
+ if _, err = newTail.Seek(off, io.SeekStart); err != nil {
+ return err
+ }
+
+ w.locks[len(w.locks)-1] = newTail
+
+ prevCrc = w.encoder.crc.Sum32()
+ w.encoder, err = newFileEncoder(w.tail().File, prevCrc)
+ if err != nil {
+ return err
+ }
+
+ plog.Infof("segmented wal file %v is created", fpath)
+ return nil
+}
+
+func (w *WAL) sync() error {
+ if w.encoder != nil {
+ if err := w.encoder.flush(); err != nil {
+ return err
+ }
+ }
+ start := time.Now()
+ err := fileutil.Fdatasync(w.tail().File)
+
+ duration := time.Since(start)
+ if duration > warnSyncDuration {
+ plog.Warningf("sync duration of %v, expected less than %v", duration, warnSyncDuration)
+ }
+ syncDurations.Observe(duration.Seconds())
+
+ return err
+}
+
+// ReleaseLockTo releases the locks, which has smaller index than the given index
+// except the largest one among them.
+// For example, if WAL is holding lock 1,2,3,4,5,6, ReleaseLockTo(4) will release
+// lock 1,2 but keep 3. ReleaseLockTo(5) will release 1,2,3 but keep 4.
+func (w *WAL) ReleaseLockTo(index uint64) error {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ if len(w.locks) == 0 {
+ return nil
+ }
+
+ var smaller int
+ found := false
+
+ for i, l := range w.locks {
+ _, lockIndex, err := parseWalName(filepath.Base(l.Name()))
+ if err != nil {
+ return err
+ }
+ if lockIndex >= index {
+ smaller = i - 1
+ found = true
+ break
+ }
+ }
+
+ // if no lock index is greater than the release index, we can
+ // release lock up to the last one(excluding).
+ if !found {
+ smaller = len(w.locks) - 1
+ }
+
+ if smaller <= 0 {
+ return nil
+ }
+
+ for i := 0; i < smaller; i++ {
+ if w.locks[i] == nil {
+ continue
+ }
+ w.locks[i].Close()
+ }
+ w.locks = w.locks[smaller:]
+
+ return nil
+}
+
+func (w *WAL) Close() error {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ if w.fp != nil {
+ w.fp.Close()
+ w.fp = nil
+ }
+
+ if w.tail() != nil {
+ if err := w.sync(); err != nil {
+ return err
+ }
+ }
+ for _, l := range w.locks {
+ if l == nil {
+ continue
+ }
+ if err := l.Close(); err != nil {
+ plog.Errorf("failed to unlock during closing wal: %s", err)
+ }
+ }
+
+ return w.dirFile.Close()
+}
+
+func (w *WAL) saveEntry(e *raftpb.Entry) error {
+ // TODO: add MustMarshalTo to reduce one allocation.
+ b := pbutil.MustMarshal(e)
+ rec := &walpb.Record{Type: entryType, Data: b}
+ if err := w.encoder.encode(rec); err != nil {
+ return err
+ }
+ w.enti = e.Index
+ return nil
+}
+
+func (w *WAL) saveState(s *raftpb.HardState) error {
+ if raft.IsEmptyHardState(*s) {
+ return nil
+ }
+ w.state = *s
+ b := pbutil.MustMarshal(s)
+ rec := &walpb.Record{Type: stateType, Data: b}
+ return w.encoder.encode(rec)
+}
+
+func (w *WAL) Save(st raftpb.HardState, ents []raftpb.Entry) error {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ // short cut, do not call sync
+ if raft.IsEmptyHardState(st) && len(ents) == 0 {
+ return nil
+ }
+
+ mustSync := raft.MustSync(st, w.state, len(ents))
+
+ // TODO(xiangli): no more reference operator
+ for i := range ents {
+ if err := w.saveEntry(&ents[i]); err != nil {
+ return err
+ }
+ }
+ if err := w.saveState(&st); err != nil {
+ return err
+ }
+
+ curOff, err := w.tail().Seek(0, io.SeekCurrent)
+ if err != nil {
+ return err
+ }
+ if curOff < SegmentSizeBytes {
+ if mustSync {
+ return w.sync()
+ }
+ return nil
+ }
+
+ return w.cut()
+}
+
+func (w *WAL) SaveSnapshot(e walpb.Snapshot) error {
+ b := pbutil.MustMarshal(&e)
+
+ w.mu.Lock()
+ defer w.mu.Unlock()
+
+ rec := &walpb.Record{Type: snapshotType, Data: b}
+ if err := w.encoder.encode(rec); err != nil {
+ return err
+ }
+ // update enti only when snapshot is ahead of last index
+ if w.enti < e.Index {
+ w.enti = e.Index
+ }
+ return w.sync()
+}
+
+func (w *WAL) saveCrc(prevCrc uint32) error {
+ return w.encoder.encode(&walpb.Record{Type: crcType, Crc: prevCrc})
+}
+
+func (w *WAL) tail() *fileutil.LockedFile {
+ if len(w.locks) > 0 {
+ return w.locks[len(w.locks)-1]
+ }
+ return nil
+}
+
+func (w *WAL) seq() uint64 {
+ t := w.tail()
+ if t == nil {
+ return 0
+ }
+ seq, _, err := parseWalName(filepath.Base(t.Name()))
+ if err != nil {
+ plog.Fatalf("bad wal name %s (%v)", t.Name(), err)
+ }
+ return seq
+}
+
+func closeAll(rcs ...io.ReadCloser) error {
+ for _, f := range rcs {
+ if err := f.Close(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/coreos/etcd/wal/walpb/record.go b/vendor/github.com/coreos/etcd/wal/walpb/record.go
new file mode 100644
index 00000000..30a05e0c
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/walpb/record.go
@@ -0,0 +1,29 @@
+// Copyright 2015 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package walpb
+
+import "errors"
+
+var (
+ ErrCRCMismatch = errors.New("walpb: crc mismatch")
+)
+
+func (rec *Record) Validate(crc uint32) error {
+ if rec.Crc == crc {
+ return nil
+ }
+ rec.Reset()
+ return ErrCRCMismatch
+}
diff --git a/vendor/github.com/coreos/etcd/wal/walpb/record.pb.go b/vendor/github.com/coreos/etcd/wal/walpb/record.pb.go
new file mode 100644
index 00000000..3ce63ddc
--- /dev/null
+++ b/vendor/github.com/coreos/etcd/wal/walpb/record.pb.go
@@ -0,0 +1,504 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: record.proto
+
+/*
+ Package walpb is a generated protocol buffer package.
+
+ It is generated from these files:
+ record.proto
+
+ It has these top-level messages:
+ Record
+ Snapshot
+*/
+package walpb
+
+import (
+ "fmt"
+
+ proto "github.com/golang/protobuf/proto"
+
+ math "math"
+
+ _ "github.com/gogo/protobuf/gogoproto"
+
+ io "io"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Record struct {
+ Type int64 `protobuf:"varint,1,opt,name=type" json:"type"`
+ Crc uint32 `protobuf:"varint,2,opt,name=crc" json:"crc"`
+ Data []byte `protobuf:"bytes,3,opt,name=data" json:"data,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Record) Reset() { *m = Record{} }
+func (m *Record) String() string { return proto.CompactTextString(m) }
+func (*Record) ProtoMessage() {}
+func (*Record) Descriptor() ([]byte, []int) { return fileDescriptorRecord, []int{0} }
+
+type Snapshot struct {
+ Index uint64 `protobuf:"varint,1,opt,name=index" json:"index"`
+ Term uint64 `protobuf:"varint,2,opt,name=term" json:"term"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Snapshot) Reset() { *m = Snapshot{} }
+func (m *Snapshot) String() string { return proto.CompactTextString(m) }
+func (*Snapshot) ProtoMessage() {}
+func (*Snapshot) Descriptor() ([]byte, []int) { return fileDescriptorRecord, []int{1} }
+
+func init() {
+ proto.RegisterType((*Record)(nil), "walpb.Record")
+ proto.RegisterType((*Snapshot)(nil), "walpb.Snapshot")
+}
+func (m *Record) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Record) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRecord(dAtA, i, uint64(m.Type))
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRecord(dAtA, i, uint64(m.Crc))
+ if m.Data != nil {
+ dAtA[i] = 0x1a
+ i++
+ i = encodeVarintRecord(dAtA, i, uint64(len(m.Data)))
+ i += copy(dAtA[i:], m.Data)
+ }
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func (m *Snapshot) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalTo(dAtA)
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) {
+ var i int
+ _ = i
+ var l int
+ _ = l
+ dAtA[i] = 0x8
+ i++
+ i = encodeVarintRecord(dAtA, i, uint64(m.Index))
+ dAtA[i] = 0x10
+ i++
+ i = encodeVarintRecord(dAtA, i, uint64(m.Term))
+ if m.XXX_unrecognized != nil {
+ i += copy(dAtA[i:], m.XXX_unrecognized)
+ }
+ return i, nil
+}
+
+func encodeVarintRecord(dAtA []byte, offset int, v uint64) int {
+ for v >= 1<<7 {
+ dAtA[offset] = uint8(v&0x7f | 0x80)
+ v >>= 7
+ offset++
+ }
+ dAtA[offset] = uint8(v)
+ return offset + 1
+}
+func (m *Record) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRecord(uint64(m.Type))
+ n += 1 + sovRecord(uint64(m.Crc))
+ if m.Data != nil {
+ l = len(m.Data)
+ n += 1 + l + sovRecord(uint64(l))
+ }
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func (m *Snapshot) Size() (n int) {
+ var l int
+ _ = l
+ n += 1 + sovRecord(uint64(m.Index))
+ n += 1 + sovRecord(uint64(m.Term))
+ if m.XXX_unrecognized != nil {
+ n += len(m.XXX_unrecognized)
+ }
+ return n
+}
+
+func sovRecord(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+func sozRecord(x uint64) (n int) {
+ return sovRecord(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (m *Record) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Record: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Record: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+ }
+ m.Type = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Type |= (int64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Crc", wireType)
+ }
+ m.Crc = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Crc |= (uint32(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 3:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+ }
+ var byteLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ byteLen |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if byteLen < 0 {
+ return ErrInvalidLengthRecord
+ }
+ postIndex := iNdEx + byteLen
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+ if m.Data == nil {
+ m.Data = []byte{}
+ }
+ iNdEx = postIndex
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRecord(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRecord
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *Snapshot) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: Snapshot: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: Snapshot: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType)
+ }
+ m.Index = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Index |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ case 2:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Term", wireType)
+ }
+ m.Term = 0
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ m.Term |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipRecord(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthRecord
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func skipRecord(dAtA []byte) (n int, err error) {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ wireType := int(wire & 0x7)
+ switch wireType {
+ case 0:
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ iNdEx++
+ if dAtA[iNdEx-1] < 0x80 {
+ break
+ }
+ }
+ return iNdEx, nil
+ case 1:
+ iNdEx += 8
+ return iNdEx, nil
+ case 2:
+ var length int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ length |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ iNdEx += length
+ if length < 0 {
+ return 0, ErrInvalidLengthRecord
+ }
+ return iNdEx, nil
+ case 3:
+ for {
+ var innerWire uint64
+ var start int = iNdEx
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return 0, ErrIntOverflowRecord
+ }
+ if iNdEx >= l {
+ return 0, io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ innerWire |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ innerWireType := int(innerWire & 0x7)
+ if innerWireType == 4 {
+ break
+ }
+ next, err := skipRecord(dAtA[start:])
+ if err != nil {
+ return 0, err
+ }
+ iNdEx = start + next
+ }
+ return iNdEx, nil
+ case 4:
+ return iNdEx, nil
+ case 5:
+ iNdEx += 4
+ return iNdEx, nil
+ default:
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+ }
+ }
+ panic("unreachable")
+}
+
+var (
+ ErrInvalidLengthRecord = fmt.Errorf("proto: negative length found during unmarshaling")
+ ErrIntOverflowRecord = fmt.Errorf("proto: integer overflow")
+)
+
+func init() { proto.RegisterFile("record.proto", fileDescriptorRecord) }
+
+var fileDescriptorRecord = []byte{
+ // 186 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x4a, 0x4d, 0xce,
+ 0x2f, 0x4a, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2d, 0x4f, 0xcc, 0x29, 0x48, 0x92,
+ 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x8b, 0xe8, 0x83, 0x58, 0x10, 0x49, 0x25, 0x3f, 0x2e, 0xb6,
+ 0x20, 0xb0, 0x62, 0x21, 0x09, 0x2e, 0x96, 0x92, 0xca, 0x82, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d,
+ 0x66, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, 0xc0, 0x22, 0x42, 0x62, 0x5c, 0xcc, 0xc9, 0x45,
+ 0xc9, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xbc, 0x50, 0x09, 0x90, 0x80, 0x90, 0x10, 0x17, 0x4b, 0x4a,
+ 0x62, 0x49, 0xa2, 0x04, 0xb3, 0x02, 0xa3, 0x06, 0x4f, 0x10, 0x98, 0xad, 0xe4, 0xc0, 0xc5, 0x11,
+ 0x9c, 0x97, 0x58, 0x50, 0x9c, 0x91, 0x5f, 0x22, 0x24, 0xc5, 0xc5, 0x9a, 0x99, 0x97, 0x92, 0x5a,
+ 0x01, 0x36, 0x92, 0x05, 0xaa, 0x13, 0x22, 0x04, 0xb6, 0x2d, 0xb5, 0x28, 0x17, 0x6c, 0x28, 0x0b,
+ 0xdc, 0xb6, 0xd4, 0xa2, 0x5c, 0x27, 0x91, 0x13, 0x0f, 0xe5, 0x18, 0x4e, 0x3c, 0x92, 0x63, 0xbc,
+ 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x19, 0x8f, 0xe5, 0x18, 0x00, 0x01, 0x00, 0x00,
+ 0xff, 0xff, 0x7f, 0x5e, 0x5c, 0x46, 0xd3, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/coreos/go-semver/LICENSE b/vendor/github.com/coreos/go-semver/LICENSE
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/vendor/github.com/coreos/go-semver/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/coreos/go-semver/semver/semver.go b/vendor/github.com/coreos/go-semver/semver/semver.go
new file mode 100644
index 00000000..110fc23e
--- /dev/null
+++ b/vendor/github.com/coreos/go-semver/semver/semver.go
@@ -0,0 +1,268 @@
+// Copyright 2013-2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Semantic Versions http://semver.org
+package semver
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+type Version struct {
+ Major int64
+ Minor int64
+ Patch int64
+ PreRelease PreRelease
+ Metadata string
+}
+
+type PreRelease string
+
+func splitOff(input *string, delim string) (val string) {
+ parts := strings.SplitN(*input, delim, 2)
+
+ if len(parts) == 2 {
+ *input = parts[0]
+ val = parts[1]
+ }
+
+ return val
+}
+
+func New(version string) *Version {
+ return Must(NewVersion(version))
+}
+
+func NewVersion(version string) (*Version, error) {
+ v := Version{}
+
+ if err := v.Set(version); err != nil {
+ return nil, err
+ }
+
+ return &v, nil
+}
+
+// Must is a helper for wrapping NewVersion and will panic if err is not nil.
+func Must(v *Version, err error) *Version {
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Set parses and updates v from the given version string. Implements flag.Value
+func (v *Version) Set(version string) error {
+ metadata := splitOff(&version, "+")
+ preRelease := PreRelease(splitOff(&version, "-"))
+ dotParts := strings.SplitN(version, ".", 3)
+
+ if len(dotParts) != 3 {
+ return fmt.Errorf("%s is not in dotted-tri format", version)
+ }
+
+ parsed := make([]int64, 3, 3)
+
+ for i, v := range dotParts[:3] {
+ val, err := strconv.ParseInt(v, 10, 64)
+ parsed[i] = val
+ if err != nil {
+ return err
+ }
+ }
+
+ v.Metadata = metadata
+ v.PreRelease = preRelease
+ v.Major = parsed[0]
+ v.Minor = parsed[1]
+ v.Patch = parsed[2]
+ return nil
+}
+
+func (v Version) String() string {
+ var buffer bytes.Buffer
+
+ fmt.Fprintf(&buffer, "%d.%d.%d", v.Major, v.Minor, v.Patch)
+
+ if v.PreRelease != "" {
+ fmt.Fprintf(&buffer, "-%s", v.PreRelease)
+ }
+
+ if v.Metadata != "" {
+ fmt.Fprintf(&buffer, "+%s", v.Metadata)
+ }
+
+ return buffer.String()
+}
+
+func (v *Version) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var data string
+ if err := unmarshal(&data); err != nil {
+ return err
+ }
+ return v.Set(data)
+}
+
+func (v Version) MarshalJSON() ([]byte, error) {
+ return []byte(`"` + v.String() + `"`), nil
+}
+
+func (v *Version) UnmarshalJSON(data []byte) error {
+ l := len(data)
+ if l == 0 || string(data) == `""` {
+ return nil
+ }
+ if l < 2 || data[0] != '"' || data[l-1] != '"' {
+ return errors.New("invalid semver string")
+ }
+ return v.Set(string(data[1 : l-1]))
+}
+
+// Compare tests if v is less than, equal to, or greater than versionB,
+// returning -1, 0, or +1 respectively.
+func (v Version) Compare(versionB Version) int {
+ if cmp := recursiveCompare(v.Slice(), versionB.Slice()); cmp != 0 {
+ return cmp
+ }
+ return preReleaseCompare(v, versionB)
+}
+
+// Equal tests if v is equal to versionB.
+func (v Version) Equal(versionB Version) bool {
+ return v.Compare(versionB) == 0
+}
+
+// LessThan tests if v is less than versionB.
+func (v Version) LessThan(versionB Version) bool {
+ return v.Compare(versionB) < 0
+}
+
+// Slice converts the comparable parts of the semver into a slice of integers.
+func (v Version) Slice() []int64 {
+ return []int64{v.Major, v.Minor, v.Patch}
+}
+
+func (p PreRelease) Slice() []string {
+ preRelease := string(p)
+ return strings.Split(preRelease, ".")
+}
+
+func preReleaseCompare(versionA Version, versionB Version) int {
+ a := versionA.PreRelease
+ b := versionB.PreRelease
+
+ /* Handle the case where if two versions are otherwise equal it is the
+ * one without a PreRelease that is greater */
+ if len(a) == 0 && (len(b) > 0) {
+ return 1
+ } else if len(b) == 0 && (len(a) > 0) {
+ return -1
+ }
+
+ // If there is a prerelease, check and compare each part.
+ return recursivePreReleaseCompare(a.Slice(), b.Slice())
+}
+
+func recursiveCompare(versionA []int64, versionB []int64) int {
+ if len(versionA) == 0 {
+ return 0
+ }
+
+ a := versionA[0]
+ b := versionB[0]
+
+ if a > b {
+ return 1
+ } else if a < b {
+ return -1
+ }
+
+ return recursiveCompare(versionA[1:], versionB[1:])
+}
+
+func recursivePreReleaseCompare(versionA []string, versionB []string) int {
+ // A larger set of pre-release fields has a higher precedence than a smaller set,
+ // if all of the preceding identifiers are equal.
+ if len(versionA) == 0 {
+ if len(versionB) > 0 {
+ return -1
+ }
+ return 0
+ } else if len(versionB) == 0 {
+ // We're longer than versionB so return 1.
+ return 1
+ }
+
+ a := versionA[0]
+ b := versionB[0]
+
+ aInt := false
+ bInt := false
+
+ aI, err := strconv.Atoi(versionA[0])
+ if err == nil {
+ aInt = true
+ }
+
+ bI, err := strconv.Atoi(versionB[0])
+ if err == nil {
+ bInt = true
+ }
+
+ // Handle Integer Comparison
+ if aInt && bInt {
+ if aI > bI {
+ return 1
+ } else if aI < bI {
+ return -1
+ }
+ }
+
+ // Handle String Comparison
+ if a > b {
+ return 1
+ } else if a < b {
+ return -1
+ }
+
+ return recursivePreReleaseCompare(versionA[1:], versionB[1:])
+}
+
+// BumpMajor increments the Major field by 1 and resets all other fields to their default values
+func (v *Version) BumpMajor() {
+ v.Major += 1
+ v.Minor = 0
+ v.Patch = 0
+ v.PreRelease = PreRelease("")
+ v.Metadata = ""
+}
+
+// BumpMinor increments the Minor field by 1 and resets all other fields to their default values
+func (v *Version) BumpMinor() {
+ v.Minor += 1
+ v.Patch = 0
+ v.PreRelease = PreRelease("")
+ v.Metadata = ""
+}
+
+// BumpPatch increments the Patch field by 1 and resets all other fields to their default values
+func (v *Version) BumpPatch() {
+ v.Patch += 1
+ v.PreRelease = PreRelease("")
+ v.Metadata = ""
+}
diff --git a/vendor/github.com/coreos/go-semver/semver/sort.go b/vendor/github.com/coreos/go-semver/semver/sort.go
new file mode 100644
index 00000000..e256b41a
--- /dev/null
+++ b/vendor/github.com/coreos/go-semver/semver/sort.go
@@ -0,0 +1,38 @@
+// Copyright 2013-2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package semver
+
+import (
+ "sort"
+)
+
+type Versions []*Version
+
+func (s Versions) Len() int {
+ return len(s)
+}
+
+func (s Versions) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s Versions) Less(i, j int) bool {
+ return s[i].LessThan(*s[j])
+}
+
+// Sort sorts the given slice of Version
+func Sort(versions []*Version) {
+ sort.Sort(Versions(versions))
+}
diff --git a/vendor/github.com/coreos/go-systemd/LICENSE b/vendor/github.com/coreos/go-systemd/LICENSE
new file mode 100644
index 00000000..37ec93a1
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/LICENSE
@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "[]" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/coreos/go-systemd/NOTICE b/vendor/github.com/coreos/go-systemd/NOTICE
new file mode 100644
index 00000000..23a0ada2
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/NOTICE
@@ -0,0 +1,5 @@
+CoreOS Project
+Copyright 2018 CoreOS, Inc
+
+This product includes software developed at CoreOS, Inc.
+(http://www.coreos.com/).
diff --git a/vendor/github.com/coreos/go-systemd/journal/journal.go b/vendor/github.com/coreos/go-systemd/journal/journal.go
new file mode 100644
index 00000000..ef85a3ba
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/journal/journal.go
@@ -0,0 +1,182 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package journal provides write bindings to the local systemd journal.
+// It is implemented in pure Go and connects to the journal directly over its
+// unix socket.
+//
+// To read from the journal, see the "sdjournal" package, which wraps the
+// sd-journal a C API.
+//
+// http://www.freedesktop.org/software/systemd/man/systemd-journald.service.html
+package journal
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "os"
+ "strconv"
+ "strings"
+ "syscall"
+)
+
+// Priority of a journal message
+type Priority int
+
+const (
+ PriEmerg Priority = iota
+ PriAlert
+ PriCrit
+ PriErr
+ PriWarning
+ PriNotice
+ PriInfo
+ PriDebug
+)
+
+var conn net.Conn
+
+func init() {
+ var err error
+ conn, err = net.Dial("unixgram", "/run/systemd/journal/socket")
+ if err != nil {
+ conn = nil
+ }
+}
+
+// Enabled returns true if the local systemd journal is available for logging
+func Enabled() bool {
+ return conn != nil
+}
+
+// Send a message to the local systemd journal. vars is a map of journald
+// fields to values. Fields must be composed of uppercase letters, numbers,
+// and underscores, but must not start with an underscore. Within these
+// restrictions, any arbitrary field name may be used. Some names have special
+// significance: see the journalctl documentation
+// (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
+// for more details. vars may be nil.
+func Send(message string, priority Priority, vars map[string]string) error {
+ if conn == nil {
+ return journalError("could not connect to journald socket")
+ }
+
+ data := new(bytes.Buffer)
+ appendVariable(data, "PRIORITY", strconv.Itoa(int(priority)))
+ appendVariable(data, "MESSAGE", message)
+ for k, v := range vars {
+ appendVariable(data, k, v)
+ }
+
+ _, err := io.Copy(conn, data)
+ if err != nil && isSocketSpaceError(err) {
+ file, err := tempFd()
+ if err != nil {
+ return journalError(err.Error())
+ }
+ defer file.Close()
+ _, err = io.Copy(file, data)
+ if err != nil {
+ return journalError(err.Error())
+ }
+
+ rights := syscall.UnixRights(int(file.Fd()))
+
+ /* this connection should always be a UnixConn, but better safe than sorry */
+ unixConn, ok := conn.(*net.UnixConn)
+ if !ok {
+ return journalError("can't send file through non-Unix connection")
+ }
+ _, _, err = unixConn.WriteMsgUnix([]byte{}, rights, nil)
+ if err != nil {
+ return journalError(err.Error())
+ }
+ } else if err != nil {
+ return journalError(err.Error())
+ }
+ return nil
+}
+
+// Print prints a message to the local systemd journal using Send().
+func Print(priority Priority, format string, a ...interface{}) error {
+ return Send(fmt.Sprintf(format, a...), priority, nil)
+}
+
+func appendVariable(w io.Writer, name, value string) {
+ if !validVarName(name) {
+ journalError("variable name contains invalid character, ignoring")
+ }
+ if strings.ContainsRune(value, '\n') {
+ /* When the value contains a newline, we write:
+ * - the variable name, followed by a newline
+ * - the size (in 64bit little endian format)
+ * - the data, followed by a newline
+ */
+ fmt.Fprintln(w, name)
+ binary.Write(w, binary.LittleEndian, uint64(len(value)))
+ fmt.Fprintln(w, value)
+ } else {
+ /* just write the variable and value all on one line */
+ fmt.Fprintf(w, "%s=%s\n", name, value)
+ }
+}
+
+func validVarName(name string) bool {
+ /* The variable name must be in uppercase and consist only of characters,
+ * numbers and underscores, and may not begin with an underscore. (from the docs)
+ */
+
+ valid := name[0] != '_'
+ for _, c := range name {
+ valid = valid && ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_'
+ }
+ return valid
+}
+
+func isSocketSpaceError(err error) bool {
+ opErr, ok := err.(*net.OpError)
+ if !ok {
+ return false
+ }
+
+ sysErr, ok := opErr.Err.(syscall.Errno)
+ if !ok {
+ return false
+ }
+
+ return sysErr == syscall.EMSGSIZE || sysErr == syscall.ENOBUFS
+}
+
+func tempFd() (*os.File, error) {
+ file, err := ioutil.TempFile("/dev/shm/", "journal.XXXXX")
+ if err != nil {
+ return nil, err
+ }
+ err = syscall.Unlink(file.Name())
+ if err != nil {
+ return nil, err
+ }
+ return file, nil
+}
+
+func journalError(s string) error {
+ s = "journal error: " + s
+ fmt.Fprintln(os.Stderr, s)
+ return errors.New(s)
+}
diff --git a/vendor/github.com/coreos/pkg/LICENSE b/vendor/github.com/coreos/pkg/LICENSE
new file mode 100644
index 00000000..e06d2081
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/LICENSE
@@ -0,0 +1,202 @@
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/vendor/github.com/coreos/pkg/NOTICE b/vendor/github.com/coreos/pkg/NOTICE
new file mode 100644
index 00000000..b39ddfa5
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/NOTICE
@@ -0,0 +1,5 @@
+CoreOS Project
+Copyright 2014 CoreOS, Inc
+
+This product includes software developed at CoreOS, Inc.
+(http://www.coreos.com/).
diff --git a/vendor/github.com/coreos/pkg/capnslog/formatters.go b/vendor/github.com/coreos/pkg/capnslog/formatters.go
new file mode 100644
index 00000000..b305a845
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/formatters.go
@@ -0,0 +1,157 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "log"
+ "runtime"
+ "strings"
+ "time"
+)
+
+type Formatter interface {
+ Format(pkg string, level LogLevel, depth int, entries ...interface{})
+ Flush()
+}
+
+func NewStringFormatter(w io.Writer) Formatter {
+ return &StringFormatter{
+ w: bufio.NewWriter(w),
+ }
+}
+
+type StringFormatter struct {
+ w *bufio.Writer
+}
+
+func (s *StringFormatter) Format(pkg string, l LogLevel, i int, entries ...interface{}) {
+ now := time.Now().UTC()
+ s.w.WriteString(now.Format(time.RFC3339))
+ s.w.WriteByte(' ')
+ writeEntries(s.w, pkg, l, i, entries...)
+ s.Flush()
+}
+
+func writeEntries(w *bufio.Writer, pkg string, _ LogLevel, _ int, entries ...interface{}) {
+ if pkg != "" {
+ w.WriteString(pkg + ": ")
+ }
+ str := fmt.Sprint(entries...)
+ endsInNL := strings.HasSuffix(str, "\n")
+ w.WriteString(str)
+ if !endsInNL {
+ w.WriteString("\n")
+ }
+}
+
+func (s *StringFormatter) Flush() {
+ s.w.Flush()
+}
+
+func NewPrettyFormatter(w io.Writer, debug bool) Formatter {
+ return &PrettyFormatter{
+ w: bufio.NewWriter(w),
+ debug: debug,
+ }
+}
+
+type PrettyFormatter struct {
+ w *bufio.Writer
+ debug bool
+}
+
+func (c *PrettyFormatter) Format(pkg string, l LogLevel, depth int, entries ...interface{}) {
+ now := time.Now()
+ ts := now.Format("2006-01-02 15:04:05")
+ c.w.WriteString(ts)
+ ms := now.Nanosecond() / 1000
+ c.w.WriteString(fmt.Sprintf(".%06d", ms))
+ if c.debug {
+ _, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
+ if !ok {
+ file = "???"
+ line = 1
+ } else {
+ slash := strings.LastIndex(file, "/")
+ if slash >= 0 {
+ file = file[slash+1:]
+ }
+ }
+ if line < 0 {
+ line = 0 // not a real line number
+ }
+ c.w.WriteString(fmt.Sprintf(" [%s:%d]", file, line))
+ }
+ c.w.WriteString(fmt.Sprint(" ", l.Char(), " | "))
+ writeEntries(c.w, pkg, l, depth, entries...)
+ c.Flush()
+}
+
+func (c *PrettyFormatter) Flush() {
+ c.w.Flush()
+}
+
+// LogFormatter emulates the form of the traditional built-in logger.
+type LogFormatter struct {
+ logger *log.Logger
+ prefix string
+}
+
+// NewLogFormatter is a helper to produce a new LogFormatter struct. It uses the
+// golang log package to actually do the logging work so that logs look similar.
+func NewLogFormatter(w io.Writer, prefix string, flag int) Formatter {
+ return &LogFormatter{
+ logger: log.New(w, "", flag), // don't use prefix here
+ prefix: prefix, // save it instead
+ }
+}
+
+// Format builds a log message for the LogFormatter. The LogLevel is ignored.
+func (lf *LogFormatter) Format(pkg string, _ LogLevel, _ int, entries ...interface{}) {
+ str := fmt.Sprint(entries...)
+ prefix := lf.prefix
+ if pkg != "" {
+ prefix = fmt.Sprintf("%s%s: ", prefix, pkg)
+ }
+ lf.logger.Output(5, fmt.Sprintf("%s%v", prefix, str)) // call depth is 5
+}
+
+// Flush is included so that the interface is complete, but is a no-op.
+func (lf *LogFormatter) Flush() {
+ // noop
+}
+
+// NilFormatter is a no-op log formatter that does nothing.
+type NilFormatter struct {
+}
+
+// NewNilFormatter is a helper to produce a new LogFormatter struct. It logs no
+// messages so that you can cause part of your logging to be silent.
+func NewNilFormatter() Formatter {
+ return &NilFormatter{}
+}
+
+// Format does nothing.
+func (_ *NilFormatter) Format(_ string, _ LogLevel, _ int, _ ...interface{}) {
+ // noop
+}
+
+// Flush is included so that the interface is complete, but is a no-op.
+func (_ *NilFormatter) Flush() {
+ // noop
+}
diff --git a/vendor/github.com/coreos/pkg/capnslog/glog_formatter.go b/vendor/github.com/coreos/pkg/capnslog/glog_formatter.go
new file mode 100644
index 00000000..426603ef
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/glog_formatter.go
@@ -0,0 +1,96 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import (
+ "bufio"
+ "bytes"
+ "io"
+ "os"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+)
+
+var pid = os.Getpid()
+
+type GlogFormatter struct {
+ StringFormatter
+}
+
+func NewGlogFormatter(w io.Writer) *GlogFormatter {
+ g := &GlogFormatter{}
+ g.w = bufio.NewWriter(w)
+ return g
+}
+
+func (g GlogFormatter) Format(pkg string, level LogLevel, depth int, entries ...interface{}) {
+ g.w.Write(GlogHeader(level, depth+1))
+ g.StringFormatter.Format(pkg, level, depth+1, entries...)
+}
+
+func GlogHeader(level LogLevel, depth int) []byte {
+ // Lmmdd hh:mm:ss.uuuuuu threadid file:line]
+ now := time.Now().UTC()
+ _, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
+ if !ok {
+ file = "???"
+ line = 1
+ } else {
+ slash := strings.LastIndex(file, "/")
+ if slash >= 0 {
+ file = file[slash+1:]
+ }
+ }
+ if line < 0 {
+ line = 0 // not a real line number
+ }
+ buf := &bytes.Buffer{}
+ buf.Grow(30)
+ _, month, day := now.Date()
+ hour, minute, second := now.Clock()
+ buf.WriteString(level.Char())
+ twoDigits(buf, int(month))
+ twoDigits(buf, day)
+ buf.WriteByte(' ')
+ twoDigits(buf, hour)
+ buf.WriteByte(':')
+ twoDigits(buf, minute)
+ buf.WriteByte(':')
+ twoDigits(buf, second)
+ buf.WriteByte('.')
+ buf.WriteString(strconv.Itoa(now.Nanosecond() / 1000))
+ buf.WriteByte('Z')
+ buf.WriteByte(' ')
+ buf.WriteString(strconv.Itoa(pid))
+ buf.WriteByte(' ')
+ buf.WriteString(file)
+ buf.WriteByte(':')
+ buf.WriteString(strconv.Itoa(line))
+ buf.WriteByte(']')
+ buf.WriteByte(' ')
+ return buf.Bytes()
+}
+
+const digits = "0123456789"
+
+func twoDigits(b *bytes.Buffer, d int) {
+ c2 := digits[d%10]
+ d /= 10
+ c1 := digits[d%10]
+ b.WriteByte(c1)
+ b.WriteByte(c2)
+}
diff --git a/vendor/github.com/coreos/pkg/capnslog/init.go b/vendor/github.com/coreos/pkg/capnslog/init.go
new file mode 100644
index 00000000..44b8cd36
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/init.go
@@ -0,0 +1,49 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// +build !windows
+
+package capnslog
+
+import (
+ "io"
+ "os"
+ "syscall"
+)
+
+// Here's where the opinionation comes in. We need some sensible defaults,
+// especially after taking over the log package. Your project (whatever it may
+// be) may see things differently. That's okay; there should be no defaults in
+// the main package that cannot be controlled or overridden programatically,
+// otherwise it's a bug. Doing so is creating your own init_log.go file much
+// like this one.
+
+func init() {
+ initHijack()
+
+ // Go `log` pacakge uses os.Stderr.
+ SetFormatter(NewDefaultFormatter(os.Stderr))
+ SetGlobalLogLevel(INFO)
+}
+
+func NewDefaultFormatter(out io.Writer) Formatter {
+ if syscall.Getppid() == 1 {
+ // We're running under init, which may be systemd.
+ f, err := NewJournaldFormatter()
+ if err == nil {
+ return f
+ }
+ }
+ return NewPrettyFormatter(out, false)
+}
diff --git a/vendor/github.com/coreos/pkg/capnslog/init_windows.go b/vendor/github.com/coreos/pkg/capnslog/init_windows.go
new file mode 100644
index 00000000..45530506
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/init_windows.go
@@ -0,0 +1,25 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import "os"
+
+func init() {
+ initHijack()
+
+ // Go `log` package uses os.Stderr.
+ SetFormatter(NewPrettyFormatter(os.Stderr, false))
+ SetGlobalLogLevel(INFO)
+}
diff --git a/vendor/github.com/coreos/pkg/capnslog/journald_formatter.go b/vendor/github.com/coreos/pkg/capnslog/journald_formatter.go
new file mode 100644
index 00000000..72e05207
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/journald_formatter.go
@@ -0,0 +1,68 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// +build !windows
+
+package capnslog
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+
+ "github.com/coreos/go-systemd/journal"
+)
+
+func NewJournaldFormatter() (Formatter, error) {
+ if !journal.Enabled() {
+ return nil, errors.New("No systemd detected")
+ }
+ return &journaldFormatter{}, nil
+}
+
+type journaldFormatter struct{}
+
+func (j *journaldFormatter) Format(pkg string, l LogLevel, _ int, entries ...interface{}) {
+ var pri journal.Priority
+ switch l {
+ case CRITICAL:
+ pri = journal.PriCrit
+ case ERROR:
+ pri = journal.PriErr
+ case WARNING:
+ pri = journal.PriWarning
+ case NOTICE:
+ pri = journal.PriNotice
+ case INFO:
+ pri = journal.PriInfo
+ case DEBUG:
+ pri = journal.PriDebug
+ case TRACE:
+ pri = journal.PriDebug
+ default:
+ panic("Unhandled loglevel")
+ }
+ msg := fmt.Sprint(entries...)
+ tags := map[string]string{
+ "PACKAGE": pkg,
+ "SYSLOG_IDENTIFIER": filepath.Base(os.Args[0]),
+ }
+ err := journal.Send(msg, pri, tags)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ }
+}
+
+func (j *journaldFormatter) Flush() {}
diff --git a/vendor/github.com/coreos/pkg/capnslog/log_hijack.go b/vendor/github.com/coreos/pkg/capnslog/log_hijack.go
new file mode 100644
index 00000000..970086b9
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/log_hijack.go
@@ -0,0 +1,39 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import (
+ "log"
+)
+
+func initHijack() {
+ pkg := NewPackageLogger("log", "")
+ w := packageWriter{pkg}
+ log.SetFlags(0)
+ log.SetPrefix("")
+ log.SetOutput(w)
+}
+
+type packageWriter struct {
+ pl *PackageLogger
+}
+
+func (p packageWriter) Write(b []byte) (int, error) {
+ if p.pl.level < INFO {
+ return 0, nil
+ }
+ p.pl.internalLog(calldepth+2, INFO, string(b))
+ return len(b), nil
+}
diff --git a/vendor/github.com/coreos/pkg/capnslog/logmap.go b/vendor/github.com/coreos/pkg/capnslog/logmap.go
new file mode 100644
index 00000000..226b60c2
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/logmap.go
@@ -0,0 +1,245 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import (
+ "errors"
+ "strings"
+ "sync"
+)
+
+// LogLevel is the set of all log levels.
+type LogLevel int8
+
+const (
+ // CRITICAL is the lowest log level; only errors which will end the program will be propagated.
+ CRITICAL LogLevel = iota - 1
+ // ERROR is for errors that are not fatal but lead to troubling behavior.
+ ERROR
+ // WARNING is for errors which are not fatal and not errors, but are unusual. Often sourced from misconfigurations.
+ WARNING
+ // NOTICE is for normal but significant conditions.
+ NOTICE
+ // INFO is a log level for common, everyday log updates.
+ INFO
+ // DEBUG is the default hidden level for more verbose updates about internal processes.
+ DEBUG
+ // TRACE is for (potentially) call by call tracing of programs.
+ TRACE
+)
+
+// Char returns a single-character representation of the log level.
+func (l LogLevel) Char() string {
+ switch l {
+ case CRITICAL:
+ return "C"
+ case ERROR:
+ return "E"
+ case WARNING:
+ return "W"
+ case NOTICE:
+ return "N"
+ case INFO:
+ return "I"
+ case DEBUG:
+ return "D"
+ case TRACE:
+ return "T"
+ default:
+ panic("Unhandled loglevel")
+ }
+}
+
+// String returns a multi-character representation of the log level.
+func (l LogLevel) String() string {
+ switch l {
+ case CRITICAL:
+ return "CRITICAL"
+ case ERROR:
+ return "ERROR"
+ case WARNING:
+ return "WARNING"
+ case NOTICE:
+ return "NOTICE"
+ case INFO:
+ return "INFO"
+ case DEBUG:
+ return "DEBUG"
+ case TRACE:
+ return "TRACE"
+ default:
+ panic("Unhandled loglevel")
+ }
+}
+
+// Update using the given string value. Fulfills the flag.Value interface.
+func (l *LogLevel) Set(s string) error {
+ value, err := ParseLevel(s)
+ if err != nil {
+ return err
+ }
+
+ *l = value
+ return nil
+}
+
+// Returns an empty string, only here to fulfill the pflag.Value interface.
+func (l *LogLevel) Type() string {
+ return ""
+}
+
+// ParseLevel translates some potential loglevel strings into their corresponding levels.
+func ParseLevel(s string) (LogLevel, error) {
+ switch s {
+ case "CRITICAL", "C":
+ return CRITICAL, nil
+ case "ERROR", "0", "E":
+ return ERROR, nil
+ case "WARNING", "1", "W":
+ return WARNING, nil
+ case "NOTICE", "2", "N":
+ return NOTICE, nil
+ case "INFO", "3", "I":
+ return INFO, nil
+ case "DEBUG", "4", "D":
+ return DEBUG, nil
+ case "TRACE", "5", "T":
+ return TRACE, nil
+ }
+ return CRITICAL, errors.New("couldn't parse log level " + s)
+}
+
+type RepoLogger map[string]*PackageLogger
+
+type loggerStruct struct {
+ sync.Mutex
+ repoMap map[string]RepoLogger
+ formatter Formatter
+}
+
+// logger is the global logger
+var logger = new(loggerStruct)
+
+// SetGlobalLogLevel sets the log level for all packages in all repositories
+// registered with capnslog.
+func SetGlobalLogLevel(l LogLevel) {
+ logger.Lock()
+ defer logger.Unlock()
+ for _, r := range logger.repoMap {
+ r.setRepoLogLevelInternal(l)
+ }
+}
+
+// GetRepoLogger may return the handle to the repository's set of packages' loggers.
+func GetRepoLogger(repo string) (RepoLogger, error) {
+ logger.Lock()
+ defer logger.Unlock()
+ r, ok := logger.repoMap[repo]
+ if !ok {
+ return nil, errors.New("no packages registered for repo " + repo)
+ }
+ return r, nil
+}
+
+// MustRepoLogger returns the handle to the repository's packages' loggers.
+func MustRepoLogger(repo string) RepoLogger {
+ r, err := GetRepoLogger(repo)
+ if err != nil {
+ panic(err)
+ }
+ return r
+}
+
+// SetRepoLogLevel sets the log level for all packages in the repository.
+func (r RepoLogger) SetRepoLogLevel(l LogLevel) {
+ logger.Lock()
+ defer logger.Unlock()
+ r.setRepoLogLevelInternal(l)
+}
+
+func (r RepoLogger) setRepoLogLevelInternal(l LogLevel) {
+ for _, v := range r {
+ v.level = l
+ }
+}
+
+// ParseLogLevelConfig parses a comma-separated string of "package=loglevel", in
+// order, and returns a map of the results, for use in SetLogLevel.
+func (r RepoLogger) ParseLogLevelConfig(conf string) (map[string]LogLevel, error) {
+ setlist := strings.Split(conf, ",")
+ out := make(map[string]LogLevel)
+ for _, setstring := range setlist {
+ setting := strings.Split(setstring, "=")
+ if len(setting) != 2 {
+ return nil, errors.New("oddly structured `pkg=level` option: " + setstring)
+ }
+ l, err := ParseLevel(setting[1])
+ if err != nil {
+ return nil, err
+ }
+ out[setting[0]] = l
+ }
+ return out, nil
+}
+
+// SetLogLevel takes a map of package names within a repository to their desired
+// loglevel, and sets the levels appropriately. Unknown packages are ignored.
+// "*" is a special package name that corresponds to all packages, and will be
+// processed first.
+func (r RepoLogger) SetLogLevel(m map[string]LogLevel) {
+ logger.Lock()
+ defer logger.Unlock()
+ if l, ok := m["*"]; ok {
+ r.setRepoLogLevelInternal(l)
+ }
+ for k, v := range m {
+ l, ok := r[k]
+ if !ok {
+ continue
+ }
+ l.level = v
+ }
+}
+
+// SetFormatter sets the formatting function for all logs.
+func SetFormatter(f Formatter) {
+ logger.Lock()
+ defer logger.Unlock()
+ logger.formatter = f
+}
+
+// NewPackageLogger creates a package logger object.
+// This should be defined as a global var in your package, referencing your repo.
+func NewPackageLogger(repo string, pkg string) (p *PackageLogger) {
+ logger.Lock()
+ defer logger.Unlock()
+ if logger.repoMap == nil {
+ logger.repoMap = make(map[string]RepoLogger)
+ }
+ r, rok := logger.repoMap[repo]
+ if !rok {
+ logger.repoMap[repo] = make(RepoLogger)
+ r = logger.repoMap[repo]
+ }
+ p, pok := r[pkg]
+ if !pok {
+ r[pkg] = &PackageLogger{
+ pkg: pkg,
+ level: INFO,
+ }
+ p = r[pkg]
+ }
+ return
+}
diff --git a/vendor/github.com/coreos/pkg/capnslog/pkg_logger.go b/vendor/github.com/coreos/pkg/capnslog/pkg_logger.go
new file mode 100644
index 00000000..00ff3714
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/pkg_logger.go
@@ -0,0 +1,191 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import (
+ "fmt"
+ "os"
+)
+
+type PackageLogger struct {
+ pkg string
+ level LogLevel
+}
+
+const calldepth = 2
+
+func (p *PackageLogger) internalLog(depth int, inLevel LogLevel, entries ...interface{}) {
+ logger.Lock()
+ defer logger.Unlock()
+ if inLevel != CRITICAL && p.level < inLevel {
+ return
+ }
+ if logger.formatter != nil {
+ logger.formatter.Format(p.pkg, inLevel, depth+1, entries...)
+ }
+}
+
+// SetLevel allows users to change the current logging level.
+func (p *PackageLogger) SetLevel(l LogLevel) {
+ logger.Lock()
+ defer logger.Unlock()
+ p.level = l
+}
+
+// LevelAt checks if the given log level will be outputted under current setting.
+func (p *PackageLogger) LevelAt(l LogLevel) bool {
+ logger.Lock()
+ defer logger.Unlock()
+ return p.level >= l
+}
+
+// Log a formatted string at any level between ERROR and TRACE
+func (p *PackageLogger) Logf(l LogLevel, format string, args ...interface{}) {
+ p.internalLog(calldepth, l, fmt.Sprintf(format, args...))
+}
+
+// Log a message at any level between ERROR and TRACE
+func (p *PackageLogger) Log(l LogLevel, args ...interface{}) {
+ p.internalLog(calldepth, l, fmt.Sprint(args...))
+}
+
+// log stdlib compatibility
+
+func (p *PackageLogger) Println(args ...interface{}) {
+ p.internalLog(calldepth, INFO, fmt.Sprintln(args...))
+}
+
+func (p *PackageLogger) Printf(format string, args ...interface{}) {
+ p.Logf(INFO, format, args...)
+}
+
+func (p *PackageLogger) Print(args ...interface{}) {
+ p.internalLog(calldepth, INFO, fmt.Sprint(args...))
+}
+
+// Panic and fatal
+
+func (p *PackageLogger) Panicf(format string, args ...interface{}) {
+ s := fmt.Sprintf(format, args...)
+ p.internalLog(calldepth, CRITICAL, s)
+ panic(s)
+}
+
+func (p *PackageLogger) Panic(args ...interface{}) {
+ s := fmt.Sprint(args...)
+ p.internalLog(calldepth, CRITICAL, s)
+ panic(s)
+}
+
+func (p *PackageLogger) Panicln(args ...interface{}) {
+ s := fmt.Sprintln(args...)
+ p.internalLog(calldepth, CRITICAL, s)
+ panic(s)
+}
+
+func (p *PackageLogger) Fatalf(format string, args ...interface{}) {
+ p.Logf(CRITICAL, format, args...)
+ os.Exit(1)
+}
+
+func (p *PackageLogger) Fatal(args ...interface{}) {
+ s := fmt.Sprint(args...)
+ p.internalLog(calldepth, CRITICAL, s)
+ os.Exit(1)
+}
+
+func (p *PackageLogger) Fatalln(args ...interface{}) {
+ s := fmt.Sprintln(args...)
+ p.internalLog(calldepth, CRITICAL, s)
+ os.Exit(1)
+}
+
+// Error Functions
+
+func (p *PackageLogger) Errorf(format string, args ...interface{}) {
+ p.Logf(ERROR, format, args...)
+}
+
+func (p *PackageLogger) Error(entries ...interface{}) {
+ p.internalLog(calldepth, ERROR, entries...)
+}
+
+// Warning Functions
+
+func (p *PackageLogger) Warningf(format string, args ...interface{}) {
+ p.Logf(WARNING, format, args...)
+}
+
+func (p *PackageLogger) Warning(entries ...interface{}) {
+ p.internalLog(calldepth, WARNING, entries...)
+}
+
+// Notice Functions
+
+func (p *PackageLogger) Noticef(format string, args ...interface{}) {
+ p.Logf(NOTICE, format, args...)
+}
+
+func (p *PackageLogger) Notice(entries ...interface{}) {
+ p.internalLog(calldepth, NOTICE, entries...)
+}
+
+// Info Functions
+
+func (p *PackageLogger) Infof(format string, args ...interface{}) {
+ p.Logf(INFO, format, args...)
+}
+
+func (p *PackageLogger) Info(entries ...interface{}) {
+ p.internalLog(calldepth, INFO, entries...)
+}
+
+// Debug Functions
+
+func (p *PackageLogger) Debugf(format string, args ...interface{}) {
+ if p.level < DEBUG {
+ return
+ }
+ p.Logf(DEBUG, format, args...)
+}
+
+func (p *PackageLogger) Debug(entries ...interface{}) {
+ if p.level < DEBUG {
+ return
+ }
+ p.internalLog(calldepth, DEBUG, entries...)
+}
+
+// Trace Functions
+
+func (p *PackageLogger) Tracef(format string, args ...interface{}) {
+ if p.level < TRACE {
+ return
+ }
+ p.Logf(TRACE, format, args...)
+}
+
+func (p *PackageLogger) Trace(entries ...interface{}) {
+ if p.level < TRACE {
+ return
+ }
+ p.internalLog(calldepth, TRACE, entries...)
+}
+
+func (p *PackageLogger) Flush() {
+ logger.Lock()
+ defer logger.Unlock()
+ logger.formatter.Flush()
+}
diff --git a/vendor/github.com/coreos/pkg/capnslog/syslog_formatter.go b/vendor/github.com/coreos/pkg/capnslog/syslog_formatter.go
new file mode 100644
index 00000000..4be5a1f2
--- /dev/null
+++ b/vendor/github.com/coreos/pkg/capnslog/syslog_formatter.go
@@ -0,0 +1,65 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// +build !windows
+
+package capnslog
+
+import (
+ "fmt"
+ "log/syslog"
+)
+
+func NewSyslogFormatter(w *syslog.Writer) Formatter {
+ return &syslogFormatter{w}
+}
+
+func NewDefaultSyslogFormatter(tag string) (Formatter, error) {
+ w, err := syslog.New(syslog.LOG_DEBUG, tag)
+ if err != nil {
+ return nil, err
+ }
+ return NewSyslogFormatter(w), nil
+}
+
+type syslogFormatter struct {
+ w *syslog.Writer
+}
+
+func (s *syslogFormatter) Format(pkg string, l LogLevel, _ int, entries ...interface{}) {
+ for _, entry := range entries {
+ str := fmt.Sprint(entry)
+ switch l {
+ case CRITICAL:
+ s.w.Crit(str)
+ case ERROR:
+ s.w.Err(str)
+ case WARNING:
+ s.w.Warning(str)
+ case NOTICE:
+ s.w.Notice(str)
+ case INFO:
+ s.w.Info(str)
+ case DEBUG:
+ s.w.Debug(str)
+ case TRACE:
+ s.w.Debug(str)
+ default:
+ panic("Unhandled loglevel")
+ }
+ }
+}
+
+func (s *syslogFormatter) Flush() {
+}
diff --git a/vendor/github.com/docker/distribution/AUTHORS b/vendor/github.com/docker/distribution/AUTHORS
new file mode 100644
index 00000000..aaf02987
--- /dev/null
+++ b/vendor/github.com/docker/distribution/AUTHORS
@@ -0,0 +1,182 @@
+Aaron Lehmann
+Aaron Schlesinger
+Aaron Vinson
+Adam Duke
+Adam Enger
+Adrian Mouat
+Ahmet Alp Balkan
+Alex Chan
+Alex Elman
+Alexey Gladkov
+allencloud
+amitshukla
+Amy Lindburg
+Andrew Hsu
+Andrew Meredith
+Andrew T Nguyen
+Andrey Kostov
+Andy Goldstein
+Anis Elleuch
+Antonio Mercado
+Antonio Murdaca
+Anton Tiurin
+Anusha Ragunathan
+a-palchikov
+Arien Holthuizen
+Arnaud Porterie
+Arthur Baars
+Asuka Suzuki
+Avi Miller
+Ayose Cazorla
+BadZen
+Ben Bodenmiller
+Ben Firshman
+bin liu
+Brian Bland
+burnettk
+Carson A
+Cezar Sa Espinola
+Charles Smith
+Chris Dillon
+cuiwei13
+cyli
+Daisuke Fujita
+Daniel Huhn
+Darren Shepherd
+Dave Trombley
+Dave Tucker
+David Lawrence
+davidli
+David Verhasselt
+David Xia
+Dejan Golja
+Derek McGowan
+Diogo Mónica
+DJ Enriquez
+Donald Huang
+Doug Davis
+Edgar Lee
+Eric Yang
+Fabio Berchtold
+Fabio Huser
+farmerworking
+Felix Yan
+Florentin Raud
+Frank Chen
+Frederick F. Kautz IV
+gabriell nascimento
+Gleb Schukin
+harche
+Henri Gomez
+Hua Wang
+Hu Keping
+HuKeping
+Ian Babrou
+igayoso
+Jack Griffin
+James Findley
+Jason Freidman
+Jason Heiss
+Jeff Nickoloff
+Jess Frazelle
+Jessie Frazelle
+jhaohai
+Jianqing Wang
+Jihoon Chung
+Joao Fernandes
+John Mulhausen
+John Starks
+Jonathan Boulle
+Jon Johnson
+Jon Poler
+Jordan Liggitt
+Josh Chorlton
+Josh Hawn
+Julien Fernandez
+Keerthan Mala
+Kelsey Hightower
+Kenneth Lim
+Kenny Leung
+Ke Xu
+liuchang0812
+Liu Hua
+Li Yi
+Lloyd Ramey
+Louis Kottmann
+Luke Carpenter
+Marcus Martins
+Mary Anthony
+Matt Bentley
+Matt Duch
+Matthew Green
+Matt Moore
+Matt Robenolt
+Michael Prokop
+Michal Minar
+Michal Minář
+Mike Brown
+Miquel Sabaté
+Misty Stanley-Jones
+Morgan Bauer
+moxiegirl
+Nathan Sullivan
+nevermosby
+Nghia Tran
+Nikita Tarasov
+Noah Treuhaft
+Nuutti Kotivuori
+Oilbeater
+Olivier Gambier
+Olivier Jacques
+Omer Cohen
+Patrick Devine
+Phil Estes
+Philip Misiowiec
+Pierre-Yves Ritschard
+Qiao Anran
+Randy Barlow
+Richard Scothern
+Rodolfo Carvalho
+Rusty Conover
+Sean Boran
+Sebastiaan van Stijn
+Sebastien Coavoux
+Serge Dubrouski
+Sharif Nassar
+Shawn Falkner-Horine
+Shreyas Karnik
+Simon Thulbourn
+spacexnice
+Spencer Rinehart
+Stan Hu
+Stefan Majewsky
+Stefan Weil
+Stephen J Day
+Sungho Moon
+Sven Dowideit
+Sylvain Baubeau
+Ted Reed
+tgic
+Thomas Sjögren
+Tianon Gravi
+Tibor Vass
+Tonis Tiigi
+Tony Holdstock-Brown
+Trevor Pounds
+Troels Thomsen
+Victoria Bialas
+Victor Vieux
+Vincent Batts
+Vincent Demeester
+Vincent Giersch
+weiyuan.yl
+W. Trevor King
+xg.song
+xiekeyang
+Yann ROBERT
+yaoyao.xyy
+yixi zhang
+yuexiao-wang
+yuzou
+zhouhaibing089
+姜继忠
diff --git a/vendor/github.com/docker/distribution/LICENSE b/vendor/github.com/docker/distribution/LICENSE
new file mode 100644
index 00000000..e06d2081
--- /dev/null
+++ b/vendor/github.com/docker/distribution/LICENSE
@@ -0,0 +1,202 @@
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/vendor/github.com/docker/distribution/digest/digest.go b/vendor/github.com/docker/distribution/digest/digest.go
new file mode 100644
index 00000000..31d821bb
--- /dev/null
+++ b/vendor/github.com/docker/distribution/digest/digest.go
@@ -0,0 +1,139 @@
+package digest
+
+import (
+ "fmt"
+ "hash"
+ "io"
+ "regexp"
+ "strings"
+)
+
+const (
+ // DigestSha256EmptyTar is the canonical sha256 digest of empty data
+ DigestSha256EmptyTar = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+)
+
+// Digest allows simple protection of hex formatted digest strings, prefixed
+// by their algorithm. Strings of type Digest have some guarantee of being in
+// the correct format and it provides quick access to the components of a
+// digest string.
+//
+// The following is an example of the contents of Digest types:
+//
+// sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc
+//
+// This allows to abstract the digest behind this type and work only in those
+// terms.
+type Digest string
+
+// NewDigest returns a Digest from alg and a hash.Hash object.
+func NewDigest(alg Algorithm, h hash.Hash) Digest {
+ return NewDigestFromBytes(alg, h.Sum(nil))
+}
+
+// NewDigestFromBytes returns a new digest from the byte contents of p.
+// Typically, this can come from hash.Hash.Sum(...) or xxx.SumXXX(...)
+// functions. This is also useful for rebuilding digests from binary
+// serializations.
+func NewDigestFromBytes(alg Algorithm, p []byte) Digest {
+ return Digest(fmt.Sprintf("%s:%x", alg, p))
+}
+
+// NewDigestFromHex returns a Digest from alg and a the hex encoded digest.
+func NewDigestFromHex(alg, hex string) Digest {
+ return Digest(fmt.Sprintf("%s:%s", alg, hex))
+}
+
+// DigestRegexp matches valid digest types.
+var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+`)
+
+// DigestRegexpAnchored matches valid digest types, anchored to the start and end of the match.
+var DigestRegexpAnchored = regexp.MustCompile(`^` + DigestRegexp.String() + `$`)
+
+var (
+ // ErrDigestInvalidFormat returned when digest format invalid.
+ ErrDigestInvalidFormat = fmt.Errorf("invalid checksum digest format")
+
+ // ErrDigestInvalidLength returned when digest has invalid length.
+ ErrDigestInvalidLength = fmt.Errorf("invalid checksum digest length")
+
+ // ErrDigestUnsupported returned when the digest algorithm is unsupported.
+ ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm")
+)
+
+// ParseDigest parses s and returns the validated digest object. An error will
+// be returned if the format is invalid.
+func ParseDigest(s string) (Digest, error) {
+ d := Digest(s)
+
+ return d, d.Validate()
+}
+
+// FromReader returns the most valid digest for the underlying content using
+// the canonical digest algorithm.
+func FromReader(rd io.Reader) (Digest, error) {
+ return Canonical.FromReader(rd)
+}
+
+// FromBytes digests the input and returns a Digest.
+func FromBytes(p []byte) Digest {
+ return Canonical.FromBytes(p)
+}
+
+// Validate checks that the contents of d is a valid digest, returning an
+// error if not.
+func (d Digest) Validate() error {
+ s := string(d)
+
+ if !DigestRegexpAnchored.MatchString(s) {
+ return ErrDigestInvalidFormat
+ }
+
+ i := strings.Index(s, ":")
+ if i < 0 {
+ return ErrDigestInvalidFormat
+ }
+
+ // case: "sha256:" with no hex.
+ if i+1 == len(s) {
+ return ErrDigestInvalidFormat
+ }
+
+ switch algorithm := Algorithm(s[:i]); algorithm {
+ case SHA256, SHA384, SHA512:
+ if algorithm.Size()*2 != len(s[i+1:]) {
+ return ErrDigestInvalidLength
+ }
+ break
+ default:
+ return ErrDigestUnsupported
+ }
+
+ return nil
+}
+
+// Algorithm returns the algorithm portion of the digest. This will panic if
+// the underlying digest is not in a valid format.
+func (d Digest) Algorithm() Algorithm {
+ return Algorithm(d[:d.sepIndex()])
+}
+
+// Hex returns the hex digest portion of the digest. This will panic if the
+// underlying digest is not in a valid format.
+func (d Digest) Hex() string {
+ return string(d[d.sepIndex()+1:])
+}
+
+func (d Digest) String() string {
+ return string(d)
+}
+
+func (d Digest) sepIndex() int {
+ i := strings.Index(string(d), ":")
+
+ if i < 0 {
+ panic("could not find ':' in digest: " + d)
+ }
+
+ return i
+}
diff --git a/vendor/github.com/docker/distribution/digest/digester.go b/vendor/github.com/docker/distribution/digest/digester.go
new file mode 100644
index 00000000..f3105a45
--- /dev/null
+++ b/vendor/github.com/docker/distribution/digest/digester.go
@@ -0,0 +1,155 @@
+package digest
+
+import (
+ "crypto"
+ "fmt"
+ "hash"
+ "io"
+)
+
+// Algorithm identifies and implementation of a digester by an identifier.
+// Note the that this defines both the hash algorithm used and the string
+// encoding.
+type Algorithm string
+
+// supported digest types
+const (
+ SHA256 Algorithm = "sha256" // sha256 with hex encoding
+ SHA384 Algorithm = "sha384" // sha384 with hex encoding
+ SHA512 Algorithm = "sha512" // sha512 with hex encoding
+
+ // Canonical is the primary digest algorithm used with the distribution
+ // project. Other digests may be used but this one is the primary storage
+ // digest.
+ Canonical = SHA256
+)
+
+var (
+ // TODO(stevvooe): Follow the pattern of the standard crypto package for
+ // registration of digests. Effectively, we are a registerable set and
+ // common symbol access.
+
+ // algorithms maps values to hash.Hash implementations. Other algorithms
+ // may be available but they cannot be calculated by the digest package.
+ algorithms = map[Algorithm]crypto.Hash{
+ SHA256: crypto.SHA256,
+ SHA384: crypto.SHA384,
+ SHA512: crypto.SHA512,
+ }
+)
+
+// Available returns true if the digest type is available for use. If this
+// returns false, New and Hash will return nil.
+func (a Algorithm) Available() bool {
+ h, ok := algorithms[a]
+ if !ok {
+ return false
+ }
+
+ // check availability of the hash, as well
+ return h.Available()
+}
+
+func (a Algorithm) String() string {
+ return string(a)
+}
+
+// Size returns number of bytes returned by the hash.
+func (a Algorithm) Size() int {
+ h, ok := algorithms[a]
+ if !ok {
+ return 0
+ }
+ return h.Size()
+}
+
+// Set implemented to allow use of Algorithm as a command line flag.
+func (a *Algorithm) Set(value string) error {
+ if value == "" {
+ *a = Canonical
+ } else {
+ // just do a type conversion, support is queried with Available.
+ *a = Algorithm(value)
+ }
+
+ return nil
+}
+
+// New returns a new digester for the specified algorithm. If the algorithm
+// does not have a digester implementation, nil will be returned. This can be
+// checked by calling Available before calling New.
+func (a Algorithm) New() Digester {
+ return &digester{
+ alg: a,
+ hash: a.Hash(),
+ }
+}
+
+// Hash returns a new hash as used by the algorithm. If not available, the
+// method will panic. Check Algorithm.Available() before calling.
+func (a Algorithm) Hash() hash.Hash {
+ if !a.Available() {
+ // NOTE(stevvooe): A missing hash is usually a programming error that
+ // must be resolved at compile time. We don't import in the digest
+ // package to allow users to choose their hash implementation (such as
+ // when using stevvooe/resumable or a hardware accelerated package).
+ //
+ // Applications that may want to resolve the hash at runtime should
+ // call Algorithm.Available before call Algorithm.Hash().
+ panic(fmt.Sprintf("%v not available (make sure it is imported)", a))
+ }
+
+ return algorithms[a].New()
+}
+
+// FromReader returns the digest of the reader using the algorithm.
+func (a Algorithm) FromReader(rd io.Reader) (Digest, error) {
+ digester := a.New()
+
+ if _, err := io.Copy(digester.Hash(), rd); err != nil {
+ return "", err
+ }
+
+ return digester.Digest(), nil
+}
+
+// FromBytes digests the input and returns a Digest.
+func (a Algorithm) FromBytes(p []byte) Digest {
+ digester := a.New()
+
+ if _, err := digester.Hash().Write(p); err != nil {
+ // Writes to a Hash should never fail. None of the existing
+ // hash implementations in the stdlib or hashes vendored
+ // here can return errors from Write. Having a panic in this
+ // condition instead of having FromBytes return an error value
+ // avoids unnecessary error handling paths in all callers.
+ panic("write to hash function returned error: " + err.Error())
+ }
+
+ return digester.Digest()
+}
+
+// TODO(stevvooe): Allow resolution of verifiers using the digest type and
+// this registration system.
+
+// Digester calculates the digest of written data. Writes should go directly
+// to the return value of Hash, while calling Digest will return the current
+// value of the digest.
+type Digester interface {
+ Hash() hash.Hash // provides direct access to underlying hash instance.
+ Digest() Digest
+}
+
+// digester provides a simple digester definition that embeds a hasher.
+type digester struct {
+ alg Algorithm
+ hash hash.Hash
+}
+
+func (d *digester) Hash() hash.Hash {
+ return d.hash
+}
+
+func (d *digester) Digest() Digest {
+ return NewDigest(d.alg, d.hash)
+}
diff --git a/vendor/github.com/docker/distribution/digest/doc.go b/vendor/github.com/docker/distribution/digest/doc.go
new file mode 100644
index 00000000..f64b0db3
--- /dev/null
+++ b/vendor/github.com/docker/distribution/digest/doc.go
@@ -0,0 +1,42 @@
+// Package digest provides a generalized type to opaquely represent message
+// digests and their operations within the registry. The Digest type is
+// designed to serve as a flexible identifier in a content-addressable system.
+// More importantly, it provides tools and wrappers to work with
+// hash.Hash-based digests with little effort.
+//
+// Basics
+//
+// The format of a digest is simply a string with two parts, dubbed the
+// "algorithm" and the "digest", separated by a colon:
+//
+// :
+//
+// An example of a sha256 digest representation follows:
+//
+// sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc
+//
+// In this case, the string "sha256" is the algorithm and the hex bytes are
+// the "digest".
+//
+// Because the Digest type is simply a string, once a valid Digest is
+// obtained, comparisons are cheap, quick and simple to express with the
+// standard equality operator.
+//
+// Verification
+//
+// The main benefit of using the Digest type is simple verification against a
+// given digest. The Verifier interface, modeled after the stdlib hash.Hash
+// interface, provides a common write sink for digest verification. After
+// writing is complete, calling the Verifier.Verified method will indicate
+// whether or not the stream of bytes matches the target digest.
+//
+// Missing Features
+//
+// In addition to the above, we intend to add the following features to this
+// package:
+//
+// 1. A Digester type that supports write sink digest calculation.
+//
+// 2. Suspend and resume of ongoing digest calculations to support efficient digest verification in the registry.
+//
+package digest
diff --git a/vendor/github.com/docker/distribution/digest/set.go b/vendor/github.com/docker/distribution/digest/set.go
new file mode 100644
index 00000000..4b9313c1
--- /dev/null
+++ b/vendor/github.com/docker/distribution/digest/set.go
@@ -0,0 +1,245 @@
+package digest
+
+import (
+ "errors"
+ "sort"
+ "strings"
+ "sync"
+)
+
+var (
+ // ErrDigestNotFound is used when a matching digest
+ // could not be found in a set.
+ ErrDigestNotFound = errors.New("digest not found")
+
+ // ErrDigestAmbiguous is used when multiple digests
+ // are found in a set. None of the matching digests
+ // should be considered valid matches.
+ ErrDigestAmbiguous = errors.New("ambiguous digest string")
+)
+
+// Set is used to hold a unique set of digests which
+// may be easily referenced by easily referenced by a string
+// representation of the digest as well as short representation.
+// The uniqueness of the short representation is based on other
+// digests in the set. If digests are omitted from this set,
+// collisions in a larger set may not be detected, therefore it
+// is important to always do short representation lookups on
+// the complete set of digests. To mitigate collisions, an
+// appropriately long short code should be used.
+type Set struct {
+ mutex sync.RWMutex
+ entries digestEntries
+}
+
+// NewSet creates an empty set of digests
+// which may have digests added.
+func NewSet() *Set {
+ return &Set{
+ entries: digestEntries{},
+ }
+}
+
+// checkShortMatch checks whether two digests match as either whole
+// values or short values. This function does not test equality,
+// rather whether the second value could match against the first
+// value.
+func checkShortMatch(alg Algorithm, hex, shortAlg, shortHex string) bool {
+ if len(hex) == len(shortHex) {
+ if hex != shortHex {
+ return false
+ }
+ if len(shortAlg) > 0 && string(alg) != shortAlg {
+ return false
+ }
+ } else if !strings.HasPrefix(hex, shortHex) {
+ return false
+ } else if len(shortAlg) > 0 && string(alg) != shortAlg {
+ return false
+ }
+ return true
+}
+
+// Lookup looks for a digest matching the given string representation.
+// If no digests could be found ErrDigestNotFound will be returned
+// with an empty digest value. If multiple matches are found
+// ErrDigestAmbiguous will be returned with an empty digest value.
+func (dst *Set) Lookup(d string) (Digest, error) {
+ dst.mutex.RLock()
+ defer dst.mutex.RUnlock()
+ if len(dst.entries) == 0 {
+ return "", ErrDigestNotFound
+ }
+ var (
+ searchFunc func(int) bool
+ alg Algorithm
+ hex string
+ )
+ dgst, err := ParseDigest(d)
+ if err == ErrDigestInvalidFormat {
+ hex = d
+ searchFunc = func(i int) bool {
+ return dst.entries[i].val >= d
+ }
+ } else {
+ hex = dgst.Hex()
+ alg = dgst.Algorithm()
+ searchFunc = func(i int) bool {
+ if dst.entries[i].val == hex {
+ return dst.entries[i].alg >= alg
+ }
+ return dst.entries[i].val >= hex
+ }
+ }
+ idx := sort.Search(len(dst.entries), searchFunc)
+ if idx == len(dst.entries) || !checkShortMatch(dst.entries[idx].alg, dst.entries[idx].val, string(alg), hex) {
+ return "", ErrDigestNotFound
+ }
+ if dst.entries[idx].alg == alg && dst.entries[idx].val == hex {
+ return dst.entries[idx].digest, nil
+ }
+ if idx+1 < len(dst.entries) && checkShortMatch(dst.entries[idx+1].alg, dst.entries[idx+1].val, string(alg), hex) {
+ return "", ErrDigestAmbiguous
+ }
+
+ return dst.entries[idx].digest, nil
+}
+
+// Add adds the given digest to the set. An error will be returned
+// if the given digest is invalid. If the digest already exists in the
+// set, this operation will be a no-op.
+func (dst *Set) Add(d Digest) error {
+ if err := d.Validate(); err != nil {
+ return err
+ }
+ dst.mutex.Lock()
+ defer dst.mutex.Unlock()
+ entry := &digestEntry{alg: d.Algorithm(), val: d.Hex(), digest: d}
+ searchFunc := func(i int) bool {
+ if dst.entries[i].val == entry.val {
+ return dst.entries[i].alg >= entry.alg
+ }
+ return dst.entries[i].val >= entry.val
+ }
+ idx := sort.Search(len(dst.entries), searchFunc)
+ if idx == len(dst.entries) {
+ dst.entries = append(dst.entries, entry)
+ return nil
+ } else if dst.entries[idx].digest == d {
+ return nil
+ }
+
+ entries := append(dst.entries, nil)
+ copy(entries[idx+1:], entries[idx:len(entries)-1])
+ entries[idx] = entry
+ dst.entries = entries
+ return nil
+}
+
+// Remove removes the given digest from the set. An err will be
+// returned if the given digest is invalid. If the digest does
+// not exist in the set, this operation will be a no-op.
+func (dst *Set) Remove(d Digest) error {
+ if err := d.Validate(); err != nil {
+ return err
+ }
+ dst.mutex.Lock()
+ defer dst.mutex.Unlock()
+ entry := &digestEntry{alg: d.Algorithm(), val: d.Hex(), digest: d}
+ searchFunc := func(i int) bool {
+ if dst.entries[i].val == entry.val {
+ return dst.entries[i].alg >= entry.alg
+ }
+ return dst.entries[i].val >= entry.val
+ }
+ idx := sort.Search(len(dst.entries), searchFunc)
+ // Not found if idx is after or value at idx is not digest
+ if idx == len(dst.entries) || dst.entries[idx].digest != d {
+ return nil
+ }
+
+ entries := dst.entries
+ copy(entries[idx:], entries[idx+1:])
+ entries = entries[:len(entries)-1]
+ dst.entries = entries
+
+ return nil
+}
+
+// All returns all the digests in the set
+func (dst *Set) All() []Digest {
+ dst.mutex.RLock()
+ defer dst.mutex.RUnlock()
+ retValues := make([]Digest, len(dst.entries))
+ for i := range dst.entries {
+ retValues[i] = dst.entries[i].digest
+ }
+
+ return retValues
+}
+
+// ShortCodeTable returns a map of Digest to unique short codes. The
+// length represents the minimum value, the maximum length may be the
+// entire value of digest if uniqueness cannot be achieved without the
+// full value. This function will attempt to make short codes as short
+// as possible to be unique.
+func ShortCodeTable(dst *Set, length int) map[Digest]string {
+ dst.mutex.RLock()
+ defer dst.mutex.RUnlock()
+ m := make(map[Digest]string, len(dst.entries))
+ l := length
+ resetIdx := 0
+ for i := 0; i < len(dst.entries); i++ {
+ var short string
+ extended := true
+ for extended {
+ extended = false
+ if len(dst.entries[i].val) <= l {
+ short = dst.entries[i].digest.String()
+ } else {
+ short = dst.entries[i].val[:l]
+ for j := i + 1; j < len(dst.entries); j++ {
+ if checkShortMatch(dst.entries[j].alg, dst.entries[j].val, "", short) {
+ if j > resetIdx {
+ resetIdx = j
+ }
+ extended = true
+ } else {
+ break
+ }
+ }
+ if extended {
+ l++
+ }
+ }
+ }
+ m[dst.entries[i].digest] = short
+ if i >= resetIdx {
+ l = length
+ }
+ }
+ return m
+}
+
+type digestEntry struct {
+ alg Algorithm
+ val string
+ digest Digest
+}
+
+type digestEntries []*digestEntry
+
+func (d digestEntries) Len() int {
+ return len(d)
+}
+
+func (d digestEntries) Less(i, j int) bool {
+ if d[i].val != d[j].val {
+ return d[i].val < d[j].val
+ }
+ return d[i].alg < d[j].alg
+}
+
+func (d digestEntries) Swap(i, j int) {
+ d[i], d[j] = d[j], d[i]
+}
diff --git a/vendor/github.com/docker/distribution/digest/verifiers.go b/vendor/github.com/docker/distribution/digest/verifiers.go
new file mode 100644
index 00000000..9af3be13
--- /dev/null
+++ b/vendor/github.com/docker/distribution/digest/verifiers.go
@@ -0,0 +1,44 @@
+package digest
+
+import (
+ "hash"
+ "io"
+)
+
+// Verifier presents a general verification interface to be used with message
+// digests and other byte stream verifications. Users instantiate a Verifier
+// from one of the various methods, write the data under test to it then check
+// the result with the Verified method.
+type Verifier interface {
+ io.Writer
+
+ // Verified will return true if the content written to Verifier matches
+ // the digest.
+ Verified() bool
+}
+
+// NewDigestVerifier returns a verifier that compares the written bytes
+// against a passed in digest.
+func NewDigestVerifier(d Digest) (Verifier, error) {
+ if err := d.Validate(); err != nil {
+ return nil, err
+ }
+
+ return hashVerifier{
+ hash: d.Algorithm().Hash(),
+ digest: d,
+ }, nil
+}
+
+type hashVerifier struct {
+ digest Digest
+ hash hash.Hash
+}
+
+func (hv hashVerifier) Write(p []byte) (n int, err error) {
+ return hv.hash.Write(p)
+}
+
+func (hv hashVerifier) Verified() bool {
+ return hv.digest == NewDigest(hv.digest.Algorithm(), hv.hash)
+}
diff --git a/vendor/github.com/docker/distribution/reference/reference.go b/vendor/github.com/docker/distribution/reference/reference.go
new file mode 100644
index 00000000..02786628
--- /dev/null
+++ b/vendor/github.com/docker/distribution/reference/reference.go
@@ -0,0 +1,370 @@
+// Package reference provides a general type to represent any way of referencing images within the registry.
+// Its main purpose is to abstract tags and digests (content-addressable hash).
+//
+// Grammar
+//
+// reference := name [ ":" tag ] [ "@" digest ]
+// name := [hostname '/'] component ['/' component]*
+// hostname := hostcomponent ['.' hostcomponent]* [':' port-number]
+// hostcomponent := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
+// port-number := /[0-9]+/
+// component := alpha-numeric [separator alpha-numeric]*
+// alpha-numeric := /[a-z0-9]+/
+// separator := /[_.]|__|[-]*/
+//
+// tag := /[\w][\w.-]{0,127}/
+//
+// digest := digest-algorithm ":" digest-hex
+// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]
+// digest-algorithm-separator := /[+.-_]/
+// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/
+// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
+package reference
+
+import (
+ "errors"
+ "fmt"
+ "path"
+ "strings"
+
+ "github.com/docker/distribution/digest"
+)
+
+const (
+ // NameTotalLengthMax is the maximum total number of characters in a repository name.
+ NameTotalLengthMax = 255
+)
+
+var (
+ // ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference.
+ ErrReferenceInvalidFormat = errors.New("invalid reference format")
+
+ // ErrTagInvalidFormat represents an error while trying to parse a string as a tag.
+ ErrTagInvalidFormat = errors.New("invalid tag format")
+
+ // ErrDigestInvalidFormat represents an error while trying to parse a string as a tag.
+ ErrDigestInvalidFormat = errors.New("invalid digest format")
+
+ // ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters.
+ ErrNameContainsUppercase = errors.New("repository name must be lowercase")
+
+ // ErrNameEmpty is returned for empty, invalid repository names.
+ ErrNameEmpty = errors.New("repository name must have at least one component")
+
+ // ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
+ ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
+)
+
+// Reference is an opaque object reference identifier that may include
+// modifiers such as a hostname, name, tag, and digest.
+type Reference interface {
+ // String returns the full reference
+ String() string
+}
+
+// Field provides a wrapper type for resolving correct reference types when
+// working with encoding.
+type Field struct {
+ reference Reference
+}
+
+// AsField wraps a reference in a Field for encoding.
+func AsField(reference Reference) Field {
+ return Field{reference}
+}
+
+// Reference unwraps the reference type from the field to
+// return the Reference object. This object should be
+// of the appropriate type to further check for different
+// reference types.
+func (f Field) Reference() Reference {
+ return f.reference
+}
+
+// MarshalText serializes the field to byte text which
+// is the string of the reference.
+func (f Field) MarshalText() (p []byte, err error) {
+ return []byte(f.reference.String()), nil
+}
+
+// UnmarshalText parses text bytes by invoking the
+// reference parser to ensure the appropriately
+// typed reference object is wrapped by field.
+func (f *Field) UnmarshalText(p []byte) error {
+ r, err := Parse(string(p))
+ if err != nil {
+ return err
+ }
+
+ f.reference = r
+ return nil
+}
+
+// Named is an object with a full name
+type Named interface {
+ Reference
+ Name() string
+}
+
+// Tagged is an object which has a tag
+type Tagged interface {
+ Reference
+ Tag() string
+}
+
+// NamedTagged is an object including a name and tag.
+type NamedTagged interface {
+ Named
+ Tag() string
+}
+
+// Digested is an object which has a digest
+// in which it can be referenced by
+type Digested interface {
+ Reference
+ Digest() digest.Digest
+}
+
+// Canonical reference is an object with a fully unique
+// name including a name with hostname and digest
+type Canonical interface {
+ Named
+ Digest() digest.Digest
+}
+
+// SplitHostname splits a named reference into a
+// hostname and name string. If no valid hostname is
+// found, the hostname is empty and the full value
+// is returned as name
+func SplitHostname(named Named) (string, string) {
+ name := named.Name()
+ match := anchoredNameRegexp.FindStringSubmatch(name)
+ if len(match) != 3 {
+ return "", name
+ }
+ return match[1], match[2]
+}
+
+// Parse parses s and returns a syntactically valid Reference.
+// If an error was encountered it is returned, along with a nil Reference.
+// NOTE: Parse will not handle short digests.
+func Parse(s string) (Reference, error) {
+ matches := ReferenceRegexp.FindStringSubmatch(s)
+ if matches == nil {
+ if s == "" {
+ return nil, ErrNameEmpty
+ }
+ if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil {
+ return nil, ErrNameContainsUppercase
+ }
+ return nil, ErrReferenceInvalidFormat
+ }
+
+ if len(matches[1]) > NameTotalLengthMax {
+ return nil, ErrNameTooLong
+ }
+
+ ref := reference{
+ name: matches[1],
+ tag: matches[2],
+ }
+ if matches[3] != "" {
+ var err error
+ ref.digest, err = digest.ParseDigest(matches[3])
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ r := getBestReferenceType(ref)
+ if r == nil {
+ return nil, ErrNameEmpty
+ }
+
+ return r, nil
+}
+
+// ParseNamed parses s and returns a syntactically valid reference implementing
+// the Named interface. The reference must have a name, otherwise an error is
+// returned.
+// If an error was encountered it is returned, along with a nil Reference.
+// NOTE: ParseNamed will not handle short digests.
+func ParseNamed(s string) (Named, error) {
+ ref, err := Parse(s)
+ if err != nil {
+ return nil, err
+ }
+ named, isNamed := ref.(Named)
+ if !isNamed {
+ return nil, fmt.Errorf("reference %s has no name", ref.String())
+ }
+ return named, nil
+}
+
+// WithName returns a named object representing the given string. If the input
+// is invalid ErrReferenceInvalidFormat will be returned.
+func WithName(name string) (Named, error) {
+ if len(name) > NameTotalLengthMax {
+ return nil, ErrNameTooLong
+ }
+ if !anchoredNameRegexp.MatchString(name) {
+ return nil, ErrReferenceInvalidFormat
+ }
+ return repository(name), nil
+}
+
+// WithTag combines the name from "name" and the tag from "tag" to form a
+// reference incorporating both the name and the tag.
+func WithTag(name Named, tag string) (NamedTagged, error) {
+ if !anchoredTagRegexp.MatchString(tag) {
+ return nil, ErrTagInvalidFormat
+ }
+ if canonical, ok := name.(Canonical); ok {
+ return reference{
+ name: name.Name(),
+ tag: tag,
+ digest: canonical.Digest(),
+ }, nil
+ }
+ return taggedReference{
+ name: name.Name(),
+ tag: tag,
+ }, nil
+}
+
+// WithDigest combines the name from "name" and the digest from "digest" to form
+// a reference incorporating both the name and the digest.
+func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
+ if !anchoredDigestRegexp.MatchString(digest.String()) {
+ return nil, ErrDigestInvalidFormat
+ }
+ if tagged, ok := name.(Tagged); ok {
+ return reference{
+ name: name.Name(),
+ tag: tagged.Tag(),
+ digest: digest,
+ }, nil
+ }
+ return canonicalReference{
+ name: name.Name(),
+ digest: digest,
+ }, nil
+}
+
+// Match reports whether ref matches the specified pattern.
+// See https://godoc.org/path#Match for supported patterns.
+func Match(pattern string, ref Reference) (bool, error) {
+ matched, err := path.Match(pattern, ref.String())
+ if namedRef, isNamed := ref.(Named); isNamed && !matched {
+ matched, _ = path.Match(pattern, namedRef.Name())
+ }
+ return matched, err
+}
+
+// TrimNamed removes any tag or digest from the named reference.
+func TrimNamed(ref Named) Named {
+ return repository(ref.Name())
+}
+
+func getBestReferenceType(ref reference) Reference {
+ if ref.name == "" {
+ // Allow digest only references
+ if ref.digest != "" {
+ return digestReference(ref.digest)
+ }
+ return nil
+ }
+ if ref.tag == "" {
+ if ref.digest != "" {
+ return canonicalReference{
+ name: ref.name,
+ digest: ref.digest,
+ }
+ }
+ return repository(ref.name)
+ }
+ if ref.digest == "" {
+ return taggedReference{
+ name: ref.name,
+ tag: ref.tag,
+ }
+ }
+
+ return ref
+}
+
+type reference struct {
+ name string
+ tag string
+ digest digest.Digest
+}
+
+func (r reference) String() string {
+ return r.name + ":" + r.tag + "@" + r.digest.String()
+}
+
+func (r reference) Name() string {
+ return r.name
+}
+
+func (r reference) Tag() string {
+ return r.tag
+}
+
+func (r reference) Digest() digest.Digest {
+ return r.digest
+}
+
+type repository string
+
+func (r repository) String() string {
+ return string(r)
+}
+
+func (r repository) Name() string {
+ return string(r)
+}
+
+type digestReference digest.Digest
+
+func (d digestReference) String() string {
+ return d.String()
+}
+
+func (d digestReference) Digest() digest.Digest {
+ return digest.Digest(d)
+}
+
+type taggedReference struct {
+ name string
+ tag string
+}
+
+func (t taggedReference) String() string {
+ return t.name + ":" + t.tag
+}
+
+func (t taggedReference) Name() string {
+ return t.name
+}
+
+func (t taggedReference) Tag() string {
+ return t.tag
+}
+
+type canonicalReference struct {
+ name string
+ digest digest.Digest
+}
+
+func (c canonicalReference) String() string {
+ return c.name + "@" + c.digest.String()
+}
+
+func (c canonicalReference) Name() string {
+ return c.name
+}
+
+func (c canonicalReference) Digest() digest.Digest {
+ return c.digest
+}
diff --git a/vendor/github.com/docker/distribution/reference/regexp.go b/vendor/github.com/docker/distribution/reference/regexp.go
new file mode 100644
index 00000000..9a7d366b
--- /dev/null
+++ b/vendor/github.com/docker/distribution/reference/regexp.go
@@ -0,0 +1,124 @@
+package reference
+
+import "regexp"
+
+var (
+ // alphaNumericRegexp defines the alpha numeric atom, typically a
+ // component of names. This only allows lower case characters and digits.
+ alphaNumericRegexp = match(`[a-z0-9]+`)
+
+ // separatorRegexp defines the separators allowed to be embedded in name
+ // components. This allow one period, one or two underscore and multiple
+ // dashes.
+ separatorRegexp = match(`(?:[._]|__|[-]*)`)
+
+ // nameComponentRegexp restricts registry path component names to start
+ // with at least one letter or number, with following parts able to be
+ // separated by one period, one or two underscore and multiple dashes.
+ nameComponentRegexp = expression(
+ alphaNumericRegexp,
+ optional(repeated(separatorRegexp, alphaNumericRegexp)))
+
+ // hostnameComponentRegexp restricts the registry hostname component of a
+ // repository name to start with a component as defined by hostnameRegexp
+ // and followed by an optional port.
+ hostnameComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
+
+ // hostnameRegexp defines the structure of potential hostname components
+ // that may be part of image names. This is purposely a subset of what is
+ // allowed by DNS to ensure backwards compatibility with Docker image
+ // names.
+ hostnameRegexp = expression(
+ hostnameComponentRegexp,
+ optional(repeated(literal(`.`), hostnameComponentRegexp)),
+ optional(literal(`:`), match(`[0-9]+`)))
+
+ // TagRegexp matches valid tag names. From docker/docker:graph/tags.go.
+ TagRegexp = match(`[\w][\w.-]{0,127}`)
+
+ // anchoredTagRegexp matches valid tag names, anchored at the start and
+ // end of the matched string.
+ anchoredTagRegexp = anchored(TagRegexp)
+
+ // DigestRegexp matches valid digests.
+ DigestRegexp = match(`[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}`)
+
+ // anchoredDigestRegexp matches valid digests, anchored at the start and
+ // end of the matched string.
+ anchoredDigestRegexp = anchored(DigestRegexp)
+
+ // NameRegexp is the format for the name component of references. The
+ // regexp has capturing groups for the hostname and name part omitting
+ // the separating forward slash from either.
+ NameRegexp = expression(
+ optional(hostnameRegexp, literal(`/`)),
+ nameComponentRegexp,
+ optional(repeated(literal(`/`), nameComponentRegexp)))
+
+ // anchoredNameRegexp is used to parse a name value, capturing the
+ // hostname and trailing components.
+ anchoredNameRegexp = anchored(
+ optional(capture(hostnameRegexp), literal(`/`)),
+ capture(nameComponentRegexp,
+ optional(repeated(literal(`/`), nameComponentRegexp))))
+
+ // ReferenceRegexp is the full supported format of a reference. The regexp
+ // is anchored and has capturing groups for name, tag, and digest
+ // components.
+ ReferenceRegexp = anchored(capture(NameRegexp),
+ optional(literal(":"), capture(TagRegexp)),
+ optional(literal("@"), capture(DigestRegexp)))
+)
+
+// match compiles the string to a regular expression.
+var match = regexp.MustCompile
+
+// literal compiles s into a literal regular expression, escaping any regexp
+// reserved characters.
+func literal(s string) *regexp.Regexp {
+ re := match(regexp.QuoteMeta(s))
+
+ if _, complete := re.LiteralPrefix(); !complete {
+ panic("must be a literal")
+ }
+
+ return re
+}
+
+// expression defines a full expression, where each regular expression must
+// follow the previous.
+func expression(res ...*regexp.Regexp) *regexp.Regexp {
+ var s string
+ for _, re := range res {
+ s += re.String()
+ }
+
+ return match(s)
+}
+
+// optional wraps the expression in a non-capturing group and makes the
+// production optional.
+func optional(res ...*regexp.Regexp) *regexp.Regexp {
+ return match(group(expression(res...)).String() + `?`)
+}
+
+// repeated wraps the regexp in a non-capturing group to get one or more
+// matches.
+func repeated(res ...*regexp.Regexp) *regexp.Regexp {
+ return match(group(expression(res...)).String() + `+`)
+}
+
+// group wraps the regexp in a non-capturing group.
+func group(res ...*regexp.Regexp) *regexp.Regexp {
+ return match(`(?:` + expression(res...).String() + `)`)
+}
+
+// capture wraps the expression in a capturing group.
+func capture(res ...*regexp.Regexp) *regexp.Regexp {
+ return match(`(` + expression(res...).String() + `)`)
+}
+
+// anchored anchors the regular expression by adding start and end delimiters.
+func anchored(res ...*regexp.Regexp) *regexp.Regexp {
+ return match(`^` + expression(res...).String() + `$`)
+}
diff --git a/vendor/github.com/gogo/protobuf/gogoproto/doc.go b/vendor/github.com/gogo/protobuf/gogoproto/doc.go
new file mode 100644
index 00000000..147b5ecc
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/gogoproto/doc.go
@@ -0,0 +1,169 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package gogoproto provides extensions for protocol buffers to achieve:
+
+ - fast marshalling and unmarshalling.
+ - peace of mind by optionally generating test and benchmark code.
+ - more canonical Go structures.
+ - less typing by optionally generating extra helper code.
+ - goprotobuf compatibility
+
+More Canonical Go Structures
+
+A lot of time working with a goprotobuf struct will lead you to a place where you create another struct that is easier to work with and then have a function to copy the values between the two structs.
+You might also find that basic structs that started their life as part of an API need to be sent over the wire. With gob, you could just send it. With goprotobuf, you need to make a parallel struct.
+Gogoprotobuf tries to fix these problems with the nullable, embed, customtype and customname field extensions.
+
+ - nullable, if false, a field is generated without a pointer (see warning below).
+ - embed, if true, the field is generated as an embedded field.
+ - customtype, It works with the Marshal and Unmarshal methods, to allow you to have your own types in your struct, but marshal to bytes. For example, custom.Uuid or custom.Fixed128
+ - customname (beta), Changes the generated fieldname. This is especially useful when generated methods conflict with fieldnames.
+ - casttype (beta), Changes the generated fieldtype. All generated code assumes that this type is castable to the protocol buffer field type. It does not work for structs or enums.
+ - castkey (beta), Changes the generated fieldtype for a map key. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps.
+ - castvalue (beta), Changes the generated fieldtype for a map value. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps.
+
+Warning about nullable: According to the Protocol Buffer specification, you should be able to tell whether a field is set or unset. With the option nullable=false this feature is lost, since your non-nullable fields will always be set. It can be seen as a layer on top of Protocol Buffers, where before and after marshalling all non-nullable fields are set and they cannot be unset.
+
+Let us look at:
+
+ github.com/gogo/protobuf/test/example/example.proto
+
+for a quicker overview.
+
+The following message:
+
+ package test;
+
+ import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+
+ message A {
+ optional string Description = 1 [(gogoproto.nullable) = false];
+ optional int64 Number = 2 [(gogoproto.nullable) = false];
+ optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
+ }
+
+Will generate a go struct which looks a lot like this:
+
+ type A struct {
+ Description string
+ Number int64
+ Id github_com_gogo_protobuf_test_custom.Uuid
+ }
+
+You will see there are no pointers, since all fields are non-nullable.
+You will also see a custom type which marshals to a string.
+Be warned it is your responsibility to test your custom types thoroughly.
+You should think of every possible empty and nil case for your marshaling, unmarshaling and size methods.
+
+Next we will embed the message A in message B.
+
+ message B {
+ optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
+ repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
+ }
+
+See below that A is embedded in B.
+
+ type B struct {
+ A
+ G []github_com_gogo_protobuf_test_custom.Uint128
+ }
+
+Also see the repeated custom type.
+
+ type Uint128 [2]uint64
+
+Next we will create a custom name for one of our fields.
+
+ message C {
+ optional int64 size = 1 [(gogoproto.customname) = "MySize"];
+ }
+
+See below that the field's name is MySize and not Size.
+
+ type C struct {
+ MySize *int64
+ }
+
+The is useful when having a protocol buffer message with a field name which conflicts with a generated method.
+As an example, having a field name size and using the sizer plugin to generate a Size method will cause a go compiler error.
+Using customname you can fix this error without changing the field name.
+This is typically useful when working with a protocol buffer that was designed before these methods and/or the go language were avialable.
+
+Gogoprotobuf also has some more subtle changes, these could be changed back:
+
+ - the generated package name for imports do not have the extra /filename.pb,
+ but are actually the imports specified in the .proto file.
+
+Gogoprotobuf also has lost some features which should be brought back with time:
+
+ - Marshalling and unmarshalling with reflect and without the unsafe package,
+ this requires work in pointer_reflect.go
+
+Why does nullable break protocol buffer specifications:
+
+The protocol buffer specification states, somewhere, that you should be able to tell whether a
+field is set or unset. With the option nullable=false this feature is lost,
+since your non-nullable fields will always be set. It can be seen as a layer on top of
+protocol buffers, where before and after marshalling all non-nullable fields are set
+and they cannot be unset.
+
+Goprotobuf Compatibility:
+
+Gogoprotobuf is compatible with Goprotobuf, because it is compatible with protocol buffers.
+Gogoprotobuf generates the same code as goprotobuf if no extensions are used.
+The enumprefix, getters and stringer extensions can be used to remove some of the unnecessary code generated by goprotobuf:
+
+ - gogoproto_import, if false, the generated code imports github.com/golang/protobuf/proto instead of github.com/gogo/protobuf/proto.
+ - goproto_enum_prefix, if false, generates the enum constant names without the messagetype prefix
+ - goproto_enum_stringer (experimental), if false, the enum is generated without the default string method, this is useful for rather using enum_stringer, or allowing you to write your own string method.
+ - goproto_getters, if false, the message is generated without get methods, this is useful when you would rather want to use face
+ - goproto_stringer, if false, the message is generated without the default string method, this is useful for rather using stringer, or allowing you to write your own string method.
+ - goproto_extensions_map (beta), if false, the extensions field is generated as type []byte instead of type map[int32]proto.Extension
+ - goproto_unrecognized (beta), if false, XXX_unrecognized field is not generated. This is useful in conjunction with gogoproto.nullable=false, to generate structures completely devoid of pointers and reduce GC pressure at the cost of losing information about unrecognized fields.
+ - goproto_registration (beta), if true, the generated files will register all messages and types against both gogo/protobuf and golang/protobuf. This is necessary when using third-party packages which read registrations from golang/protobuf (such as the grpc-gateway).
+
+Less Typing and Peace of Mind is explained in their specific plugin folders godoc:
+
+ - github.com/gogo/protobuf/plugin/
+
+If you do not use any of these extension the code that is generated
+will be the same as if goprotobuf has generated it.
+
+The most complete way to see examples is to look at
+
+ github.com/gogo/protobuf/test/thetest.proto
+
+Gogoprototest is a seperate project,
+because we want to keep gogoprotobuf independant of goprotobuf,
+but we still want to test it thoroughly.
+
+*/
+package gogoproto
diff --git a/vendor/github.com/gogo/protobuf/gogoproto/gogo.pb.go b/vendor/github.com/gogo/protobuf/gogoproto/gogo.pb.go
new file mode 100644
index 00000000..9506b6fb
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/gogoproto/gogo.pb.go
@@ -0,0 +1,804 @@
+// Code generated by protoc-gen-gogo.
+// source: gogo.proto
+// DO NOT EDIT!
+
+/*
+Package gogoproto is a generated protocol buffer package.
+
+It is generated from these files:
+ gogo.proto
+
+It has these top-level messages:
+*/
+package gogoproto
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+var E_GoprotoEnumPrefix = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62001,
+ Name: "gogoproto.goproto_enum_prefix",
+ Tag: "varint,62001,opt,name=goproto_enum_prefix,json=goprotoEnumPrefix",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoEnumStringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62021,
+ Name: "gogoproto.goproto_enum_stringer",
+ Tag: "varint,62021,opt,name=goproto_enum_stringer,json=goprotoEnumStringer",
+ Filename: "gogo.proto",
+}
+
+var E_EnumStringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62022,
+ Name: "gogoproto.enum_stringer",
+ Tag: "varint,62022,opt,name=enum_stringer,json=enumStringer",
+ Filename: "gogo.proto",
+}
+
+var E_EnumCustomname = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 62023,
+ Name: "gogoproto.enum_customname",
+ Tag: "bytes,62023,opt,name=enum_customname,json=enumCustomname",
+ Filename: "gogo.proto",
+}
+
+var E_Enumdecl = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 62024,
+ Name: "gogoproto.enumdecl",
+ Tag: "varint,62024,opt,name=enumdecl",
+ Filename: "gogo.proto",
+}
+
+var E_EnumvalueCustomname = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 66001,
+ Name: "gogoproto.enumvalue_customname",
+ Tag: "bytes,66001,opt,name=enumvalue_customname,json=enumvalueCustomname",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoGettersAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63001,
+ Name: "gogoproto.goproto_getters_all",
+ Tag: "varint,63001,opt,name=goproto_getters_all,json=goprotoGettersAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoEnumPrefixAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63002,
+ Name: "gogoproto.goproto_enum_prefix_all",
+ Tag: "varint,63002,opt,name=goproto_enum_prefix_all,json=goprotoEnumPrefixAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoStringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63003,
+ Name: "gogoproto.goproto_stringer_all",
+ Tag: "varint,63003,opt,name=goproto_stringer_all,json=goprotoStringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_VerboseEqualAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63004,
+ Name: "gogoproto.verbose_equal_all",
+ Tag: "varint,63004,opt,name=verbose_equal_all,json=verboseEqualAll",
+ Filename: "gogo.proto",
+}
+
+var E_FaceAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63005,
+ Name: "gogoproto.face_all",
+ Tag: "varint,63005,opt,name=face_all,json=faceAll",
+ Filename: "gogo.proto",
+}
+
+var E_GostringAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63006,
+ Name: "gogoproto.gostring_all",
+ Tag: "varint,63006,opt,name=gostring_all,json=gostringAll",
+ Filename: "gogo.proto",
+}
+
+var E_PopulateAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63007,
+ Name: "gogoproto.populate_all",
+ Tag: "varint,63007,opt,name=populate_all,json=populateAll",
+ Filename: "gogo.proto",
+}
+
+var E_StringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63008,
+ Name: "gogoproto.stringer_all",
+ Tag: "varint,63008,opt,name=stringer_all,json=stringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_OnlyoneAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63009,
+ Name: "gogoproto.onlyone_all",
+ Tag: "varint,63009,opt,name=onlyone_all,json=onlyoneAll",
+ Filename: "gogo.proto",
+}
+
+var E_EqualAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63013,
+ Name: "gogoproto.equal_all",
+ Tag: "varint,63013,opt,name=equal_all,json=equalAll",
+ Filename: "gogo.proto",
+}
+
+var E_DescriptionAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63014,
+ Name: "gogoproto.description_all",
+ Tag: "varint,63014,opt,name=description_all,json=descriptionAll",
+ Filename: "gogo.proto",
+}
+
+var E_TestgenAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63015,
+ Name: "gogoproto.testgen_all",
+ Tag: "varint,63015,opt,name=testgen_all,json=testgenAll",
+ Filename: "gogo.proto",
+}
+
+var E_BenchgenAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63016,
+ Name: "gogoproto.benchgen_all",
+ Tag: "varint,63016,opt,name=benchgen_all,json=benchgenAll",
+ Filename: "gogo.proto",
+}
+
+var E_MarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63017,
+ Name: "gogoproto.marshaler_all",
+ Tag: "varint,63017,opt,name=marshaler_all,json=marshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_UnmarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63018,
+ Name: "gogoproto.unmarshaler_all",
+ Tag: "varint,63018,opt,name=unmarshaler_all,json=unmarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_StableMarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63019,
+ Name: "gogoproto.stable_marshaler_all",
+ Tag: "varint,63019,opt,name=stable_marshaler_all,json=stableMarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_SizerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63020,
+ Name: "gogoproto.sizer_all",
+ Tag: "varint,63020,opt,name=sizer_all,json=sizerAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoEnumStringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63021,
+ Name: "gogoproto.goproto_enum_stringer_all",
+ Tag: "varint,63021,opt,name=goproto_enum_stringer_all,json=goprotoEnumStringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_EnumStringerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63022,
+ Name: "gogoproto.enum_stringer_all",
+ Tag: "varint,63022,opt,name=enum_stringer_all,json=enumStringerAll",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeMarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63023,
+ Name: "gogoproto.unsafe_marshaler_all",
+ Tag: "varint,63023,opt,name=unsafe_marshaler_all,json=unsafeMarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeUnmarshalerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63024,
+ Name: "gogoproto.unsafe_unmarshaler_all",
+ Tag: "varint,63024,opt,name=unsafe_unmarshaler_all,json=unsafeUnmarshalerAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoExtensionsMapAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63025,
+ Name: "gogoproto.goproto_extensions_map_all",
+ Tag: "varint,63025,opt,name=goproto_extensions_map_all,json=goprotoExtensionsMapAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoUnrecognizedAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63026,
+ Name: "gogoproto.goproto_unrecognized_all",
+ Tag: "varint,63026,opt,name=goproto_unrecognized_all,json=goprotoUnrecognizedAll",
+ Filename: "gogo.proto",
+}
+
+var E_GogoprotoImport = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63027,
+ Name: "gogoproto.gogoproto_import",
+ Tag: "varint,63027,opt,name=gogoproto_import,json=gogoprotoImport",
+ Filename: "gogo.proto",
+}
+
+var E_ProtosizerAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63028,
+ Name: "gogoproto.protosizer_all",
+ Tag: "varint,63028,opt,name=protosizer_all,json=protosizerAll",
+ Filename: "gogo.proto",
+}
+
+var E_CompareAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63029,
+ Name: "gogoproto.compare_all",
+ Tag: "varint,63029,opt,name=compare_all,json=compareAll",
+ Filename: "gogo.proto",
+}
+
+var E_TypedeclAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63030,
+ Name: "gogoproto.typedecl_all",
+ Tag: "varint,63030,opt,name=typedecl_all,json=typedeclAll",
+ Filename: "gogo.proto",
+}
+
+var E_EnumdeclAll = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63031,
+ Name: "gogoproto.enumdecl_all",
+ Tag: "varint,63031,opt,name=enumdecl_all,json=enumdeclAll",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoRegistration = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FileOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 63032,
+ Name: "gogoproto.goproto_registration",
+ Tag: "varint,63032,opt,name=goproto_registration,json=goprotoRegistration",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoGetters = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64001,
+ Name: "gogoproto.goproto_getters",
+ Tag: "varint,64001,opt,name=goproto_getters,json=goprotoGetters",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoStringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64003,
+ Name: "gogoproto.goproto_stringer",
+ Tag: "varint,64003,opt,name=goproto_stringer,json=goprotoStringer",
+ Filename: "gogo.proto",
+}
+
+var E_VerboseEqual = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64004,
+ Name: "gogoproto.verbose_equal",
+ Tag: "varint,64004,opt,name=verbose_equal,json=verboseEqual",
+ Filename: "gogo.proto",
+}
+
+var E_Face = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64005,
+ Name: "gogoproto.face",
+ Tag: "varint,64005,opt,name=face",
+ Filename: "gogo.proto",
+}
+
+var E_Gostring = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64006,
+ Name: "gogoproto.gostring",
+ Tag: "varint,64006,opt,name=gostring",
+ Filename: "gogo.proto",
+}
+
+var E_Populate = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64007,
+ Name: "gogoproto.populate",
+ Tag: "varint,64007,opt,name=populate",
+ Filename: "gogo.proto",
+}
+
+var E_Stringer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 67008,
+ Name: "gogoproto.stringer",
+ Tag: "varint,67008,opt,name=stringer",
+ Filename: "gogo.proto",
+}
+
+var E_Onlyone = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64009,
+ Name: "gogoproto.onlyone",
+ Tag: "varint,64009,opt,name=onlyone",
+ Filename: "gogo.proto",
+}
+
+var E_Equal = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64013,
+ Name: "gogoproto.equal",
+ Tag: "varint,64013,opt,name=equal",
+ Filename: "gogo.proto",
+}
+
+var E_Description = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64014,
+ Name: "gogoproto.description",
+ Tag: "varint,64014,opt,name=description",
+ Filename: "gogo.proto",
+}
+
+var E_Testgen = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64015,
+ Name: "gogoproto.testgen",
+ Tag: "varint,64015,opt,name=testgen",
+ Filename: "gogo.proto",
+}
+
+var E_Benchgen = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64016,
+ Name: "gogoproto.benchgen",
+ Tag: "varint,64016,opt,name=benchgen",
+ Filename: "gogo.proto",
+}
+
+var E_Marshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64017,
+ Name: "gogoproto.marshaler",
+ Tag: "varint,64017,opt,name=marshaler",
+ Filename: "gogo.proto",
+}
+
+var E_Unmarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64018,
+ Name: "gogoproto.unmarshaler",
+ Tag: "varint,64018,opt,name=unmarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_StableMarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64019,
+ Name: "gogoproto.stable_marshaler",
+ Tag: "varint,64019,opt,name=stable_marshaler,json=stableMarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_Sizer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64020,
+ Name: "gogoproto.sizer",
+ Tag: "varint,64020,opt,name=sizer",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeMarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64023,
+ Name: "gogoproto.unsafe_marshaler",
+ Tag: "varint,64023,opt,name=unsafe_marshaler,json=unsafeMarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_UnsafeUnmarshaler = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64024,
+ Name: "gogoproto.unsafe_unmarshaler",
+ Tag: "varint,64024,opt,name=unsafe_unmarshaler,json=unsafeUnmarshaler",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoExtensionsMap = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64025,
+ Name: "gogoproto.goproto_extensions_map",
+ Tag: "varint,64025,opt,name=goproto_extensions_map,json=goprotoExtensionsMap",
+ Filename: "gogo.proto",
+}
+
+var E_GoprotoUnrecognized = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64026,
+ Name: "gogoproto.goproto_unrecognized",
+ Tag: "varint,64026,opt,name=goproto_unrecognized,json=goprotoUnrecognized",
+ Filename: "gogo.proto",
+}
+
+var E_Protosizer = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64028,
+ Name: "gogoproto.protosizer",
+ Tag: "varint,64028,opt,name=protosizer",
+ Filename: "gogo.proto",
+}
+
+var E_Compare = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64029,
+ Name: "gogoproto.compare",
+ Tag: "varint,64029,opt,name=compare",
+ Filename: "gogo.proto",
+}
+
+var E_Typedecl = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.MessageOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 64030,
+ Name: "gogoproto.typedecl",
+ Tag: "varint,64030,opt,name=typedecl",
+ Filename: "gogo.proto",
+}
+
+var E_Nullable = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65001,
+ Name: "gogoproto.nullable",
+ Tag: "varint,65001,opt,name=nullable",
+ Filename: "gogo.proto",
+}
+
+var E_Embed = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65002,
+ Name: "gogoproto.embed",
+ Tag: "varint,65002,opt,name=embed",
+ Filename: "gogo.proto",
+}
+
+var E_Customtype = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65003,
+ Name: "gogoproto.customtype",
+ Tag: "bytes,65003,opt,name=customtype",
+ Filename: "gogo.proto",
+}
+
+var E_Customname = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65004,
+ Name: "gogoproto.customname",
+ Tag: "bytes,65004,opt,name=customname",
+ Filename: "gogo.proto",
+}
+
+var E_Jsontag = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65005,
+ Name: "gogoproto.jsontag",
+ Tag: "bytes,65005,opt,name=jsontag",
+ Filename: "gogo.proto",
+}
+
+var E_Moretags = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65006,
+ Name: "gogoproto.moretags",
+ Tag: "bytes,65006,opt,name=moretags",
+ Filename: "gogo.proto",
+}
+
+var E_Casttype = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65007,
+ Name: "gogoproto.casttype",
+ Tag: "bytes,65007,opt,name=casttype",
+ Filename: "gogo.proto",
+}
+
+var E_Castkey = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65008,
+ Name: "gogoproto.castkey",
+ Tag: "bytes,65008,opt,name=castkey",
+ Filename: "gogo.proto",
+}
+
+var E_Castvalue = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 65009,
+ Name: "gogoproto.castvalue",
+ Tag: "bytes,65009,opt,name=castvalue",
+ Filename: "gogo.proto",
+}
+
+var E_Stdtime = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65010,
+ Name: "gogoproto.stdtime",
+ Tag: "varint,65010,opt,name=stdtime",
+ Filename: "gogo.proto",
+}
+
+var E_Stdduration = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.FieldOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 65011,
+ Name: "gogoproto.stdduration",
+ Tag: "varint,65011,opt,name=stdduration",
+ Filename: "gogo.proto",
+}
+
+func init() {
+ proto.RegisterExtension(E_GoprotoEnumPrefix)
+ proto.RegisterExtension(E_GoprotoEnumStringer)
+ proto.RegisterExtension(E_EnumStringer)
+ proto.RegisterExtension(E_EnumCustomname)
+ proto.RegisterExtension(E_Enumdecl)
+ proto.RegisterExtension(E_EnumvalueCustomname)
+ proto.RegisterExtension(E_GoprotoGettersAll)
+ proto.RegisterExtension(E_GoprotoEnumPrefixAll)
+ proto.RegisterExtension(E_GoprotoStringerAll)
+ proto.RegisterExtension(E_VerboseEqualAll)
+ proto.RegisterExtension(E_FaceAll)
+ proto.RegisterExtension(E_GostringAll)
+ proto.RegisterExtension(E_PopulateAll)
+ proto.RegisterExtension(E_StringerAll)
+ proto.RegisterExtension(E_OnlyoneAll)
+ proto.RegisterExtension(E_EqualAll)
+ proto.RegisterExtension(E_DescriptionAll)
+ proto.RegisterExtension(E_TestgenAll)
+ proto.RegisterExtension(E_BenchgenAll)
+ proto.RegisterExtension(E_MarshalerAll)
+ proto.RegisterExtension(E_UnmarshalerAll)
+ proto.RegisterExtension(E_StableMarshalerAll)
+ proto.RegisterExtension(E_SizerAll)
+ proto.RegisterExtension(E_GoprotoEnumStringerAll)
+ proto.RegisterExtension(E_EnumStringerAll)
+ proto.RegisterExtension(E_UnsafeMarshalerAll)
+ proto.RegisterExtension(E_UnsafeUnmarshalerAll)
+ proto.RegisterExtension(E_GoprotoExtensionsMapAll)
+ proto.RegisterExtension(E_GoprotoUnrecognizedAll)
+ proto.RegisterExtension(E_GogoprotoImport)
+ proto.RegisterExtension(E_ProtosizerAll)
+ proto.RegisterExtension(E_CompareAll)
+ proto.RegisterExtension(E_TypedeclAll)
+ proto.RegisterExtension(E_EnumdeclAll)
+ proto.RegisterExtension(E_GoprotoRegistration)
+ proto.RegisterExtension(E_GoprotoGetters)
+ proto.RegisterExtension(E_GoprotoStringer)
+ proto.RegisterExtension(E_VerboseEqual)
+ proto.RegisterExtension(E_Face)
+ proto.RegisterExtension(E_Gostring)
+ proto.RegisterExtension(E_Populate)
+ proto.RegisterExtension(E_Stringer)
+ proto.RegisterExtension(E_Onlyone)
+ proto.RegisterExtension(E_Equal)
+ proto.RegisterExtension(E_Description)
+ proto.RegisterExtension(E_Testgen)
+ proto.RegisterExtension(E_Benchgen)
+ proto.RegisterExtension(E_Marshaler)
+ proto.RegisterExtension(E_Unmarshaler)
+ proto.RegisterExtension(E_StableMarshaler)
+ proto.RegisterExtension(E_Sizer)
+ proto.RegisterExtension(E_UnsafeMarshaler)
+ proto.RegisterExtension(E_UnsafeUnmarshaler)
+ proto.RegisterExtension(E_GoprotoExtensionsMap)
+ proto.RegisterExtension(E_GoprotoUnrecognized)
+ proto.RegisterExtension(E_Protosizer)
+ proto.RegisterExtension(E_Compare)
+ proto.RegisterExtension(E_Typedecl)
+ proto.RegisterExtension(E_Nullable)
+ proto.RegisterExtension(E_Embed)
+ proto.RegisterExtension(E_Customtype)
+ proto.RegisterExtension(E_Customname)
+ proto.RegisterExtension(E_Jsontag)
+ proto.RegisterExtension(E_Moretags)
+ proto.RegisterExtension(E_Casttype)
+ proto.RegisterExtension(E_Castkey)
+ proto.RegisterExtension(E_Castvalue)
+ proto.RegisterExtension(E_Stdtime)
+ proto.RegisterExtension(E_Stdduration)
+}
+
+func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) }
+
+var fileDescriptorGogo = []byte{
+ // 1201 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0xcb, 0x6f, 0x1c, 0x45,
+ 0x13, 0xc0, 0xf5, 0xe9, 0x73, 0x64, 0x6f, 0xf9, 0x85, 0xd7, 0xc6, 0x84, 0x08, 0x44, 0x72, 0xe3,
+ 0xe4, 0x9c, 0x22, 0x94, 0xb6, 0x22, 0xcb, 0xb1, 0x1c, 0x2b, 0x11, 0x06, 0x63, 0xe2, 0x00, 0xe2,
+ 0xb0, 0x9a, 0xdd, 0x6d, 0x4f, 0x06, 0x66, 0xa6, 0x87, 0x99, 0x9e, 0x28, 0xce, 0x0d, 0x85, 0x87,
+ 0x10, 0xe2, 0x8d, 0x04, 0x09, 0x49, 0x80, 0x03, 0xef, 0x67, 0x78, 0x1f, 0xb9, 0xf0, 0xb8, 0xf2,
+ 0x3f, 0x70, 0x01, 0xcc, 0xdb, 0x37, 0x5f, 0x50, 0xcd, 0x56, 0xcd, 0xf6, 0xac, 0x57, 0xea, 0xde,
+ 0xdb, 0xec, 0xba, 0x7f, 0xbf, 0xad, 0xa9, 0x9a, 0xae, 0xea, 0x31, 0x80, 0xaf, 0x7c, 0x35, 0x97,
+ 0xa4, 0x4a, 0xab, 0x7a, 0x0d, 0xaf, 0x8b, 0xcb, 0x03, 0x07, 0x7d, 0xa5, 0xfc, 0x50, 0x1e, 0x2e,
+ 0x3e, 0x35, 0xf3, 0xcd, 0xc3, 0x6d, 0x99, 0xb5, 0xd2, 0x20, 0xd1, 0x2a, 0xed, 0x2c, 0x16, 0x77,
+ 0xc1, 0x34, 0x2d, 0x6e, 0xc8, 0x38, 0x8f, 0x1a, 0x49, 0x2a, 0x37, 0x83, 0xf3, 0xf5, 0x5b, 0xe6,
+ 0x3a, 0xe4, 0x1c, 0x93, 0x73, 0xcb, 0x71, 0x1e, 0xdd, 0x9d, 0xe8, 0x40, 0xc5, 0xd9, 0xfe, 0xeb,
+ 0x3f, 0xff, 0xff, 0xe0, 0xff, 0x6e, 0x1f, 0x59, 0x9f, 0x22, 0x14, 0xff, 0xb6, 0x56, 0x80, 0x62,
+ 0x1d, 0x6e, 0xac, 0xf8, 0x32, 0x9d, 0x06, 0xb1, 0x2f, 0x53, 0x8b, 0xf1, 0x3b, 0x32, 0x4e, 0x1b,
+ 0xc6, 0x7b, 0x09, 0x15, 0x4b, 0x30, 0x3e, 0x88, 0xeb, 0x7b, 0x72, 0x8d, 0x49, 0x53, 0xb2, 0x02,
+ 0x93, 0x85, 0xa4, 0x95, 0x67, 0x5a, 0x45, 0xb1, 0x17, 0x49, 0x8b, 0xe6, 0x87, 0x42, 0x53, 0x5b,
+ 0x9f, 0x40, 0x6c, 0xa9, 0xa4, 0x84, 0x80, 0x11, 0xfc, 0xa6, 0x2d, 0x5b, 0xa1, 0xc5, 0xf0, 0x23,
+ 0x05, 0x52, 0xae, 0x17, 0x67, 0x60, 0x06, 0xaf, 0xcf, 0x79, 0x61, 0x2e, 0xcd, 0x48, 0x0e, 0xf5,
+ 0xf5, 0x9c, 0xc1, 0x65, 0x2c, 0xfb, 0xe9, 0xe2, 0x50, 0x11, 0xce, 0x74, 0x29, 0x30, 0x62, 0x32,
+ 0xaa, 0xe8, 0x4b, 0xad, 0x65, 0x9a, 0x35, 0xbc, 0xb0, 0x5f, 0x78, 0x27, 0x82, 0xb0, 0x34, 0x5e,
+ 0xda, 0xae, 0x56, 0x71, 0xa5, 0x43, 0x2e, 0x86, 0xa1, 0xd8, 0x80, 0x9b, 0xfa, 0x3c, 0x15, 0x0e,
+ 0xce, 0xcb, 0xe4, 0x9c, 0xd9, 0xf3, 0x64, 0xa0, 0x76, 0x0d, 0xf8, 0xfb, 0xb2, 0x96, 0x0e, 0xce,
+ 0xd7, 0xc8, 0x59, 0x27, 0x96, 0x4b, 0x8a, 0xc6, 0x53, 0x30, 0x75, 0x4e, 0xa6, 0x4d, 0x95, 0xc9,
+ 0x86, 0x7c, 0x24, 0xf7, 0x42, 0x07, 0xdd, 0x15, 0xd2, 0x4d, 0x12, 0xb8, 0x8c, 0x1c, 0xba, 0x8e,
+ 0xc2, 0xc8, 0xa6, 0xd7, 0x92, 0x0e, 0x8a, 0xab, 0xa4, 0x18, 0xc6, 0xf5, 0x88, 0x2e, 0xc2, 0x98,
+ 0xaf, 0x3a, 0xb7, 0xe4, 0x80, 0x5f, 0x23, 0x7c, 0x94, 0x19, 0x52, 0x24, 0x2a, 0xc9, 0x43, 0x4f,
+ 0xbb, 0x44, 0xf0, 0x3a, 0x2b, 0x98, 0x21, 0xc5, 0x00, 0x69, 0x7d, 0x83, 0x15, 0x99, 0x91, 0xcf,
+ 0x05, 0x18, 0x55, 0x71, 0xb8, 0xa5, 0x62, 0x97, 0x20, 0xde, 0x24, 0x03, 0x10, 0x82, 0x82, 0x79,
+ 0xa8, 0xb9, 0x16, 0xe2, 0xad, 0x6d, 0xde, 0x1e, 0x5c, 0x81, 0x15, 0x98, 0xe4, 0x06, 0x15, 0xa8,
+ 0xd8, 0x41, 0xf1, 0x36, 0x29, 0x26, 0x0c, 0x8c, 0x6e, 0x43, 0xcb, 0x4c, 0xfb, 0xd2, 0x45, 0xf2,
+ 0x0e, 0xdf, 0x06, 0x21, 0x94, 0xca, 0xa6, 0x8c, 0x5b, 0x67, 0xdd, 0x0c, 0xef, 0x72, 0x2a, 0x99,
+ 0x41, 0xc5, 0x12, 0x8c, 0x47, 0x5e, 0x9a, 0x9d, 0xf5, 0x42, 0xa7, 0x72, 0xbc, 0x47, 0x8e, 0xb1,
+ 0x12, 0xa2, 0x8c, 0xe4, 0xf1, 0x20, 0x9a, 0xf7, 0x39, 0x23, 0x06, 0x46, 0x5b, 0x2f, 0xd3, 0x5e,
+ 0x33, 0x94, 0x8d, 0x41, 0x6c, 0x1f, 0xf0, 0xd6, 0xeb, 0xb0, 0xab, 0xa6, 0x71, 0x1e, 0x6a, 0x59,
+ 0x70, 0xc1, 0x49, 0xf3, 0x21, 0x57, 0xba, 0x00, 0x10, 0x7e, 0x00, 0x6e, 0xee, 0x3b, 0x26, 0x1c,
+ 0x64, 0x1f, 0x91, 0x6c, 0xb6, 0xcf, 0xa8, 0xa0, 0x96, 0x30, 0xa8, 0xf2, 0x63, 0x6e, 0x09, 0xb2,
+ 0xc7, 0xb5, 0x06, 0x33, 0x79, 0x9c, 0x79, 0x9b, 0x83, 0x65, 0xed, 0x13, 0xce, 0x5a, 0x87, 0xad,
+ 0x64, 0xed, 0x34, 0xcc, 0x92, 0x71, 0xb0, 0xba, 0x7e, 0xca, 0x8d, 0xb5, 0x43, 0x6f, 0x54, 0xab,
+ 0xfb, 0x20, 0x1c, 0x28, 0xd3, 0x79, 0x5e, 0xcb, 0x38, 0x43, 0xa6, 0x11, 0x79, 0x89, 0x83, 0xf9,
+ 0x3a, 0x99, 0xb9, 0xe3, 0x2f, 0x97, 0x82, 0x55, 0x2f, 0x41, 0xf9, 0xfd, 0xb0, 0x9f, 0xe5, 0x79,
+ 0x9c, 0xca, 0x96, 0xf2, 0xe3, 0xe0, 0x82, 0x6c, 0x3b, 0xa8, 0x3f, 0xeb, 0x29, 0xd5, 0x86, 0x81,
+ 0xa3, 0xf9, 0x24, 0xdc, 0x50, 0x9e, 0x55, 0x1a, 0x41, 0x94, 0xa8, 0x54, 0x5b, 0x8c, 0x9f, 0x73,
+ 0xa5, 0x4a, 0xee, 0x64, 0x81, 0x89, 0x65, 0x98, 0x28, 0x3e, 0xba, 0x3e, 0x92, 0x5f, 0x90, 0x68,
+ 0xbc, 0x4b, 0x51, 0xe3, 0x68, 0xa9, 0x28, 0xf1, 0x52, 0x97, 0xfe, 0xf7, 0x25, 0x37, 0x0e, 0x42,
+ 0xa8, 0x71, 0xe8, 0xad, 0x44, 0xe2, 0xb4, 0x77, 0x30, 0x7c, 0xc5, 0x8d, 0x83, 0x19, 0x52, 0xf0,
+ 0x81, 0xc1, 0x41, 0xf1, 0x35, 0x2b, 0x98, 0x41, 0xc5, 0x3d, 0xdd, 0x41, 0x9b, 0x4a, 0x3f, 0xc8,
+ 0x74, 0xea, 0xe1, 0x6a, 0x8b, 0xea, 0x9b, 0xed, 0xea, 0x21, 0x6c, 0xdd, 0x40, 0xc5, 0x29, 0x98,
+ 0xec, 0x39, 0x62, 0xd4, 0x6f, 0xdb, 0x63, 0x5b, 0x95, 0x59, 0xe6, 0xf9, 0xa5, 0xf0, 0xd1, 0x1d,
+ 0x6a, 0x46, 0xd5, 0x13, 0x86, 0xb8, 0x13, 0xeb, 0x5e, 0x3d, 0x07, 0xd8, 0x65, 0x17, 0x77, 0xca,
+ 0xd2, 0x57, 0x8e, 0x01, 0xe2, 0x04, 0x8c, 0x57, 0xce, 0x00, 0x76, 0xd5, 0x63, 0xa4, 0x1a, 0x33,
+ 0x8f, 0x00, 0xe2, 0x08, 0x0c, 0xe1, 0x3c, 0xb7, 0xe3, 0x8f, 0x13, 0x5e, 0x2c, 0x17, 0xc7, 0x60,
+ 0x84, 0xe7, 0xb8, 0x1d, 0x7d, 0x82, 0xd0, 0x12, 0x41, 0x9c, 0x67, 0xb8, 0x1d, 0x7f, 0x92, 0x71,
+ 0x46, 0x10, 0x77, 0x4f, 0xe1, 0xb7, 0x4f, 0x0f, 0x51, 0x1f, 0xe6, 0xdc, 0xcd, 0xc3, 0x30, 0x0d,
+ 0x6f, 0x3b, 0xfd, 0x14, 0xfd, 0x38, 0x13, 0xe2, 0x0e, 0xd8, 0xe7, 0x98, 0xf0, 0x67, 0x08, 0xed,
+ 0xac, 0x17, 0x4b, 0x30, 0x6a, 0x0c, 0x6c, 0x3b, 0xfe, 0x2c, 0xe1, 0x26, 0x85, 0xa1, 0xd3, 0xc0,
+ 0xb6, 0x0b, 0x9e, 0xe3, 0xd0, 0x89, 0xc0, 0xb4, 0xf1, 0xac, 0xb6, 0xd3, 0xcf, 0x73, 0xd6, 0x19,
+ 0x11, 0x0b, 0x50, 0x2b, 0xfb, 0xaf, 0x9d, 0x7f, 0x81, 0xf8, 0x2e, 0x83, 0x19, 0x30, 0xfa, 0xbf,
+ 0x5d, 0xf1, 0x22, 0x67, 0xc0, 0xa0, 0x70, 0x1b, 0xf5, 0xce, 0x74, 0xbb, 0xe9, 0x25, 0xde, 0x46,
+ 0x3d, 0x23, 0x1d, 0xab, 0x59, 0xb4, 0x41, 0xbb, 0xe2, 0x65, 0xae, 0x66, 0xb1, 0x1e, 0xc3, 0xe8,
+ 0x1d, 0x92, 0x76, 0xc7, 0x2b, 0x1c, 0x46, 0xcf, 0x8c, 0x14, 0x6b, 0x50, 0xdf, 0x3b, 0x20, 0xed,
+ 0xbe, 0x57, 0xc9, 0x37, 0xb5, 0x67, 0x3e, 0x8a, 0xfb, 0x60, 0xb6, 0xff, 0x70, 0xb4, 0x5b, 0x2f,
+ 0xed, 0xf4, 0xbc, 0xce, 0x98, 0xb3, 0x51, 0x9c, 0xee, 0x76, 0x59, 0x73, 0x30, 0xda, 0xb5, 0x97,
+ 0x77, 0xaa, 0x8d, 0xd6, 0x9c, 0x8b, 0x62, 0x11, 0xa0, 0x3b, 0x93, 0xec, 0xae, 0x2b, 0xe4, 0x32,
+ 0x20, 0xdc, 0x1a, 0x34, 0x92, 0xec, 0xfc, 0x55, 0xde, 0x1a, 0x44, 0xe0, 0xd6, 0xe0, 0x69, 0x64,
+ 0xa7, 0xaf, 0xf1, 0xd6, 0x60, 0x44, 0xcc, 0xc3, 0x48, 0x9c, 0x87, 0x21, 0x3e, 0x5b, 0xf5, 0x5b,
+ 0xfb, 0x8c, 0x1b, 0x19, 0xb6, 0x19, 0xfe, 0x65, 0x97, 0x60, 0x06, 0xc4, 0x11, 0xd8, 0x27, 0xa3,
+ 0xa6, 0x6c, 0xdb, 0xc8, 0x5f, 0x77, 0xb9, 0x9f, 0xe0, 0x6a, 0xb1, 0x00, 0xd0, 0x79, 0x99, 0xc6,
+ 0x28, 0x6c, 0xec, 0x6f, 0xbb, 0x9d, 0xf7, 0x7a, 0x03, 0xe9, 0x0a, 0x8a, 0xb7, 0x71, 0x8b, 0x60,
+ 0xbb, 0x2a, 0x28, 0x5e, 0xc0, 0x8f, 0xc2, 0xf0, 0x43, 0x99, 0x8a, 0xb5, 0xe7, 0xdb, 0xe8, 0xdf,
+ 0x89, 0xe6, 0xf5, 0x98, 0xb0, 0x48, 0xa5, 0x52, 0x7b, 0x7e, 0x66, 0x63, 0xff, 0x20, 0xb6, 0x04,
+ 0x10, 0x6e, 0x79, 0x99, 0x76, 0xb9, 0xef, 0x3f, 0x19, 0x66, 0x00, 0x83, 0xc6, 0xeb, 0x87, 0xe5,
+ 0x96, 0x8d, 0xfd, 0x8b, 0x83, 0xa6, 0xf5, 0xe2, 0x18, 0xd4, 0xf0, 0xb2, 0xf8, 0x3f, 0x84, 0x0d,
+ 0xfe, 0x9b, 0xe0, 0x2e, 0x81, 0xbf, 0x9c, 0xe9, 0xb6, 0x0e, 0xec, 0xc9, 0xfe, 0x87, 0x2a, 0xcd,
+ 0xeb, 0xc5, 0x22, 0x8c, 0x66, 0xba, 0xdd, 0xce, 0xe9, 0x44, 0x63, 0xc1, 0xff, 0xdd, 0x2d, 0x5f,
+ 0x72, 0x4b, 0xe6, 0xf8, 0x21, 0x98, 0x6e, 0xa9, 0xa8, 0x17, 0x3c, 0x0e, 0x2b, 0x6a, 0x45, 0xad,
+ 0x15, 0xbb, 0xe8, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x9c, 0xec, 0xd8, 0x50, 0x13, 0x00,
+ 0x00,
+}
diff --git a/vendor/github.com/gogo/protobuf/gogoproto/helper.go b/vendor/github.com/gogo/protobuf/gogoproto/helper.go
new file mode 100644
index 00000000..6b851c56
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/gogoproto/helper.go
@@ -0,0 +1,357 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gogoproto
+
+import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+import proto "github.com/gogo/protobuf/proto"
+
+func IsEmbed(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Embed, false)
+}
+
+func IsNullable(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Nullable, true)
+}
+
+func IsStdTime(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Stdtime, false)
+}
+
+func IsStdDuration(field *google_protobuf.FieldDescriptorProto) bool {
+ return proto.GetBoolExtension(field.Options, E_Stdduration, false)
+}
+
+func NeedsNilCheck(proto3 bool, field *google_protobuf.FieldDescriptorProto) bool {
+ nullable := IsNullable(field)
+ if field.IsMessage() || IsCustomType(field) {
+ return nullable
+ }
+ if proto3 {
+ return false
+ }
+ return nullable || *field.Type == google_protobuf.FieldDescriptorProto_TYPE_BYTES
+}
+
+func IsCustomType(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCustomType(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsCastType(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCastType(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsCastKey(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCastKey(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsCastValue(field *google_protobuf.FieldDescriptorProto) bool {
+ typ := GetCastValue(field)
+ if len(typ) > 0 {
+ return true
+ }
+ return false
+}
+
+func HasEnumDecl(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_Enumdecl, proto.GetBoolExtension(file.Options, E_EnumdeclAll, true))
+}
+
+func HasTypeDecl(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Typedecl, proto.GetBoolExtension(file.Options, E_TypedeclAll, true))
+}
+
+func GetCustomType(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Customtype)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetCastType(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Casttype)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetCastKey(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Castkey)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetCastValue(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Castvalue)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func IsCustomName(field *google_protobuf.FieldDescriptorProto) bool {
+ name := GetCustomName(field)
+ if len(name) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsEnumCustomName(field *google_protobuf.EnumDescriptorProto) bool {
+ name := GetEnumCustomName(field)
+ if len(name) > 0 {
+ return true
+ }
+ return false
+}
+
+func IsEnumValueCustomName(field *google_protobuf.EnumValueDescriptorProto) bool {
+ name := GetEnumValueCustomName(field)
+ if len(name) > 0 {
+ return true
+ }
+ return false
+}
+
+func GetCustomName(field *google_protobuf.FieldDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Customname)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetEnumCustomName(field *google_protobuf.EnumDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_EnumCustomname)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetEnumValueCustomName(field *google_protobuf.EnumValueDescriptorProto) string {
+ if field == nil {
+ return ""
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_EnumvalueCustomname)
+ if err == nil && v.(*string) != nil {
+ return *(v.(*string))
+ }
+ }
+ return ""
+}
+
+func GetJsonTag(field *google_protobuf.FieldDescriptorProto) *string {
+ if field == nil {
+ return nil
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Jsontag)
+ if err == nil && v.(*string) != nil {
+ return (v.(*string))
+ }
+ }
+ return nil
+}
+
+func GetMoreTags(field *google_protobuf.FieldDescriptorProto) *string {
+ if field == nil {
+ return nil
+ }
+ if field.Options != nil {
+ v, err := proto.GetExtension(field.Options, E_Moretags)
+ if err == nil && v.(*string) != nil {
+ return (v.(*string))
+ }
+ }
+ return nil
+}
+
+type EnableFunc func(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool
+
+func EnabledGoEnumPrefix(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_GoprotoEnumPrefix, proto.GetBoolExtension(file.Options, E_GoprotoEnumPrefixAll, true))
+}
+
+func EnabledGoStringer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_GoprotoStringer, proto.GetBoolExtension(file.Options, E_GoprotoStringerAll, true))
+}
+
+func HasGoGetters(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_GoprotoGetters, proto.GetBoolExtension(file.Options, E_GoprotoGettersAll, true))
+}
+
+func IsUnion(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Onlyone, proto.GetBoolExtension(file.Options, E_OnlyoneAll, false))
+}
+
+func HasGoString(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Gostring, proto.GetBoolExtension(file.Options, E_GostringAll, false))
+}
+
+func HasEqual(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Equal, proto.GetBoolExtension(file.Options, E_EqualAll, false))
+}
+
+func HasVerboseEqual(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_VerboseEqual, proto.GetBoolExtension(file.Options, E_VerboseEqualAll, false))
+}
+
+func IsStringer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Stringer, proto.GetBoolExtension(file.Options, E_StringerAll, false))
+}
+
+func IsFace(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Face, proto.GetBoolExtension(file.Options, E_FaceAll, false))
+}
+
+func HasDescription(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Description, proto.GetBoolExtension(file.Options, E_DescriptionAll, false))
+}
+
+func HasPopulate(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Populate, proto.GetBoolExtension(file.Options, E_PopulateAll, false))
+}
+
+func HasTestGen(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Testgen, proto.GetBoolExtension(file.Options, E_TestgenAll, false))
+}
+
+func HasBenchGen(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Benchgen, proto.GetBoolExtension(file.Options, E_BenchgenAll, false))
+}
+
+func IsMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Marshaler, proto.GetBoolExtension(file.Options, E_MarshalerAll, false))
+}
+
+func IsUnmarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Unmarshaler, proto.GetBoolExtension(file.Options, E_UnmarshalerAll, false))
+}
+
+func IsStableMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_StableMarshaler, proto.GetBoolExtension(file.Options, E_StableMarshalerAll, false))
+}
+
+func IsSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Sizer, proto.GetBoolExtension(file.Options, E_SizerAll, false))
+}
+
+func IsProtoSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Protosizer, proto.GetBoolExtension(file.Options, E_ProtosizerAll, false))
+}
+
+func IsGoEnumStringer(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_GoprotoEnumStringer, proto.GetBoolExtension(file.Options, E_GoprotoEnumStringerAll, true))
+}
+
+func IsEnumStringer(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
+ return proto.GetBoolExtension(enum.Options, E_EnumStringer, proto.GetBoolExtension(file.Options, E_EnumStringerAll, false))
+}
+
+func IsUnsafeMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_UnsafeMarshaler, proto.GetBoolExtension(file.Options, E_UnsafeMarshalerAll, false))
+}
+
+func IsUnsafeUnmarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_UnsafeUnmarshaler, proto.GetBoolExtension(file.Options, E_UnsafeUnmarshalerAll, false))
+}
+
+func HasExtensionsMap(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_GoprotoExtensionsMap, proto.GetBoolExtension(file.Options, E_GoprotoExtensionsMapAll, true))
+}
+
+func HasUnrecognized(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ if IsProto3(file) {
+ return false
+ }
+ return proto.GetBoolExtension(message.Options, E_GoprotoUnrecognized, proto.GetBoolExtension(file.Options, E_GoprotoUnrecognizedAll, true))
+}
+
+func IsProto3(file *google_protobuf.FileDescriptorProto) bool {
+ return file.GetSyntax() == "proto3"
+}
+
+func ImportsGoGoProto(file *google_protobuf.FileDescriptorProto) bool {
+ return proto.GetBoolExtension(file.Options, E_GogoprotoImport, true)
+}
+
+func HasCompare(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
+ return proto.GetBoolExtension(message.Options, E_Compare, proto.GetBoolExtension(file.Options, E_CompareAll, false))
+}
+
+func RegistersGolangProto(file *google_protobuf.FileDescriptorProto) bool {
+ return proto.GetBoolExtension(file.Options, E_GoprotoRegistration, false)
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.go
new file mode 100644
index 00000000..a85bf198
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.go
@@ -0,0 +1,118 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Package descriptor provides functions for obtaining protocol buffer
+// descriptors for generated Go types.
+//
+// These functions cannot go in package proto because they depend on the
+// generated protobuf descriptor messages, which themselves depend on proto.
+package descriptor
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io/ioutil"
+
+ "github.com/gogo/protobuf/proto"
+)
+
+// extractFile extracts a FileDescriptorProto from a gzip'd buffer.
+func extractFile(gz []byte) (*FileDescriptorProto, error) {
+ r, err := gzip.NewReader(bytes.NewReader(gz))
+ if err != nil {
+ return nil, fmt.Errorf("failed to open gzip reader: %v", err)
+ }
+ defer r.Close()
+
+ b, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, fmt.Errorf("failed to uncompress descriptor: %v", err)
+ }
+
+ fd := new(FileDescriptorProto)
+ if err := proto.Unmarshal(b, fd); err != nil {
+ return nil, fmt.Errorf("malformed FileDescriptorProto: %v", err)
+ }
+
+ return fd, nil
+}
+
+// Message is a proto.Message with a method to return its descriptor.
+//
+// Message types generated by the protocol compiler always satisfy
+// the Message interface.
+type Message interface {
+ proto.Message
+ Descriptor() ([]byte, []int)
+}
+
+// ForMessage returns a FileDescriptorProto and a DescriptorProto from within it
+// describing the given message.
+func ForMessage(msg Message) (fd *FileDescriptorProto, md *DescriptorProto) {
+ gz, path := msg.Descriptor()
+ fd, err := extractFile(gz)
+ if err != nil {
+ panic(fmt.Sprintf("invalid FileDescriptorProto for %T: %v", msg, err))
+ }
+
+ md = fd.MessageType[path[0]]
+ for _, i := range path[1:] {
+ md = md.NestedType[i]
+ }
+ return fd, md
+}
+
+// Is this field a scalar numeric type?
+func (field *FieldDescriptorProto) IsScalar() bool {
+ if field.Type == nil {
+ return false
+ }
+ switch *field.Type {
+ case FieldDescriptorProto_TYPE_DOUBLE,
+ FieldDescriptorProto_TYPE_FLOAT,
+ FieldDescriptorProto_TYPE_INT64,
+ FieldDescriptorProto_TYPE_UINT64,
+ FieldDescriptorProto_TYPE_INT32,
+ FieldDescriptorProto_TYPE_FIXED64,
+ FieldDescriptorProto_TYPE_FIXED32,
+ FieldDescriptorProto_TYPE_BOOL,
+ FieldDescriptorProto_TYPE_UINT32,
+ FieldDescriptorProto_TYPE_ENUM,
+ FieldDescriptorProto_TYPE_SFIXED32,
+ FieldDescriptorProto_TYPE_SFIXED64,
+ FieldDescriptorProto_TYPE_SINT32,
+ FieldDescriptorProto_TYPE_SINT64:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go
new file mode 100644
index 00000000..e2703901
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go
@@ -0,0 +1,2150 @@
+// Code generated by protoc-gen-gogo.
+// source: descriptor.proto
+// DO NOT EDIT!
+
+/*
+Package descriptor is a generated protocol buffer package.
+
+It is generated from these files:
+ descriptor.proto
+
+It has these top-level messages:
+ FileDescriptorSet
+ FileDescriptorProto
+ DescriptorProto
+ FieldDescriptorProto
+ OneofDescriptorProto
+ EnumDescriptorProto
+ EnumValueDescriptorProto
+ ServiceDescriptorProto
+ MethodDescriptorProto
+ FileOptions
+ MessageOptions
+ FieldOptions
+ OneofOptions
+ EnumOptions
+ EnumValueOptions
+ ServiceOptions
+ MethodOptions
+ UninterpretedOption
+ SourceCodeInfo
+ GeneratedCodeInfo
+*/
+package descriptor
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+type FieldDescriptorProto_Type int32
+
+const (
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1
+ FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3
+ FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5
+ FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6
+ FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7
+ FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8
+ FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9
+ // Tag-delimited aggregate.
+ // Group type is deprecated and not supported in proto3. However, Proto3
+ // implementations should still be able to parse the group wire format and
+ // treat group fields as unknown fields.
+ FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10
+ FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11
+ // New in version 2.
+ FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12
+ FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13
+ FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14
+ FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15
+ FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16
+ FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17
+ FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18
+)
+
+var FieldDescriptorProto_Type_name = map[int32]string{
+ 1: "TYPE_DOUBLE",
+ 2: "TYPE_FLOAT",
+ 3: "TYPE_INT64",
+ 4: "TYPE_UINT64",
+ 5: "TYPE_INT32",
+ 6: "TYPE_FIXED64",
+ 7: "TYPE_FIXED32",
+ 8: "TYPE_BOOL",
+ 9: "TYPE_STRING",
+ 10: "TYPE_GROUP",
+ 11: "TYPE_MESSAGE",
+ 12: "TYPE_BYTES",
+ 13: "TYPE_UINT32",
+ 14: "TYPE_ENUM",
+ 15: "TYPE_SFIXED32",
+ 16: "TYPE_SFIXED64",
+ 17: "TYPE_SINT32",
+ 18: "TYPE_SINT64",
+}
+var FieldDescriptorProto_Type_value = map[string]int32{
+ "TYPE_DOUBLE": 1,
+ "TYPE_FLOAT": 2,
+ "TYPE_INT64": 3,
+ "TYPE_UINT64": 4,
+ "TYPE_INT32": 5,
+ "TYPE_FIXED64": 6,
+ "TYPE_FIXED32": 7,
+ "TYPE_BOOL": 8,
+ "TYPE_STRING": 9,
+ "TYPE_GROUP": 10,
+ "TYPE_MESSAGE": 11,
+ "TYPE_BYTES": 12,
+ "TYPE_UINT32": 13,
+ "TYPE_ENUM": 14,
+ "TYPE_SFIXED32": 15,
+ "TYPE_SFIXED64": 16,
+ "TYPE_SINT32": 17,
+ "TYPE_SINT64": 18,
+}
+
+func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type {
+ p := new(FieldDescriptorProto_Type)
+ *p = x
+ return p
+}
+func (x FieldDescriptorProto_Type) String() string {
+ return proto.EnumName(FieldDescriptorProto_Type_name, int32(x))
+}
+func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Type_value, data, "FieldDescriptorProto_Type")
+ if err != nil {
+ return err
+ }
+ *x = FieldDescriptorProto_Type(value)
+ return nil
+}
+func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{3, 0}
+}
+
+type FieldDescriptorProto_Label int32
+
+const (
+ // 0 is reserved for errors
+ FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1
+ FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2
+ FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3
+)
+
+var FieldDescriptorProto_Label_name = map[int32]string{
+ 1: "LABEL_OPTIONAL",
+ 2: "LABEL_REQUIRED",
+ 3: "LABEL_REPEATED",
+}
+var FieldDescriptorProto_Label_value = map[string]int32{
+ "LABEL_OPTIONAL": 1,
+ "LABEL_REQUIRED": 2,
+ "LABEL_REPEATED": 3,
+}
+
+func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label {
+ p := new(FieldDescriptorProto_Label)
+ *p = x
+ return p
+}
+func (x FieldDescriptorProto_Label) String() string {
+ return proto.EnumName(FieldDescriptorProto_Label_name, int32(x))
+}
+func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Label_value, data, "FieldDescriptorProto_Label")
+ if err != nil {
+ return err
+ }
+ *x = FieldDescriptorProto_Label(value)
+ return nil
+}
+func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{3, 1}
+}
+
+// Generated classes can be optimized for speed or code size.
+type FileOptions_OptimizeMode int32
+
+const (
+ FileOptions_SPEED FileOptions_OptimizeMode = 1
+ // etc.
+ FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2
+ FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3
+)
+
+var FileOptions_OptimizeMode_name = map[int32]string{
+ 1: "SPEED",
+ 2: "CODE_SIZE",
+ 3: "LITE_RUNTIME",
+}
+var FileOptions_OptimizeMode_value = map[string]int32{
+ "SPEED": 1,
+ "CODE_SIZE": 2,
+ "LITE_RUNTIME": 3,
+}
+
+func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode {
+ p := new(FileOptions_OptimizeMode)
+ *p = x
+ return p
+}
+func (x FileOptions_OptimizeMode) String() string {
+ return proto.EnumName(FileOptions_OptimizeMode_name, int32(x))
+}
+func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FileOptions_OptimizeMode_value, data, "FileOptions_OptimizeMode")
+ if err != nil {
+ return err
+ }
+ *x = FileOptions_OptimizeMode(value)
+ return nil
+}
+func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{9, 0}
+}
+
+type FieldOptions_CType int32
+
+const (
+ // Default mode.
+ FieldOptions_STRING FieldOptions_CType = 0
+ FieldOptions_CORD FieldOptions_CType = 1
+ FieldOptions_STRING_PIECE FieldOptions_CType = 2
+)
+
+var FieldOptions_CType_name = map[int32]string{
+ 0: "STRING",
+ 1: "CORD",
+ 2: "STRING_PIECE",
+}
+var FieldOptions_CType_value = map[string]int32{
+ "STRING": 0,
+ "CORD": 1,
+ "STRING_PIECE": 2,
+}
+
+func (x FieldOptions_CType) Enum() *FieldOptions_CType {
+ p := new(FieldOptions_CType)
+ *p = x
+ return p
+}
+func (x FieldOptions_CType) String() string {
+ return proto.EnumName(FieldOptions_CType_name, int32(x))
+}
+func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldOptions_CType_value, data, "FieldOptions_CType")
+ if err != nil {
+ return err
+ }
+ *x = FieldOptions_CType(value)
+ return nil
+}
+func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{11, 0}
+}
+
+type FieldOptions_JSType int32
+
+const (
+ // Use the default type.
+ FieldOptions_JS_NORMAL FieldOptions_JSType = 0
+ // Use JavaScript strings.
+ FieldOptions_JS_STRING FieldOptions_JSType = 1
+ // Use JavaScript numbers.
+ FieldOptions_JS_NUMBER FieldOptions_JSType = 2
+)
+
+var FieldOptions_JSType_name = map[int32]string{
+ 0: "JS_NORMAL",
+ 1: "JS_STRING",
+ 2: "JS_NUMBER",
+}
+var FieldOptions_JSType_value = map[string]int32{
+ "JS_NORMAL": 0,
+ "JS_STRING": 1,
+ "JS_NUMBER": 2,
+}
+
+func (x FieldOptions_JSType) Enum() *FieldOptions_JSType {
+ p := new(FieldOptions_JSType)
+ *p = x
+ return p
+}
+func (x FieldOptions_JSType) String() string {
+ return proto.EnumName(FieldOptions_JSType_name, int32(x))
+}
+func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldOptions_JSType_value, data, "FieldOptions_JSType")
+ if err != nil {
+ return err
+ }
+ *x = FieldOptions_JSType(value)
+ return nil
+}
+func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{11, 1}
+}
+
+// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+// or neither? HTTP based RPC implementation may choose GET verb for safe
+// methods, and PUT verb for idempotent methods instead of the default POST.
+type MethodOptions_IdempotencyLevel int32
+
+const (
+ MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0
+ MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1
+ MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2
+)
+
+var MethodOptions_IdempotencyLevel_name = map[int32]string{
+ 0: "IDEMPOTENCY_UNKNOWN",
+ 1: "NO_SIDE_EFFECTS",
+ 2: "IDEMPOTENT",
+}
+var MethodOptions_IdempotencyLevel_value = map[string]int32{
+ "IDEMPOTENCY_UNKNOWN": 0,
+ "NO_SIDE_EFFECTS": 1,
+ "IDEMPOTENT": 2,
+}
+
+func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel {
+ p := new(MethodOptions_IdempotencyLevel)
+ *p = x
+ return p
+}
+func (x MethodOptions_IdempotencyLevel) String() string {
+ return proto.EnumName(MethodOptions_IdempotencyLevel_name, int32(x))
+}
+func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MethodOptions_IdempotencyLevel_value, data, "MethodOptions_IdempotencyLevel")
+ if err != nil {
+ return err
+ }
+ *x = MethodOptions_IdempotencyLevel(value)
+ return nil
+}
+func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{16, 0}
+}
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+type FileDescriptorSet struct {
+ File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} }
+func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) }
+func (*FileDescriptorSet) ProtoMessage() {}
+func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{0} }
+
+func (m *FileDescriptorSet) GetFile() []*FileDescriptorProto {
+ if m != nil {
+ return m.File
+ }
+ return nil
+}
+
+// Describes a complete .proto file.
+type FileDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"`
+ // Names of files imported by this file.
+ Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"`
+ // Indexes of the public imported files in the dependency list above.
+ PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"`
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"`
+ // All top-level definitions in this file.
+ MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
+ Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"`
+ Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"`
+ // This field contains optional information about the original source code.
+ // You may safely remove this entire field without harming runtime
+ // functionality of the descriptors -- the information is needed only by
+ // development tools.
+ SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"`
+ // The syntax of the proto file.
+ // The supported values are "proto2" and "proto3".
+ Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} }
+func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*FileDescriptorProto) ProtoMessage() {}
+func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{1} }
+
+func (m *FileDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *FileDescriptorProto) GetPackage() string {
+ if m != nil && m.Package != nil {
+ return *m.Package
+ }
+ return ""
+}
+
+func (m *FileDescriptorProto) GetDependency() []string {
+ if m != nil {
+ return m.Dependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetPublicDependency() []int32 {
+ if m != nil {
+ return m.PublicDependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetWeakDependency() []int32 {
+ if m != nil {
+ return m.WeakDependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetMessageType() []*DescriptorProto {
+ if m != nil {
+ return m.MessageType
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto {
+ if m != nil {
+ return m.EnumType
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetService() []*ServiceDescriptorProto {
+ if m != nil {
+ return m.Service
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetExtension() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Extension
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetOptions() *FileOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo {
+ if m != nil {
+ return m.SourceCodeInfo
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetSyntax() string {
+ if m != nil && m.Syntax != nil {
+ return *m.Syntax
+ }
+ return ""
+}
+
+// Describes a message type.
+type DescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"`
+ NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
+ ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"`
+ OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"`
+ Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"`
+ ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto) Reset() { *m = DescriptorProto{} }
+func (m *DescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto) ProtoMessage() {}
+func (*DescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{2} }
+
+func (m *DescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *DescriptorProto) GetField() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Field
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetExtension() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Extension
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetNestedType() []*DescriptorProto {
+ if m != nil {
+ return m.NestedType
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetEnumType() []*EnumDescriptorProto {
+ if m != nil {
+ return m.EnumType
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange {
+ if m != nil {
+ return m.ExtensionRange
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto {
+ if m != nil {
+ return m.OneofDecl
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetOptions() *MessageOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange {
+ if m != nil {
+ return m.ReservedRange
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetReservedName() []string {
+ if m != nil {
+ return m.ReservedName
+ }
+ return nil
+}
+
+type DescriptorProto_ExtensionRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} }
+func (m *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto_ExtensionRange) ProtoMessage() {}
+func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{2, 0}
+}
+
+func (m *DescriptorProto_ExtensionRange) GetStart() int32 {
+ if m != nil && m.Start != nil {
+ return *m.Start
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ExtensionRange) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+// Range of reserved tag numbers. Reserved tag numbers may not be used by
+// fields or extension ranges in the same message. Reserved ranges may
+// not overlap.
+type DescriptorProto_ReservedRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto_ReservedRange) Reset() { *m = DescriptorProto_ReservedRange{} }
+func (m *DescriptorProto_ReservedRange) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto_ReservedRange) ProtoMessage() {}
+func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{2, 1}
+}
+
+func (m *DescriptorProto_ReservedRange) GetStart() int32 {
+ if m != nil && m.Start != nil {
+ return *m.Start
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ReservedRange) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+// Describes a field within a message.
+type FieldDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"`
+ Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"`
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+ Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"`
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"`
+ // For extensions, this is the name of the type being extended. It is
+ // resolved in the same manner as type_name.
+ Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"`
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"`
+ // If set, gives the index of a oneof in the containing type's oneof_decl
+ // list. This field is a member of that oneof.
+ OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"`
+ // JSON name of this field. The value is set by protocol compiler. If the
+ // user has set a "json_name" option on this field, that option's value
+ // will be used. Otherwise, it's deduced from the field's name by converting
+ // it to camelCase.
+ JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"`
+ Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} }
+func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*FieldDescriptorProto) ProtoMessage() {}
+func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{3} }
+
+func (m *FieldDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetNumber() int32 {
+ if m != nil && m.Number != nil {
+ return *m.Number
+ }
+ return 0
+}
+
+func (m *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return FieldDescriptorProto_LABEL_OPTIONAL
+}
+
+func (m *FieldDescriptorProto) GetType() FieldDescriptorProto_Type {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return FieldDescriptorProto_TYPE_DOUBLE
+}
+
+func (m *FieldDescriptorProto) GetTypeName() string {
+ if m != nil && m.TypeName != nil {
+ return *m.TypeName
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetExtendee() string {
+ if m != nil && m.Extendee != nil {
+ return *m.Extendee
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetDefaultValue() string {
+ if m != nil && m.DefaultValue != nil {
+ return *m.DefaultValue
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetOneofIndex() int32 {
+ if m != nil && m.OneofIndex != nil {
+ return *m.OneofIndex
+ }
+ return 0
+}
+
+func (m *FieldDescriptorProto) GetJsonName() string {
+ if m != nil && m.JsonName != nil {
+ return *m.JsonName
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetOptions() *FieldOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a oneof.
+type OneofDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} }
+func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*OneofDescriptorProto) ProtoMessage() {}
+func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{4} }
+
+func (m *OneofDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *OneofDescriptorProto) GetOptions() *OneofOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes an enum type.
+type EnumDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"`
+ Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
+func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*EnumDescriptorProto) ProtoMessage() {}
+func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{5} }
+
+func (m *EnumDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (m *EnumDescriptorProto) GetOptions() *EnumOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a value within an enum.
+type EnumValueDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"`
+ Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} }
+func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*EnumValueDescriptorProto) ProtoMessage() {}
+func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{6}
+}
+
+func (m *EnumValueDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *EnumValueDescriptorProto) GetNumber() int32 {
+ if m != nil && m.Number != nil {
+ return *m.Number
+ }
+ return 0
+}
+
+func (m *EnumValueDescriptorProto) GetOptions() *EnumValueOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a service.
+type ServiceDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"`
+ Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} }
+func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*ServiceDescriptorProto) ProtoMessage() {}
+func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{7} }
+
+func (m *ServiceDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto {
+ if m != nil {
+ return m.Method
+ }
+ return nil
+}
+
+func (m *ServiceDescriptorProto) GetOptions() *ServiceOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a method of a service.
+type MethodDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // Input and output type names. These are resolved in the same way as
+ // FieldDescriptorProto.type_name, but must refer to a message type.
+ InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"`
+ OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"`
+ Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"`
+ // Identifies if client streams multiple client messages
+ ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"`
+ // Identifies if server streams multiple server messages
+ ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} }
+func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*MethodDescriptorProto) ProtoMessage() {}
+func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{8} }
+
+const Default_MethodDescriptorProto_ClientStreaming bool = false
+const Default_MethodDescriptorProto_ServerStreaming bool = false
+
+func (m *MethodDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetInputType() string {
+ if m != nil && m.InputType != nil {
+ return *m.InputType
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetOutputType() string {
+ if m != nil && m.OutputType != nil {
+ return *m.OutputType
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetOptions() *MethodOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *MethodDescriptorProto) GetClientStreaming() bool {
+ if m != nil && m.ClientStreaming != nil {
+ return *m.ClientStreaming
+ }
+ return Default_MethodDescriptorProto_ClientStreaming
+}
+
+func (m *MethodDescriptorProto) GetServerStreaming() bool {
+ if m != nil && m.ServerStreaming != nil {
+ return *m.ServerStreaming
+ }
+ return Default_MethodDescriptorProto_ServerStreaming
+}
+
+type FileOptions struct {
+ // Sets the Java package where classes generated from this .proto will be
+ // placed. By default, the proto package is used, but this is often
+ // inappropriate because proto packages do not normally start with backwards
+ // domain names.
+ JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"`
+ // If set, all the classes from the .proto file are wrapped in a single
+ // outer class with the given name. This applies to both Proto1
+ // (equivalent to the old "--one_java_file" option) and Proto2 (where
+ // a .proto always translates to a single class, but you may want to
+ // explicitly choose the class name).
+ JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"`
+ // If set true, then the Java code generator will generate a separate .java
+ // file for each top-level message, enum, and service defined in the .proto
+ // file. Thus, these types will *not* be nested inside the outer class
+ // named by java_outer_classname. However, the outer class will still be
+ // generated to contain the file's getDescriptor() method as well as any
+ // top-level extensions defined in the file.
+ JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"`
+ // This option does nothing.
+ JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"`
+ // If set true, then the Java2 code generator will generate code that
+ // throws an exception whenever an attempt is made to assign a non-UTF-8
+ // byte sequence to a string field.
+ // Message reflection will do the same.
+ // However, an extension field still accepts non-UTF-8 byte sequences.
+ // This option has no effect on when used with the lite runtime.
+ JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"`
+ OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"`
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. If omitted, the Go package will be derived from the following:
+ // - The basename of the package import path, if provided.
+ // - Otherwise, the package statement in the .proto file, if present.
+ // - Otherwise, the basename of the .proto file, without extension.
+ GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"`
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of google.protobuf.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. Therefore,
+ // these default to false. Old code which depends on generic services should
+ // explicitly set them to true.
+ CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
+ JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
+ PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
+ // Is this file deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for everything in the file, or it will be completely ignored; in the very
+ // least, this is a formalization for deprecating files.
+ Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // Enables the use of arenas for the proto messages in this file. This applies
+ // only to generated classes for C++.
+ CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=0" json:"cc_enable_arenas,omitempty"`
+ // Sets the objective c class prefix which is prepended to all objective c
+ // generated classes from this .proto. There is no default.
+ ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"`
+ // Namespace for generated classes; defaults to the package.
+ CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"`
+ // By default Swift generators will take the proto package and CamelCase it
+ // replacing '.' with underscore and use that to prefix the types/symbols
+ // defined. When this options is provided, they will use this value instead
+ // to prefix the types/symbols defined.
+ SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileOptions) Reset() { *m = FileOptions{} }
+func (m *FileOptions) String() string { return proto.CompactTextString(m) }
+func (*FileOptions) ProtoMessage() {}
+func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{9} }
+
+var extRange_FileOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FileOptions
+}
+
+const Default_FileOptions_JavaMultipleFiles bool = false
+const Default_FileOptions_JavaStringCheckUtf8 bool = false
+const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED
+const Default_FileOptions_CcGenericServices bool = false
+const Default_FileOptions_JavaGenericServices bool = false
+const Default_FileOptions_PyGenericServices bool = false
+const Default_FileOptions_Deprecated bool = false
+const Default_FileOptions_CcEnableArenas bool = false
+
+func (m *FileOptions) GetJavaPackage() string {
+ if m != nil && m.JavaPackage != nil {
+ return *m.JavaPackage
+ }
+ return ""
+}
+
+func (m *FileOptions) GetJavaOuterClassname() string {
+ if m != nil && m.JavaOuterClassname != nil {
+ return *m.JavaOuterClassname
+ }
+ return ""
+}
+
+func (m *FileOptions) GetJavaMultipleFiles() bool {
+ if m != nil && m.JavaMultipleFiles != nil {
+ return *m.JavaMultipleFiles
+ }
+ return Default_FileOptions_JavaMultipleFiles
+}
+
+func (m *FileOptions) GetJavaGenerateEqualsAndHash() bool {
+ if m != nil && m.JavaGenerateEqualsAndHash != nil {
+ return *m.JavaGenerateEqualsAndHash
+ }
+ return false
+}
+
+func (m *FileOptions) GetJavaStringCheckUtf8() bool {
+ if m != nil && m.JavaStringCheckUtf8 != nil {
+ return *m.JavaStringCheckUtf8
+ }
+ return Default_FileOptions_JavaStringCheckUtf8
+}
+
+func (m *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode {
+ if m != nil && m.OptimizeFor != nil {
+ return *m.OptimizeFor
+ }
+ return Default_FileOptions_OptimizeFor
+}
+
+func (m *FileOptions) GetGoPackage() string {
+ if m != nil && m.GoPackage != nil {
+ return *m.GoPackage
+ }
+ return ""
+}
+
+func (m *FileOptions) GetCcGenericServices() bool {
+ if m != nil && m.CcGenericServices != nil {
+ return *m.CcGenericServices
+ }
+ return Default_FileOptions_CcGenericServices
+}
+
+func (m *FileOptions) GetJavaGenericServices() bool {
+ if m != nil && m.JavaGenericServices != nil {
+ return *m.JavaGenericServices
+ }
+ return Default_FileOptions_JavaGenericServices
+}
+
+func (m *FileOptions) GetPyGenericServices() bool {
+ if m != nil && m.PyGenericServices != nil {
+ return *m.PyGenericServices
+ }
+ return Default_FileOptions_PyGenericServices
+}
+
+func (m *FileOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_FileOptions_Deprecated
+}
+
+func (m *FileOptions) GetCcEnableArenas() bool {
+ if m != nil && m.CcEnableArenas != nil {
+ return *m.CcEnableArenas
+ }
+ return Default_FileOptions_CcEnableArenas
+}
+
+func (m *FileOptions) GetObjcClassPrefix() string {
+ if m != nil && m.ObjcClassPrefix != nil {
+ return *m.ObjcClassPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetCsharpNamespace() string {
+ if m != nil && m.CsharpNamespace != nil {
+ return *m.CsharpNamespace
+ }
+ return ""
+}
+
+func (m *FileOptions) GetSwiftPrefix() string {
+ if m != nil && m.SwiftPrefix != nil {
+ return *m.SwiftPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type MessageOptions struct {
+ // Set true to use the old proto1 MessageSet wire format for extensions.
+ // This is provided for backwards-compatibility with the MessageSet wire
+ // format. You should not use this for any other reason: It's less
+ // efficient, has fewer features, and is more complicated.
+ //
+ // The message must be defined exactly as follows:
+ // message Foo {
+ // option message_set_wire_format = true;
+ // extensions 4 to max;
+ // }
+ // Note that the message cannot have any defined fields; MessageSets only
+ // have extensions.
+ //
+ // All extensions of your type must be singular messages; e.g. they cannot
+ // be int32s, enums, or repeated messages.
+ //
+ // Because this is an option, the above two restrictions are not enforced by
+ // the protocol compiler.
+ MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"`
+ // Disables the generation of the standard "descriptor()" accessor, which can
+ // conflict with a field of the same name. This is meant to make migration
+ // from proto1 easier; new code should avoid fields named "descriptor".
+ NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"`
+ // Is this message deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the message, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating messages.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // Whether the message is an automatically generated map entry type for the
+ // maps field.
+ //
+ // For maps fields:
+ // map map_field = 1;
+ // The parsed descriptor looks like:
+ // message MapFieldEntry {
+ // option map_entry = true;
+ // optional KeyType key = 1;
+ // optional ValueType value = 2;
+ // }
+ // repeated MapFieldEntry map_field = 1;
+ //
+ // Implementations may choose not to generate the map_entry=true message, but
+ // use a native map in the target language to hold the keys and values.
+ // The reflection APIs in such implementions still need to work as
+ // if the field is a repeated message field.
+ //
+ // NOTE: Do not set the option in .proto files. Always use the maps syntax
+ // instead. The option should only be implicitly set by the proto compiler
+ // parser.
+ MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MessageOptions) Reset() { *m = MessageOptions{} }
+func (m *MessageOptions) String() string { return proto.CompactTextString(m) }
+func (*MessageOptions) ProtoMessage() {}
+func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{10} }
+
+var extRange_MessageOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MessageOptions
+}
+
+const Default_MessageOptions_MessageSetWireFormat bool = false
+const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
+const Default_MessageOptions_Deprecated bool = false
+
+func (m *MessageOptions) GetMessageSetWireFormat() bool {
+ if m != nil && m.MessageSetWireFormat != nil {
+ return *m.MessageSetWireFormat
+ }
+ return Default_MessageOptions_MessageSetWireFormat
+}
+
+func (m *MessageOptions) GetNoStandardDescriptorAccessor() bool {
+ if m != nil && m.NoStandardDescriptorAccessor != nil {
+ return *m.NoStandardDescriptorAccessor
+ }
+ return Default_MessageOptions_NoStandardDescriptorAccessor
+}
+
+func (m *MessageOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_MessageOptions_Deprecated
+}
+
+func (m *MessageOptions) GetMapEntry() bool {
+ if m != nil && m.MapEntry != nil {
+ return *m.MapEntry
+ }
+ return false
+}
+
+func (m *MessageOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type FieldOptions struct {
+ // The ctype option instructs the C++ code generator to use a different
+ // representation of the field than it normally would. See the specific
+ // options below. This option is not yet implemented in the open source
+ // release -- sorry, we'll try to include it in a future version!
+ Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"`
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob. In proto3, only explicit setting it to
+ // false will avoid using packed encoding.
+ Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"`
+ // The jstype option determines the JavaScript type used for values of the
+ // field. The option is permitted only for 64 bit integral and fixed types
+ // (int64, uint64, sint64, fixed64, sfixed64). By default these types are
+ // represented as JavaScript strings. This avoids loss of precision that can
+ // happen when a large value is converted to a floating point JavaScript
+ // numbers. Specifying JS_NUMBER for the jstype causes the generated
+ // JavaScript code to use the JavaScript "number" type instead of strings.
+ // This option is an enum to permit additional types to be added,
+ // e.g. goog.math.Integer.
+ Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"`
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outer message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"`
+ // Is this field deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for accessors, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating fields.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // For Google-internal migration only. Do not use.
+ Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FieldOptions) Reset() { *m = FieldOptions{} }
+func (m *FieldOptions) String() string { return proto.CompactTextString(m) }
+func (*FieldOptions) ProtoMessage() {}
+func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{11} }
+
+var extRange_FieldOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FieldOptions
+}
+
+const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
+const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL
+const Default_FieldOptions_Lazy bool = false
+const Default_FieldOptions_Deprecated bool = false
+const Default_FieldOptions_Weak bool = false
+
+func (m *FieldOptions) GetCtype() FieldOptions_CType {
+ if m != nil && m.Ctype != nil {
+ return *m.Ctype
+ }
+ return Default_FieldOptions_Ctype
+}
+
+func (m *FieldOptions) GetPacked() bool {
+ if m != nil && m.Packed != nil {
+ return *m.Packed
+ }
+ return false
+}
+
+func (m *FieldOptions) GetJstype() FieldOptions_JSType {
+ if m != nil && m.Jstype != nil {
+ return *m.Jstype
+ }
+ return Default_FieldOptions_Jstype
+}
+
+func (m *FieldOptions) GetLazy() bool {
+ if m != nil && m.Lazy != nil {
+ return *m.Lazy
+ }
+ return Default_FieldOptions_Lazy
+}
+
+func (m *FieldOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_FieldOptions_Deprecated
+}
+
+func (m *FieldOptions) GetWeak() bool {
+ if m != nil && m.Weak != nil {
+ return *m.Weak
+ }
+ return Default_FieldOptions_Weak
+}
+
+func (m *FieldOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type OneofOptions struct {
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OneofOptions) Reset() { *m = OneofOptions{} }
+func (m *OneofOptions) String() string { return proto.CompactTextString(m) }
+func (*OneofOptions) ProtoMessage() {}
+func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{12} }
+
+var extRange_OneofOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*OneofOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_OneofOptions
+}
+
+func (m *OneofOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type EnumOptions struct {
+ // Set this option to true to allow mapping different tag names to the same
+ // value.
+ AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"`
+ // Is this enum deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating enums.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumOptions) Reset() { *m = EnumOptions{} }
+func (m *EnumOptions) String() string { return proto.CompactTextString(m) }
+func (*EnumOptions) ProtoMessage() {}
+func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{13} }
+
+var extRange_EnumOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumOptions
+}
+
+const Default_EnumOptions_Deprecated bool = false
+
+func (m *EnumOptions) GetAllowAlias() bool {
+ if m != nil && m.AllowAlias != nil {
+ return *m.AllowAlias
+ }
+ return false
+}
+
+func (m *EnumOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_EnumOptions_Deprecated
+}
+
+func (m *EnumOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type EnumValueOptions struct {
+ // Is this enum value deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum value, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating enum values.
+ Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
+func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) }
+func (*EnumValueOptions) ProtoMessage() {}
+func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{14} }
+
+var extRange_EnumValueOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumValueOptions
+}
+
+const Default_EnumValueOptions_Deprecated bool = false
+
+func (m *EnumValueOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_EnumValueOptions_Deprecated
+}
+
+func (m *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type ServiceOptions struct {
+ // Is this service deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the service, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating services.
+ Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
+func (m *ServiceOptions) String() string { return proto.CompactTextString(m) }
+func (*ServiceOptions) ProtoMessage() {}
+func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{15} }
+
+var extRange_ServiceOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ServiceOptions
+}
+
+const Default_ServiceOptions_Deprecated bool = false
+
+func (m *ServiceOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_ServiceOptions_Deprecated
+}
+
+func (m *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type MethodOptions struct {
+ // Is this method deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the method, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating methods.
+ Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MethodOptions) Reset() { *m = MethodOptions{} }
+func (m *MethodOptions) String() string { return proto.CompactTextString(m) }
+func (*MethodOptions) ProtoMessage() {}
+func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{16} }
+
+var extRange_MethodOptions = []proto.ExtensionRange{
+ {Start: 1000, End: 536870911},
+}
+
+func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MethodOptions
+}
+
+const Default_MethodOptions_Deprecated bool = false
+const Default_MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN
+
+func (m *MethodOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_MethodOptions_Deprecated
+}
+
+func (m *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel {
+ if m != nil && m.IdempotencyLevel != nil {
+ return *m.IdempotencyLevel
+ }
+ return Default_MethodOptions_IdempotencyLevel
+}
+
+func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+type UninterpretedOption struct {
+ Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"`
+ // The value of the uninterpreted option, in whatever type the tokenizer
+ // identified it as during parsing. Exactly one of these should be set.
+ IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"`
+ PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"`
+ NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"`
+ DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"`
+ StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"`
+ AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} }
+func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) }
+func (*UninterpretedOption) ProtoMessage() {}
+func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{17} }
+
+func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart {
+ if m != nil {
+ return m.Name
+ }
+ return nil
+}
+
+func (m *UninterpretedOption) GetIdentifierValue() string {
+ if m != nil && m.IdentifierValue != nil {
+ return *m.IdentifierValue
+ }
+ return ""
+}
+
+func (m *UninterpretedOption) GetPositiveIntValue() uint64 {
+ if m != nil && m.PositiveIntValue != nil {
+ return *m.PositiveIntValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetNegativeIntValue() int64 {
+ if m != nil && m.NegativeIntValue != nil {
+ return *m.NegativeIntValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetDoubleValue() float64 {
+ if m != nil && m.DoubleValue != nil {
+ return *m.DoubleValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetStringValue() []byte {
+ if m != nil {
+ return m.StringValue
+ }
+ return nil
+}
+
+func (m *UninterpretedOption) GetAggregateValue() string {
+ if m != nil && m.AggregateValue != nil {
+ return *m.AggregateValue
+ }
+ return ""
+}
+
+// The name of the uninterpreted option. Each string represents a segment in
+// a dot-separated name. is_extension is true iff a segment represents an
+// extension (denoted with parentheses in options specs in .proto files).
+// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+// "foo.(bar.baz).qux".
+type UninterpretedOption_NamePart struct {
+ NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"`
+ IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOption_NamePart{} }
+func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) }
+func (*UninterpretedOption_NamePart) ProtoMessage() {}
+func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{17, 0}
+}
+
+func (m *UninterpretedOption_NamePart) GetNamePart() string {
+ if m != nil && m.NamePart != nil {
+ return *m.NamePart
+ }
+ return ""
+}
+
+func (m *UninterpretedOption_NamePart) GetIsExtension() bool {
+ if m != nil && m.IsExtension != nil {
+ return *m.IsExtension
+ }
+ return false
+}
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+type SourceCodeInfo struct {
+ // A Location identifies a piece of source code in a .proto file which
+ // corresponds to a particular definition. This information is intended
+ // to be useful to IDEs, code indexers, documentation generators, and similar
+ // tools.
+ //
+ // For example, say we have a file like:
+ // message Foo {
+ // optional string foo = 1;
+ // }
+ // Let's look at just the field definition:
+ // optional string foo = 1;
+ // ^ ^^ ^^ ^ ^^^
+ // a bc de f ghi
+ // We have the following locations:
+ // span path represents
+ // [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ //
+ // Notes:
+ // - A location may refer to a repeated field itself (i.e. not to any
+ // particular index within it). This is used whenever a set of elements are
+ // logically enclosed in a single code segment. For example, an entire
+ // extend block (possibly containing multiple extension definitions) will
+ // have an outer location whose path refers to the "extensions" repeated
+ // field without an index.
+ // - Multiple locations may have the same path. This happens when a single
+ // logical declaration is spread out across multiple places. The most
+ // obvious example is the "extend" block again -- there may be multiple
+ // extend blocks in the same scope, each of which will have the same path.
+ // - A location's span is not always a subset of its parent's span. For
+ // example, the "extendee" of an extension declaration appears at the
+ // beginning of the "extend" block and is shared by all extensions within
+ // the block.
+ // - Just because a location's span is a subset of some other location's span
+ // does not mean that it is a descendent. For example, a "group" defines
+ // both a type and a field in a single declaration. Thus, the locations
+ // corresponding to the type and field and their components will overlap.
+ // - Code which tries to interpret locations should probably be designed to
+ // ignore those that it doesn't understand, as more types of locations could
+ // be recorded in the future.
+ Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} }
+func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) }
+func (*SourceCodeInfo) ProtoMessage() {}
+func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{18} }
+
+func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
+ if m != nil {
+ return m.Location
+ }
+ return nil
+}
+
+type SourceCodeInfo_Location struct {
+ // Identifies which part of the FileDescriptorProto was defined at this
+ // location.
+ //
+ // Each element is a field number or an index. They form a path from
+ // the root FileDescriptorProto to the place where the definition. For
+ // example, this path:
+ // [ 4, 3, 2, 7, 1 ]
+ // refers to:
+ // file.message_type(3) // 4, 3
+ // .field(7) // 2, 7
+ // .name() // 1
+ // This is because FileDescriptorProto.message_type has field number 4:
+ // repeated DescriptorProto message_type = 4;
+ // and DescriptorProto.field has field number 2:
+ // repeated FieldDescriptorProto field = 2;
+ // and FieldDescriptorProto.name has field number 1:
+ // optional string name = 1;
+ //
+ // Thus, the above path gives the location of a field name. If we removed
+ // the last element:
+ // [ 4, 3, 2, 7 ]
+ // this path refers to the whole field declaration (from the beginning
+ // of the label to the terminating semicolon).
+ Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"`
+ // Always has exactly three or four elements: start line, start column,
+ // end line (optional, otherwise assumed same as start line), end column.
+ // These are packed into a single field for efficiency. Note that line
+ // and column numbers are zero-based -- typically you will want to add
+ // 1 to each before displaying to a user.
+ Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"`
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // leading_detached_comments will keep paragraphs of comments that appear
+ // before (but not connected to) the current element. Each paragraph,
+ // separated by empty lines, will be one comment element in the repeated
+ // field.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // // Detached comment for corge. This is not leading or trailing comments
+ // // to qux or corge because there are blank lines separating it from
+ // // both.
+ //
+ // // Detached comment for corge paragraph 2.
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ //
+ // // ignored detached comments.
+ LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"`
+ TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"`
+ LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} }
+func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) }
+func (*SourceCodeInfo_Location) ProtoMessage() {}
+func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{18, 0}
+}
+
+func (m *SourceCodeInfo_Location) GetPath() []int32 {
+ if m != nil {
+ return m.Path
+ }
+ return nil
+}
+
+func (m *SourceCodeInfo_Location) GetSpan() []int32 {
+ if m != nil {
+ return m.Span
+ }
+ return nil
+}
+
+func (m *SourceCodeInfo_Location) GetLeadingComments() string {
+ if m != nil && m.LeadingComments != nil {
+ return *m.LeadingComments
+ }
+ return ""
+}
+
+func (m *SourceCodeInfo_Location) GetTrailingComments() string {
+ if m != nil && m.TrailingComments != nil {
+ return *m.TrailingComments
+ }
+ return ""
+}
+
+func (m *SourceCodeInfo_Location) GetLeadingDetachedComments() []string {
+ if m != nil {
+ return m.LeadingDetachedComments
+ }
+ return nil
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+type GeneratedCodeInfo struct {
+ // An Annotation connects some span of text in generated code to an element
+ // of its generating .proto file.
+ Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} }
+func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) }
+func (*GeneratedCodeInfo) ProtoMessage() {}
+func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptorDescriptor, []int{19} }
+
+func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
+ if m != nil {
+ return m.Annotation
+ }
+ return nil
+}
+
+type GeneratedCodeInfo_Annotation struct {
+ // Identifies the element in the original source .proto file. This field
+ // is formatted the same as SourceCodeInfo.Location.path.
+ Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"`
+ // Identifies the filesystem path to the original source .proto.
+ SourceFile *string `protobuf:"bytes,2,opt,name=source_file,json=sourceFile" json:"source_file,omitempty"`
+ // Identifies the starting offset in bytes in the generated code
+ // that relates to the identified object.
+ Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"`
+ // Identifies the ending offset in bytes in the generated code that
+ // relates to the identified offset. The end offset should be one past
+ // the last relevant byte (so the length of the text = end - begin).
+ End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_Annotation{} }
+func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) }
+func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
+func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
+ return fileDescriptorDescriptor, []int{19, 0}
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 {
+ if m != nil {
+ return m.Path
+ }
+ return nil
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetSourceFile() string {
+ if m != nil && m.SourceFile != nil {
+ return *m.SourceFile
+ }
+ return ""
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetBegin() int32 {
+ if m != nil && m.Begin != nil {
+ return *m.Begin
+ }
+ return 0
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*FileDescriptorSet)(nil), "google.protobuf.FileDescriptorSet")
+ proto.RegisterType((*FileDescriptorProto)(nil), "google.protobuf.FileDescriptorProto")
+ proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto")
+ proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
+ proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
+ proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
+ proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
+ proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
+ proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto")
+ proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto")
+ proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto")
+ proto.RegisterType((*FileOptions)(nil), "google.protobuf.FileOptions")
+ proto.RegisterType((*MessageOptions)(nil), "google.protobuf.MessageOptions")
+ proto.RegisterType((*FieldOptions)(nil), "google.protobuf.FieldOptions")
+ proto.RegisterType((*OneofOptions)(nil), "google.protobuf.OneofOptions")
+ proto.RegisterType((*EnumOptions)(nil), "google.protobuf.EnumOptions")
+ proto.RegisterType((*EnumValueOptions)(nil), "google.protobuf.EnumValueOptions")
+ proto.RegisterType((*ServiceOptions)(nil), "google.protobuf.ServiceOptions")
+ proto.RegisterType((*MethodOptions)(nil), "google.protobuf.MethodOptions")
+ proto.RegisterType((*UninterpretedOption)(nil), "google.protobuf.UninterpretedOption")
+ proto.RegisterType((*UninterpretedOption_NamePart)(nil), "google.protobuf.UninterpretedOption.NamePart")
+ proto.RegisterType((*SourceCodeInfo)(nil), "google.protobuf.SourceCodeInfo")
+ proto.RegisterType((*SourceCodeInfo_Location)(nil), "google.protobuf.SourceCodeInfo.Location")
+ proto.RegisterType((*GeneratedCodeInfo)(nil), "google.protobuf.GeneratedCodeInfo")
+ proto.RegisterType((*GeneratedCodeInfo_Annotation)(nil), "google.protobuf.GeneratedCodeInfo.Annotation")
+ proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value)
+ proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value)
+ proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
+ proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
+ proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value)
+ proto.RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", MethodOptions_IdempotencyLevel_name, MethodOptions_IdempotencyLevel_value)
+}
+
+func init() { proto.RegisterFile("descriptor.proto", fileDescriptorDescriptor) }
+
+var fileDescriptorDescriptor = []byte{
+ // 2379 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xcd, 0x73, 0xdb, 0xc6,
+ 0x15, 0x37, 0xc1, 0x0f, 0x91, 0x8f, 0x14, 0xb5, 0x5a, 0x29, 0x36, 0x2c, 0xc7, 0xb1, 0xcc, 0xd8,
+ 0xb5, 0x6c, 0xb7, 0x74, 0x46, 0xfe, 0x88, 0xa3, 0x74, 0xd2, 0xa1, 0x48, 0x58, 0xa1, 0x4b, 0x91,
+ 0x2c, 0x48, 0x35, 0x76, 0x2e, 0x98, 0x15, 0xb0, 0xa4, 0x60, 0x83, 0x00, 0x02, 0x80, 0xb6, 0x95,
+ 0x93, 0x67, 0x7a, 0xea, 0x7f, 0xd0, 0xe9, 0x74, 0x7a, 0xc8, 0x25, 0x33, 0xed, 0xbd, 0x87, 0xde,
+ 0x7b, 0xed, 0x4c, 0xef, 0x3d, 0xf4, 0xd0, 0x99, 0xf6, 0x3f, 0xe8, 0xb5, 0xb3, 0xbb, 0x00, 0x08,
+ 0x7e, 0xd9, 0x4a, 0x66, 0x9c, 0x9c, 0xa4, 0xfd, 0xbd, 0xdf, 0x7b, 0x78, 0xfb, 0xf6, 0x87, 0xdd,
+ 0x87, 0x25, 0x20, 0x83, 0xfa, 0xba, 0x67, 0xba, 0x81, 0xe3, 0x55, 0x5d, 0xcf, 0x09, 0x1c, 0xbc,
+ 0x36, 0x74, 0x9c, 0xa1, 0x45, 0xc5, 0xe8, 0x78, 0x3c, 0xa8, 0x1c, 0xc2, 0xfa, 0x23, 0xd3, 0xa2,
+ 0x8d, 0x98, 0xd8, 0xa3, 0x01, 0x7e, 0x08, 0x99, 0x81, 0x69, 0x51, 0x39, 0xb5, 0x9d, 0xde, 0x29,
+ 0xee, 0x5e, 0xab, 0xce, 0x38, 0x55, 0xa7, 0x3d, 0xba, 0x0c, 0x56, 0xb9, 0x47, 0xe5, 0xdf, 0x19,
+ 0xd8, 0x58, 0x60, 0xc5, 0x18, 0x32, 0x36, 0x19, 0xb1, 0x88, 0xa9, 0x9d, 0x82, 0xca, 0xff, 0xc7,
+ 0x32, 0xac, 0xb8, 0x44, 0x7f, 0x4e, 0x86, 0x54, 0x96, 0x38, 0x1c, 0x0d, 0xf1, 0x07, 0x00, 0x06,
+ 0x75, 0xa9, 0x6d, 0x50, 0x5b, 0x3f, 0x95, 0xd3, 0xdb, 0xe9, 0x9d, 0x82, 0x9a, 0x40, 0xf0, 0x6d,
+ 0x58, 0x77, 0xc7, 0xc7, 0x96, 0xa9, 0x6b, 0x09, 0x1a, 0x6c, 0xa7, 0x77, 0xb2, 0x2a, 0x12, 0x86,
+ 0xc6, 0x84, 0x7c, 0x03, 0xd6, 0x5e, 0x52, 0xf2, 0x3c, 0x49, 0x2d, 0x72, 0x6a, 0x99, 0xc1, 0x09,
+ 0x62, 0x1d, 0x4a, 0x23, 0xea, 0xfb, 0x64, 0x48, 0xb5, 0xe0, 0xd4, 0xa5, 0x72, 0x86, 0xcf, 0x7e,
+ 0x7b, 0x6e, 0xf6, 0xb3, 0x33, 0x2f, 0x86, 0x5e, 0xfd, 0x53, 0x97, 0xe2, 0x1a, 0x14, 0xa8, 0x3d,
+ 0x1e, 0x89, 0x08, 0xd9, 0x25, 0xf5, 0x53, 0xec, 0xf1, 0x68, 0x36, 0x4a, 0x9e, 0xb9, 0x85, 0x21,
+ 0x56, 0x7c, 0xea, 0xbd, 0x30, 0x75, 0x2a, 0xe7, 0x78, 0x80, 0x1b, 0x73, 0x01, 0x7a, 0xc2, 0x3e,
+ 0x1b, 0x23, 0xf2, 0xc3, 0x75, 0x28, 0xd0, 0x57, 0x01, 0xb5, 0x7d, 0xd3, 0xb1, 0xe5, 0x15, 0x1e,
+ 0xe4, 0xfa, 0x82, 0x55, 0xa4, 0x96, 0x31, 0x1b, 0x62, 0xe2, 0x87, 0x1f, 0xc0, 0x8a, 0xe3, 0x06,
+ 0xa6, 0x63, 0xfb, 0x72, 0x7e, 0x3b, 0xb5, 0x53, 0xdc, 0x7d, 0x7f, 0xa1, 0x10, 0x3a, 0x82, 0xa3,
+ 0x46, 0x64, 0xdc, 0x04, 0xe4, 0x3b, 0x63, 0x4f, 0xa7, 0x9a, 0xee, 0x18, 0x54, 0x33, 0xed, 0x81,
+ 0x23, 0x17, 0x78, 0x80, 0x2b, 0xf3, 0x13, 0xe1, 0xc4, 0xba, 0x63, 0xd0, 0xa6, 0x3d, 0x70, 0xd4,
+ 0xb2, 0x3f, 0x35, 0xc6, 0xe7, 0x21, 0xe7, 0x9f, 0xda, 0x01, 0x79, 0x25, 0x97, 0xb8, 0x42, 0xc2,
+ 0x51, 0xe5, 0x7f, 0x59, 0x58, 0x3b, 0x8b, 0xc4, 0x3e, 0x85, 0xec, 0x80, 0xcd, 0x52, 0x96, 0xbe,
+ 0x4b, 0x0d, 0x84, 0xcf, 0x74, 0x11, 0x73, 0xdf, 0xb3, 0x88, 0x35, 0x28, 0xda, 0xd4, 0x0f, 0xa8,
+ 0x21, 0x14, 0x91, 0x3e, 0xa3, 0xa6, 0x40, 0x38, 0xcd, 0x4b, 0x2a, 0xf3, 0xbd, 0x24, 0xf5, 0x04,
+ 0xd6, 0xe2, 0x94, 0x34, 0x8f, 0xd8, 0xc3, 0x48, 0x9b, 0x77, 0xde, 0x96, 0x49, 0x55, 0x89, 0xfc,
+ 0x54, 0xe6, 0xa6, 0x96, 0xe9, 0xd4, 0x18, 0x37, 0x00, 0x1c, 0x9b, 0x3a, 0x03, 0xcd, 0xa0, 0xba,
+ 0x25, 0xe7, 0x97, 0x54, 0xa9, 0xc3, 0x28, 0x73, 0x55, 0x72, 0x04, 0xaa, 0x5b, 0xf8, 0x93, 0x89,
+ 0xd4, 0x56, 0x96, 0x28, 0xe5, 0x50, 0xbc, 0x64, 0x73, 0x6a, 0x3b, 0x82, 0xb2, 0x47, 0x99, 0xee,
+ 0xa9, 0x11, 0xce, 0xac, 0xc0, 0x93, 0xa8, 0xbe, 0x75, 0x66, 0x6a, 0xe8, 0x26, 0x26, 0xb6, 0xea,
+ 0x25, 0x87, 0xf8, 0x43, 0x88, 0x01, 0x8d, 0xcb, 0x0a, 0xf8, 0x2e, 0x54, 0x8a, 0xc0, 0x36, 0x19,
+ 0xd1, 0xad, 0x87, 0x50, 0x9e, 0x2e, 0x0f, 0xde, 0x84, 0xac, 0x1f, 0x10, 0x2f, 0xe0, 0x2a, 0xcc,
+ 0xaa, 0x62, 0x80, 0x11, 0xa4, 0xa9, 0x6d, 0xf0, 0x5d, 0x2e, 0xab, 0xb2, 0x7f, 0xb7, 0x3e, 0x86,
+ 0xd5, 0xa9, 0xc7, 0x9f, 0xd5, 0xb1, 0xf2, 0xbb, 0x1c, 0x6c, 0x2e, 0xd2, 0xdc, 0x42, 0xf9, 0x9f,
+ 0x87, 0x9c, 0x3d, 0x1e, 0x1d, 0x53, 0x4f, 0x4e, 0xf3, 0x08, 0xe1, 0x08, 0xd7, 0x20, 0x6b, 0x91,
+ 0x63, 0x6a, 0xc9, 0x99, 0xed, 0xd4, 0x4e, 0x79, 0xf7, 0xf6, 0x99, 0x54, 0x5d, 0x6d, 0x31, 0x17,
+ 0x55, 0x78, 0xe2, 0xcf, 0x20, 0x13, 0x6e, 0x71, 0x2c, 0xc2, 0xad, 0xb3, 0x45, 0x60, 0x5a, 0x54,
+ 0xb9, 0x1f, 0xbe, 0x04, 0x05, 0xf6, 0x57, 0xd4, 0x36, 0xc7, 0x73, 0xce, 0x33, 0x80, 0xd5, 0x15,
+ 0x6f, 0x41, 0x9e, 0xcb, 0xcc, 0xa0, 0xd1, 0xd1, 0x10, 0x8f, 0xd9, 0xc2, 0x18, 0x74, 0x40, 0xc6,
+ 0x56, 0xa0, 0xbd, 0x20, 0xd6, 0x98, 0x72, 0xc1, 0x14, 0xd4, 0x52, 0x08, 0xfe, 0x9a, 0x61, 0xf8,
+ 0x0a, 0x14, 0x85, 0x2a, 0x4d, 0xdb, 0xa0, 0xaf, 0xf8, 0xee, 0x93, 0x55, 0x85, 0x50, 0x9b, 0x0c,
+ 0x61, 0x8f, 0x7f, 0xe6, 0x3b, 0x76, 0xb4, 0xb4, 0xfc, 0x11, 0x0c, 0xe0, 0x8f, 0xff, 0x78, 0x76,
+ 0xe3, 0xbb, 0xbc, 0x78, 0x7a, 0xb3, 0x5a, 0xac, 0xfc, 0x45, 0x82, 0x0c, 0x7f, 0xdf, 0xd6, 0xa0,
+ 0xd8, 0x7f, 0xda, 0x55, 0xb4, 0x46, 0xe7, 0x68, 0xbf, 0xa5, 0xa0, 0x14, 0x2e, 0x03, 0x70, 0xe0,
+ 0x51, 0xab, 0x53, 0xeb, 0x23, 0x29, 0x1e, 0x37, 0xdb, 0xfd, 0x07, 0xf7, 0x50, 0x3a, 0x76, 0x38,
+ 0x12, 0x40, 0x26, 0x49, 0xb8, 0xbb, 0x8b, 0xb2, 0x18, 0x41, 0x49, 0x04, 0x68, 0x3e, 0x51, 0x1a,
+ 0x0f, 0xee, 0xa1, 0xdc, 0x34, 0x72, 0x77, 0x17, 0xad, 0xe0, 0x55, 0x28, 0x70, 0x64, 0xbf, 0xd3,
+ 0x69, 0xa1, 0x7c, 0x1c, 0xb3, 0xd7, 0x57, 0x9b, 0xed, 0x03, 0x54, 0x88, 0x63, 0x1e, 0xa8, 0x9d,
+ 0xa3, 0x2e, 0x82, 0x38, 0xc2, 0xa1, 0xd2, 0xeb, 0xd5, 0x0e, 0x14, 0x54, 0x8c, 0x19, 0xfb, 0x4f,
+ 0xfb, 0x4a, 0x0f, 0x95, 0xa6, 0xd2, 0xba, 0xbb, 0x8b, 0x56, 0xe3, 0x47, 0x28, 0xed, 0xa3, 0x43,
+ 0x54, 0xc6, 0xeb, 0xb0, 0x2a, 0x1e, 0x11, 0x25, 0xb1, 0x36, 0x03, 0x3d, 0xb8, 0x87, 0xd0, 0x24,
+ 0x11, 0x11, 0x65, 0x7d, 0x0a, 0x78, 0x70, 0x0f, 0xe1, 0x4a, 0x1d, 0xb2, 0x5c, 0x5d, 0x18, 0x43,
+ 0xb9, 0x55, 0xdb, 0x57, 0x5a, 0x5a, 0xa7, 0xdb, 0x6f, 0x76, 0xda, 0xb5, 0x16, 0x4a, 0x4d, 0x30,
+ 0x55, 0xf9, 0xd5, 0x51, 0x53, 0x55, 0x1a, 0x48, 0x4a, 0x62, 0x5d, 0xa5, 0xd6, 0x57, 0x1a, 0x28,
+ 0x5d, 0xd1, 0x61, 0x73, 0xd1, 0x3e, 0xb3, 0xf0, 0xcd, 0x48, 0x2c, 0xb1, 0xb4, 0x64, 0x89, 0x79,
+ 0xac, 0xb9, 0x25, 0xfe, 0x26, 0x05, 0x1b, 0x0b, 0xf6, 0xda, 0x85, 0x0f, 0xf9, 0x05, 0x64, 0x85,
+ 0x44, 0xc5, 0xe9, 0x73, 0x73, 0xe1, 0xa6, 0xcd, 0x05, 0x3b, 0x77, 0x02, 0x71, 0xbf, 0xe4, 0x09,
+ 0x9c, 0x5e, 0x72, 0x02, 0xb3, 0x10, 0x73, 0x49, 0xfe, 0x26, 0x05, 0xf2, 0xb2, 0xd8, 0x6f, 0xd9,
+ 0x28, 0xa4, 0xa9, 0x8d, 0xe2, 0xd3, 0xd9, 0x04, 0xae, 0x2e, 0x9f, 0xc3, 0x5c, 0x16, 0xdf, 0xa6,
+ 0xe0, 0xfc, 0xe2, 0x46, 0x65, 0x61, 0x0e, 0x9f, 0x41, 0x6e, 0x44, 0x83, 0x13, 0x27, 0x3a, 0xac,
+ 0x7f, 0xb2, 0xe0, 0x08, 0x60, 0xe6, 0xd9, 0x5a, 0x85, 0x5e, 0xc9, 0x33, 0x24, 0xbd, 0xac, 0xdb,
+ 0x10, 0xd9, 0xcc, 0x65, 0xfa, 0x5b, 0x09, 0xde, 0x5b, 0x18, 0x7c, 0x61, 0xa2, 0x97, 0x01, 0x4c,
+ 0xdb, 0x1d, 0x07, 0xe2, 0x40, 0x16, 0xfb, 0x53, 0x81, 0x23, 0xfc, 0xdd, 0x67, 0x7b, 0xcf, 0x38,
+ 0x88, 0xed, 0x69, 0x6e, 0x07, 0x01, 0x71, 0xc2, 0xc3, 0x49, 0xa2, 0x19, 0x9e, 0xe8, 0x07, 0x4b,
+ 0x66, 0x3a, 0x77, 0xd6, 0x7d, 0x04, 0x48, 0xb7, 0x4c, 0x6a, 0x07, 0x9a, 0x1f, 0x78, 0x94, 0x8c,
+ 0x4c, 0x7b, 0xc8, 0x37, 0xe0, 0xfc, 0x5e, 0x76, 0x40, 0x2c, 0x9f, 0xaa, 0x6b, 0xc2, 0xdc, 0x8b,
+ 0xac, 0xcc, 0x83, 0x9f, 0x32, 0x5e, 0xc2, 0x23, 0x37, 0xe5, 0x21, 0xcc, 0xb1, 0x47, 0xe5, 0xcf,
+ 0x2b, 0x50, 0x4c, 0xb4, 0x75, 0xf8, 0x2a, 0x94, 0x9e, 0x91, 0x17, 0x44, 0x8b, 0x5a, 0x75, 0x51,
+ 0x89, 0x22, 0xc3, 0xba, 0x61, 0xbb, 0xfe, 0x11, 0x6c, 0x72, 0x8a, 0x33, 0x0e, 0xa8, 0xa7, 0xe9,
+ 0x16, 0xf1, 0x7d, 0x5e, 0xb4, 0x3c, 0xa7, 0x62, 0x66, 0xeb, 0x30, 0x53, 0x3d, 0xb2, 0xe0, 0xfb,
+ 0xb0, 0xc1, 0x3d, 0x46, 0x63, 0x2b, 0x30, 0x5d, 0x8b, 0x6a, 0xec, 0xe3, 0xc1, 0xe7, 0x1b, 0x71,
+ 0x9c, 0xd9, 0x3a, 0x63, 0x1c, 0x86, 0x04, 0x96, 0x91, 0x8f, 0x1b, 0x70, 0x99, 0xbb, 0x0d, 0xa9,
+ 0x4d, 0x3d, 0x12, 0x50, 0x8d, 0x7e, 0x35, 0x26, 0x96, 0xaf, 0x11, 0xdb, 0xd0, 0x4e, 0x88, 0x7f,
+ 0x22, 0x6f, 0xb2, 0x00, 0xfb, 0x92, 0x9c, 0x52, 0x2f, 0x32, 0xe2, 0x41, 0xc8, 0x53, 0x38, 0xad,
+ 0x66, 0x1b, 0x9f, 0x13, 0xff, 0x04, 0xef, 0xc1, 0x79, 0x1e, 0xc5, 0x0f, 0x3c, 0xd3, 0x1e, 0x6a,
+ 0xfa, 0x09, 0xd5, 0x9f, 0x6b, 0xe3, 0x60, 0xf0, 0x50, 0xbe, 0x94, 0x7c, 0x3e, 0xcf, 0xb0, 0xc7,
+ 0x39, 0x75, 0x46, 0x39, 0x0a, 0x06, 0x0f, 0x71, 0x0f, 0x4a, 0x6c, 0x31, 0x46, 0xe6, 0xd7, 0x54,
+ 0x1b, 0x38, 0x1e, 0x3f, 0x59, 0xca, 0x0b, 0xde, 0xec, 0x44, 0x05, 0xab, 0x9d, 0xd0, 0xe1, 0xd0,
+ 0x31, 0xe8, 0x5e, 0xb6, 0xd7, 0x55, 0x94, 0x86, 0x5a, 0x8c, 0xa2, 0x3c, 0x72, 0x3c, 0x26, 0xa8,
+ 0xa1, 0x13, 0x17, 0xb8, 0x28, 0x04, 0x35, 0x74, 0xa2, 0xf2, 0xde, 0x87, 0x0d, 0x5d, 0x17, 0x73,
+ 0x36, 0x75, 0x2d, 0x6c, 0xf1, 0x7d, 0x19, 0x4d, 0x15, 0x4b, 0xd7, 0x0f, 0x04, 0x21, 0xd4, 0xb8,
+ 0x8f, 0x3f, 0x81, 0xf7, 0x26, 0xc5, 0x4a, 0x3a, 0xae, 0xcf, 0xcd, 0x72, 0xd6, 0xf5, 0x3e, 0x6c,
+ 0xb8, 0xa7, 0xf3, 0x8e, 0x78, 0xea, 0x89, 0xee, 0xe9, 0xac, 0xdb, 0x75, 0xfe, 0xd9, 0xe6, 0x51,
+ 0x9d, 0x04, 0xd4, 0x90, 0x2f, 0x24, 0xd9, 0x09, 0x03, 0xbe, 0x03, 0x48, 0xd7, 0x35, 0x6a, 0x93,
+ 0x63, 0x8b, 0x6a, 0xc4, 0xa3, 0x36, 0xf1, 0xe5, 0x2b, 0x49, 0x72, 0x59, 0xd7, 0x15, 0x6e, 0xad,
+ 0x71, 0x23, 0xbe, 0x05, 0xeb, 0xce, 0xf1, 0x33, 0x5d, 0x28, 0x4b, 0x73, 0x3d, 0x3a, 0x30, 0x5f,
+ 0xc9, 0xd7, 0x78, 0x99, 0xd6, 0x98, 0x81, 0xeb, 0xaa, 0xcb, 0x61, 0x7c, 0x13, 0x90, 0xee, 0x9f,
+ 0x10, 0xcf, 0xe5, 0x47, 0xbb, 0xef, 0x12, 0x9d, 0xca, 0xd7, 0x05, 0x55, 0xe0, 0xed, 0x08, 0x66,
+ 0xca, 0xf6, 0x5f, 0x9a, 0x83, 0x20, 0x8a, 0x78, 0x43, 0x28, 0x9b, 0x63, 0x61, 0xb4, 0x27, 0xb0,
+ 0x39, 0xb6, 0x4d, 0x3b, 0xa0, 0x9e, 0xeb, 0x51, 0xd6, 0xc4, 0x8b, 0x37, 0x51, 0xfe, 0xcf, 0xca,
+ 0x92, 0x36, 0xfc, 0x28, 0xc9, 0x16, 0x02, 0x50, 0x37, 0xc6, 0xf3, 0x60, 0x65, 0x0f, 0x4a, 0x49,
+ 0x5d, 0xe0, 0x02, 0x08, 0x65, 0xa0, 0x14, 0x3b, 0x63, 0xeb, 0x9d, 0x06, 0x3b, 0x1d, 0xbf, 0x54,
+ 0x90, 0xc4, 0x4e, 0xe9, 0x56, 0xb3, 0xaf, 0x68, 0xea, 0x51, 0xbb, 0xdf, 0x3c, 0x54, 0x50, 0xfa,
+ 0x56, 0x21, 0xff, 0xdf, 0x15, 0xf4, 0xfa, 0xf5, 0xeb, 0xd7, 0x52, 0xe5, 0x6f, 0x12, 0x94, 0xa7,
+ 0x3b, 0x63, 0xfc, 0x73, 0xb8, 0x10, 0x7d, 0xc6, 0xfa, 0x34, 0xd0, 0x5e, 0x9a, 0x1e, 0x97, 0xea,
+ 0x88, 0x88, 0xde, 0x32, 0xae, 0xf2, 0x66, 0xc8, 0xea, 0xd1, 0xe0, 0x0b, 0xd3, 0x63, 0x42, 0x1c,
+ 0x91, 0x00, 0xb7, 0xe0, 0x8a, 0xed, 0x68, 0x7e, 0x40, 0x6c, 0x83, 0x78, 0x86, 0x36, 0xb9, 0x40,
+ 0xd0, 0x88, 0xae, 0x53, 0xdf, 0x77, 0xc4, 0x11, 0x11, 0x47, 0x79, 0xdf, 0x76, 0x7a, 0x21, 0x79,
+ 0xb2, 0x77, 0xd6, 0x42, 0xea, 0x8c, 0x22, 0xd2, 0xcb, 0x14, 0x71, 0x09, 0x0a, 0x23, 0xe2, 0x6a,
+ 0xd4, 0x0e, 0xbc, 0x53, 0xde, 0xcf, 0xe5, 0xd5, 0xfc, 0x88, 0xb8, 0x0a, 0x1b, 0xbf, 0xbb, 0x35,
+ 0x48, 0xd6, 0xf1, 0x9f, 0x69, 0x28, 0x25, 0x7b, 0x3a, 0xd6, 0x22, 0xeb, 0x7c, 0xff, 0x4e, 0xf1,
+ 0x37, 0xfc, 0xc3, 0x37, 0x76, 0x80, 0xd5, 0x3a, 0xdb, 0xd8, 0xf7, 0x72, 0xa2, 0xd3, 0x52, 0x85,
+ 0x27, 0x3b, 0x54, 0xd9, 0x3b, 0x4d, 0x45, 0xff, 0x9e, 0x57, 0xc3, 0x11, 0x3e, 0x80, 0xdc, 0x33,
+ 0x9f, 0xc7, 0xce, 0xf1, 0xd8, 0xd7, 0xde, 0x1c, 0xfb, 0x71, 0x8f, 0x07, 0x2f, 0x3c, 0xee, 0x69,
+ 0xed, 0x8e, 0x7a, 0x58, 0x6b, 0xa9, 0xa1, 0x3b, 0xbe, 0x08, 0x19, 0x8b, 0x7c, 0x7d, 0x3a, 0x7d,
+ 0x04, 0x70, 0xe8, 0xac, 0x85, 0xbf, 0x08, 0x99, 0x97, 0x94, 0x3c, 0x9f, 0xde, 0x78, 0x39, 0xf4,
+ 0x0e, 0xa5, 0x7f, 0x07, 0xb2, 0xbc, 0x5e, 0x18, 0x20, 0xac, 0x18, 0x3a, 0x87, 0xf3, 0x90, 0xa9,
+ 0x77, 0x54, 0x26, 0x7f, 0x04, 0x25, 0x81, 0x6a, 0xdd, 0xa6, 0x52, 0x57, 0x90, 0x54, 0xb9, 0x0f,
+ 0x39, 0x51, 0x04, 0xf6, 0x6a, 0xc4, 0x65, 0x40, 0xe7, 0xc2, 0x61, 0x18, 0x23, 0x15, 0x59, 0x8f,
+ 0x0e, 0xf7, 0x15, 0x15, 0x49, 0xc9, 0xe5, 0xf5, 0xa1, 0x94, 0x6c, 0xe7, 0x7e, 0x18, 0x4d, 0xfd,
+ 0x35, 0x05, 0xc5, 0x44, 0x7b, 0xc6, 0x1a, 0x03, 0x62, 0x59, 0xce, 0x4b, 0x8d, 0x58, 0x26, 0xf1,
+ 0x43, 0x51, 0x00, 0x87, 0x6a, 0x0c, 0x39, 0xeb, 0xa2, 0xfd, 0x20, 0xc9, 0xff, 0x31, 0x05, 0x68,
+ 0xb6, 0xb5, 0x9b, 0x49, 0x30, 0xf5, 0xa3, 0x26, 0xf8, 0x87, 0x14, 0x94, 0xa7, 0xfb, 0xb9, 0x99,
+ 0xf4, 0xae, 0xfe, 0xa8, 0xe9, 0xfd, 0x4b, 0x82, 0xd5, 0xa9, 0x2e, 0xee, 0xac, 0xd9, 0x7d, 0x05,
+ 0xeb, 0xa6, 0x41, 0x47, 0xae, 0x13, 0x50, 0x5b, 0x3f, 0xd5, 0x2c, 0xfa, 0x82, 0x5a, 0x72, 0x85,
+ 0x6f, 0x14, 0x77, 0xde, 0xdc, 0x27, 0x56, 0x9b, 0x13, 0xbf, 0x16, 0x73, 0xdb, 0xdb, 0x68, 0x36,
+ 0x94, 0xc3, 0x6e, 0xa7, 0xaf, 0xb4, 0xeb, 0x4f, 0xb5, 0xa3, 0xf6, 0x2f, 0xdb, 0x9d, 0x2f, 0xda,
+ 0x2a, 0x32, 0x67, 0x68, 0xef, 0xf0, 0x55, 0xef, 0x02, 0x9a, 0x4d, 0x0a, 0x5f, 0x80, 0x45, 0x69,
+ 0xa1, 0x73, 0x78, 0x03, 0xd6, 0xda, 0x1d, 0xad, 0xd7, 0x6c, 0x28, 0x9a, 0xf2, 0xe8, 0x91, 0x52,
+ 0xef, 0xf7, 0xc4, 0x87, 0x73, 0xcc, 0xee, 0x4f, 0xbf, 0xd4, 0xbf, 0x4f, 0xc3, 0xc6, 0x82, 0x4c,
+ 0x70, 0x2d, 0xec, 0xd9, 0xc5, 0x67, 0xc4, 0xcf, 0xce, 0x92, 0x7d, 0x95, 0x75, 0x05, 0x5d, 0xe2,
+ 0x05, 0x61, 0x8b, 0x7f, 0x13, 0x58, 0x95, 0xec, 0xc0, 0x1c, 0x98, 0xd4, 0x0b, 0xef, 0x19, 0x44,
+ 0x23, 0xbf, 0x36, 0xc1, 0xc5, 0x55, 0xc3, 0x4f, 0x01, 0xbb, 0x8e, 0x6f, 0x06, 0xe6, 0x0b, 0xaa,
+ 0x99, 0x76, 0x74, 0x29, 0xc1, 0x1a, 0xfb, 0x8c, 0x8a, 0x22, 0x4b, 0xd3, 0x0e, 0x62, 0xb6, 0x4d,
+ 0x87, 0x64, 0x86, 0xcd, 0x36, 0xf0, 0xb4, 0x8a, 0x22, 0x4b, 0xcc, 0xbe, 0x0a, 0x25, 0xc3, 0x19,
+ 0xb3, 0x36, 0x49, 0xf0, 0xd8, 0x79, 0x91, 0x52, 0x8b, 0x02, 0x8b, 0x29, 0x61, 0x1f, 0x3b, 0xb9,
+ 0x0d, 0x29, 0xa9, 0x45, 0x81, 0x09, 0xca, 0x0d, 0x58, 0x23, 0xc3, 0xa1, 0xc7, 0x82, 0x47, 0x81,
+ 0x44, 0x67, 0x5e, 0x8e, 0x61, 0x4e, 0xdc, 0x7a, 0x0c, 0xf9, 0xa8, 0x0e, 0xec, 0x48, 0x66, 0x95,
+ 0xd0, 0x5c, 0x71, 0x27, 0x25, 0xed, 0x14, 0xd4, 0xbc, 0x1d, 0x19, 0xaf, 0x42, 0xc9, 0xf4, 0xb5,
+ 0xc9, 0xe5, 0xa8, 0xb4, 0x2d, 0xed, 0xe4, 0xd5, 0xa2, 0xe9, 0xc7, 0xb7, 0x61, 0x95, 0x6f, 0x25,
+ 0x28, 0x4f, 0x5f, 0xee, 0xe2, 0x06, 0xe4, 0x2d, 0x47, 0x27, 0x5c, 0x5a, 0xe2, 0x97, 0x85, 0x9d,
+ 0xb7, 0xdc, 0x07, 0x57, 0x5b, 0x21, 0x5f, 0x8d, 0x3d, 0xb7, 0xfe, 0x9e, 0x82, 0x7c, 0x04, 0xe3,
+ 0xf3, 0x90, 0x71, 0x49, 0x70, 0xc2, 0xc3, 0x65, 0xf7, 0x25, 0x94, 0x52, 0xf9, 0x98, 0xe1, 0xbe,
+ 0x4b, 0x6c, 0x2e, 0x81, 0x10, 0x67, 0x63, 0xb6, 0xae, 0x16, 0x25, 0x06, 0x6f, 0xfb, 0x9d, 0xd1,
+ 0x88, 0xda, 0x81, 0x1f, 0xad, 0x6b, 0x88, 0xd7, 0x43, 0x18, 0xdf, 0x86, 0xf5, 0xc0, 0x23, 0xa6,
+ 0x35, 0xc5, 0xcd, 0x70, 0x2e, 0x8a, 0x0c, 0x31, 0x79, 0x0f, 0x2e, 0x46, 0x71, 0x0d, 0x1a, 0x10,
+ 0xfd, 0x84, 0x1a, 0x13, 0xa7, 0x1c, 0xbf, 0x39, 0xbc, 0x10, 0x12, 0x1a, 0xa1, 0x3d, 0xf2, 0xad,
+ 0xfc, 0x23, 0x05, 0xeb, 0xd1, 0x87, 0x8a, 0x11, 0x17, 0xeb, 0x10, 0x80, 0xd8, 0xb6, 0x13, 0x24,
+ 0xcb, 0x35, 0x2f, 0xe5, 0x39, 0xbf, 0x6a, 0x2d, 0x76, 0x52, 0x13, 0x01, 0xb6, 0x46, 0x00, 0x13,
+ 0xcb, 0xd2, 0xb2, 0x5d, 0x81, 0x62, 0x78, 0x73, 0xcf, 0x7f, 0xfe, 0x11, 0x9f, 0xb6, 0x20, 0x20,
+ 0xf6, 0x45, 0x83, 0x37, 0x21, 0x7b, 0x4c, 0x87, 0xa6, 0x1d, 0xde, 0x27, 0x8a, 0x41, 0x74, 0x4b,
+ 0x99, 0x89, 0x6f, 0x29, 0xf7, 0x9f, 0xc0, 0x86, 0xee, 0x8c, 0x66, 0xd3, 0xdd, 0x47, 0x33, 0x9f,
+ 0xd7, 0xfe, 0xe7, 0xa9, 0x2f, 0x61, 0xd2, 0x62, 0x7e, 0x23, 0xa5, 0x0f, 0xba, 0xfb, 0x7f, 0x92,
+ 0xb6, 0x0e, 0x84, 0x5f, 0x37, 0x9a, 0xa6, 0x4a, 0x07, 0x16, 0xd5, 0x59, 0xea, 0xff, 0x0f, 0x00,
+ 0x00, 0xff, 0xff, 0xa0, 0xbf, 0x63, 0x15, 0xd3, 0x1a, 0x00, 0x00,
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor_gostring.gen.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor_gostring.gen.go
new file mode 100644
index 00000000..bac9913e
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor_gostring.gen.go
@@ -0,0 +1,721 @@
+// Code generated by protoc-gen-gogo.
+// source: descriptor.proto
+// DO NOT EDIT!
+
+/*
+Package descriptor is a generated protocol buffer package.
+
+It is generated from these files:
+ descriptor.proto
+
+It has these top-level messages:
+ FileDescriptorSet
+ FileDescriptorProto
+ DescriptorProto
+ FieldDescriptorProto
+ OneofDescriptorProto
+ EnumDescriptorProto
+ EnumValueDescriptorProto
+ ServiceDescriptorProto
+ MethodDescriptorProto
+ FileOptions
+ MessageOptions
+ FieldOptions
+ OneofOptions
+ EnumOptions
+ EnumValueOptions
+ ServiceOptions
+ MethodOptions
+ UninterpretedOption
+ SourceCodeInfo
+ GeneratedCodeInfo
+*/
+package descriptor
+
+import fmt "fmt"
+import strings "strings"
+import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
+import sort "sort"
+import strconv "strconv"
+import reflect "reflect"
+import proto "github.com/gogo/protobuf/proto"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+func (this *FileDescriptorSet) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.FileDescriptorSet{")
+ if this.File != nil {
+ s = append(s, "File: "+fmt.Sprintf("%#v", this.File)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FileDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 16)
+ s = append(s, "&descriptor.FileDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Package != nil {
+ s = append(s, "Package: "+valueToGoStringDescriptor(this.Package, "string")+",\n")
+ }
+ if this.Dependency != nil {
+ s = append(s, "Dependency: "+fmt.Sprintf("%#v", this.Dependency)+",\n")
+ }
+ if this.PublicDependency != nil {
+ s = append(s, "PublicDependency: "+fmt.Sprintf("%#v", this.PublicDependency)+",\n")
+ }
+ if this.WeakDependency != nil {
+ s = append(s, "WeakDependency: "+fmt.Sprintf("%#v", this.WeakDependency)+",\n")
+ }
+ if this.MessageType != nil {
+ s = append(s, "MessageType: "+fmt.Sprintf("%#v", this.MessageType)+",\n")
+ }
+ if this.EnumType != nil {
+ s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
+ }
+ if this.Service != nil {
+ s = append(s, "Service: "+fmt.Sprintf("%#v", this.Service)+",\n")
+ }
+ if this.Extension != nil {
+ s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.SourceCodeInfo != nil {
+ s = append(s, "SourceCodeInfo: "+fmt.Sprintf("%#v", this.SourceCodeInfo)+",\n")
+ }
+ if this.Syntax != nil {
+ s = append(s, "Syntax: "+valueToGoStringDescriptor(this.Syntax, "string")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *DescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 14)
+ s = append(s, "&descriptor.DescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Field != nil {
+ s = append(s, "Field: "+fmt.Sprintf("%#v", this.Field)+",\n")
+ }
+ if this.Extension != nil {
+ s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
+ }
+ if this.NestedType != nil {
+ s = append(s, "NestedType: "+fmt.Sprintf("%#v", this.NestedType)+",\n")
+ }
+ if this.EnumType != nil {
+ s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
+ }
+ if this.ExtensionRange != nil {
+ s = append(s, "ExtensionRange: "+fmt.Sprintf("%#v", this.ExtensionRange)+",\n")
+ }
+ if this.OneofDecl != nil {
+ s = append(s, "OneofDecl: "+fmt.Sprintf("%#v", this.OneofDecl)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.ReservedRange != nil {
+ s = append(s, "ReservedRange: "+fmt.Sprintf("%#v", this.ReservedRange)+",\n")
+ }
+ if this.ReservedName != nil {
+ s = append(s, "ReservedName: "+fmt.Sprintf("%#v", this.ReservedName)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *DescriptorProto_ExtensionRange) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.DescriptorProto_ExtensionRange{")
+ if this.Start != nil {
+ s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
+ }
+ if this.End != nil {
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *DescriptorProto_ReservedRange) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.DescriptorProto_ReservedRange{")
+ if this.Start != nil {
+ s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
+ }
+ if this.End != nil {
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FieldDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 14)
+ s = append(s, "&descriptor.FieldDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Number != nil {
+ s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n")
+ }
+ if this.Label != nil {
+ s = append(s, "Label: "+valueToGoStringDescriptor(this.Label, "descriptor.FieldDescriptorProto_Label")+",\n")
+ }
+ if this.Type != nil {
+ s = append(s, "Type: "+valueToGoStringDescriptor(this.Type, "descriptor.FieldDescriptorProto_Type")+",\n")
+ }
+ if this.TypeName != nil {
+ s = append(s, "TypeName: "+valueToGoStringDescriptor(this.TypeName, "string")+",\n")
+ }
+ if this.Extendee != nil {
+ s = append(s, "Extendee: "+valueToGoStringDescriptor(this.Extendee, "string")+",\n")
+ }
+ if this.DefaultValue != nil {
+ s = append(s, "DefaultValue: "+valueToGoStringDescriptor(this.DefaultValue, "string")+",\n")
+ }
+ if this.OneofIndex != nil {
+ s = append(s, "OneofIndex: "+valueToGoStringDescriptor(this.OneofIndex, "int32")+",\n")
+ }
+ if this.JsonName != nil {
+ s = append(s, "JsonName: "+valueToGoStringDescriptor(this.JsonName, "string")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *OneofDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.OneofDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.EnumDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Value != nil {
+ s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumValueDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.EnumValueDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Number != nil {
+ s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *ServiceDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.ServiceDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.Method != nil {
+ s = append(s, "Method: "+fmt.Sprintf("%#v", this.Method)+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *MethodDescriptorProto) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 10)
+ s = append(s, "&descriptor.MethodDescriptorProto{")
+ if this.Name != nil {
+ s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
+ }
+ if this.InputType != nil {
+ s = append(s, "InputType: "+valueToGoStringDescriptor(this.InputType, "string")+",\n")
+ }
+ if this.OutputType != nil {
+ s = append(s, "OutputType: "+valueToGoStringDescriptor(this.OutputType, "string")+",\n")
+ }
+ if this.Options != nil {
+ s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
+ }
+ if this.ClientStreaming != nil {
+ s = append(s, "ClientStreaming: "+valueToGoStringDescriptor(this.ClientStreaming, "bool")+",\n")
+ }
+ if this.ServerStreaming != nil {
+ s = append(s, "ServerStreaming: "+valueToGoStringDescriptor(this.ServerStreaming, "bool")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FileOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 20)
+ s = append(s, "&descriptor.FileOptions{")
+ if this.JavaPackage != nil {
+ s = append(s, "JavaPackage: "+valueToGoStringDescriptor(this.JavaPackage, "string")+",\n")
+ }
+ if this.JavaOuterClassname != nil {
+ s = append(s, "JavaOuterClassname: "+valueToGoStringDescriptor(this.JavaOuterClassname, "string")+",\n")
+ }
+ if this.JavaMultipleFiles != nil {
+ s = append(s, "JavaMultipleFiles: "+valueToGoStringDescriptor(this.JavaMultipleFiles, "bool")+",\n")
+ }
+ if this.JavaGenerateEqualsAndHash != nil {
+ s = append(s, "JavaGenerateEqualsAndHash: "+valueToGoStringDescriptor(this.JavaGenerateEqualsAndHash, "bool")+",\n")
+ }
+ if this.JavaStringCheckUtf8 != nil {
+ s = append(s, "JavaStringCheckUtf8: "+valueToGoStringDescriptor(this.JavaStringCheckUtf8, "bool")+",\n")
+ }
+ if this.OptimizeFor != nil {
+ s = append(s, "OptimizeFor: "+valueToGoStringDescriptor(this.OptimizeFor, "descriptor.FileOptions_OptimizeMode")+",\n")
+ }
+ if this.GoPackage != nil {
+ s = append(s, "GoPackage: "+valueToGoStringDescriptor(this.GoPackage, "string")+",\n")
+ }
+ if this.CcGenericServices != nil {
+ s = append(s, "CcGenericServices: "+valueToGoStringDescriptor(this.CcGenericServices, "bool")+",\n")
+ }
+ if this.JavaGenericServices != nil {
+ s = append(s, "JavaGenericServices: "+valueToGoStringDescriptor(this.JavaGenericServices, "bool")+",\n")
+ }
+ if this.PyGenericServices != nil {
+ s = append(s, "PyGenericServices: "+valueToGoStringDescriptor(this.PyGenericServices, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.CcEnableArenas != nil {
+ s = append(s, "CcEnableArenas: "+valueToGoStringDescriptor(this.CcEnableArenas, "bool")+",\n")
+ }
+ if this.ObjcClassPrefix != nil {
+ s = append(s, "ObjcClassPrefix: "+valueToGoStringDescriptor(this.ObjcClassPrefix, "string")+",\n")
+ }
+ if this.CsharpNamespace != nil {
+ s = append(s, "CsharpNamespace: "+valueToGoStringDescriptor(this.CsharpNamespace, "string")+",\n")
+ }
+ if this.SwiftPrefix != nil {
+ s = append(s, "SwiftPrefix: "+valueToGoStringDescriptor(this.SwiftPrefix, "string")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *MessageOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 9)
+ s = append(s, "&descriptor.MessageOptions{")
+ if this.MessageSetWireFormat != nil {
+ s = append(s, "MessageSetWireFormat: "+valueToGoStringDescriptor(this.MessageSetWireFormat, "bool")+",\n")
+ }
+ if this.NoStandardDescriptorAccessor != nil {
+ s = append(s, "NoStandardDescriptorAccessor: "+valueToGoStringDescriptor(this.NoStandardDescriptorAccessor, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.MapEntry != nil {
+ s = append(s, "MapEntry: "+valueToGoStringDescriptor(this.MapEntry, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *FieldOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 11)
+ s = append(s, "&descriptor.FieldOptions{")
+ if this.Ctype != nil {
+ s = append(s, "Ctype: "+valueToGoStringDescriptor(this.Ctype, "descriptor.FieldOptions_CType")+",\n")
+ }
+ if this.Packed != nil {
+ s = append(s, "Packed: "+valueToGoStringDescriptor(this.Packed, "bool")+",\n")
+ }
+ if this.Jstype != nil {
+ s = append(s, "Jstype: "+valueToGoStringDescriptor(this.Jstype, "descriptor.FieldOptions_JSType")+",\n")
+ }
+ if this.Lazy != nil {
+ s = append(s, "Lazy: "+valueToGoStringDescriptor(this.Lazy, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.Weak != nil {
+ s = append(s, "Weak: "+valueToGoStringDescriptor(this.Weak, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *OneofOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.OneofOptions{")
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.EnumOptions{")
+ if this.AllowAlias != nil {
+ s = append(s, "AllowAlias: "+valueToGoStringDescriptor(this.AllowAlias, "bool")+",\n")
+ }
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *EnumValueOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.EnumValueOptions{")
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *ServiceOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.ServiceOptions{")
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *MethodOptions) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 7)
+ s = append(s, "&descriptor.MethodOptions{")
+ if this.Deprecated != nil {
+ s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
+ }
+ if this.IdempotencyLevel != nil {
+ s = append(s, "IdempotencyLevel: "+valueToGoStringDescriptor(this.IdempotencyLevel, "descriptor.MethodOptions_IdempotencyLevel")+",\n")
+ }
+ if this.UninterpretedOption != nil {
+ s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
+ }
+ s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *UninterpretedOption) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 11)
+ s = append(s, "&descriptor.UninterpretedOption{")
+ if this.Name != nil {
+ s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
+ }
+ if this.IdentifierValue != nil {
+ s = append(s, "IdentifierValue: "+valueToGoStringDescriptor(this.IdentifierValue, "string")+",\n")
+ }
+ if this.PositiveIntValue != nil {
+ s = append(s, "PositiveIntValue: "+valueToGoStringDescriptor(this.PositiveIntValue, "uint64")+",\n")
+ }
+ if this.NegativeIntValue != nil {
+ s = append(s, "NegativeIntValue: "+valueToGoStringDescriptor(this.NegativeIntValue, "int64")+",\n")
+ }
+ if this.DoubleValue != nil {
+ s = append(s, "DoubleValue: "+valueToGoStringDescriptor(this.DoubleValue, "float64")+",\n")
+ }
+ if this.StringValue != nil {
+ s = append(s, "StringValue: "+valueToGoStringDescriptor(this.StringValue, "byte")+",\n")
+ }
+ if this.AggregateValue != nil {
+ s = append(s, "AggregateValue: "+valueToGoStringDescriptor(this.AggregateValue, "string")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *UninterpretedOption_NamePart) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 6)
+ s = append(s, "&descriptor.UninterpretedOption_NamePart{")
+ if this.NamePart != nil {
+ s = append(s, "NamePart: "+valueToGoStringDescriptor(this.NamePart, "string")+",\n")
+ }
+ if this.IsExtension != nil {
+ s = append(s, "IsExtension: "+valueToGoStringDescriptor(this.IsExtension, "bool")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *SourceCodeInfo) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.SourceCodeInfo{")
+ if this.Location != nil {
+ s = append(s, "Location: "+fmt.Sprintf("%#v", this.Location)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *SourceCodeInfo_Location) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 9)
+ s = append(s, "&descriptor.SourceCodeInfo_Location{")
+ if this.Path != nil {
+ s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
+ }
+ if this.Span != nil {
+ s = append(s, "Span: "+fmt.Sprintf("%#v", this.Span)+",\n")
+ }
+ if this.LeadingComments != nil {
+ s = append(s, "LeadingComments: "+valueToGoStringDescriptor(this.LeadingComments, "string")+",\n")
+ }
+ if this.TrailingComments != nil {
+ s = append(s, "TrailingComments: "+valueToGoStringDescriptor(this.TrailingComments, "string")+",\n")
+ }
+ if this.LeadingDetachedComments != nil {
+ s = append(s, "LeadingDetachedComments: "+fmt.Sprintf("%#v", this.LeadingDetachedComments)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *GeneratedCodeInfo) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 5)
+ s = append(s, "&descriptor.GeneratedCodeInfo{")
+ if this.Annotation != nil {
+ s = append(s, "Annotation: "+fmt.Sprintf("%#v", this.Annotation)+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func (this *GeneratedCodeInfo_Annotation) GoString() string {
+ if this == nil {
+ return "nil"
+ }
+ s := make([]string, 0, 8)
+ s = append(s, "&descriptor.GeneratedCodeInfo_Annotation{")
+ if this.Path != nil {
+ s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
+ }
+ if this.SourceFile != nil {
+ s = append(s, "SourceFile: "+valueToGoStringDescriptor(this.SourceFile, "string")+",\n")
+ }
+ if this.Begin != nil {
+ s = append(s, "Begin: "+valueToGoStringDescriptor(this.Begin, "int32")+",\n")
+ }
+ if this.End != nil {
+ s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
+ }
+ if this.XXX_unrecognized != nil {
+ s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
+ }
+ s = append(s, "}")
+ return strings.Join(s, "")
+}
+func valueToGoStringDescriptor(v interface{}, typ string) string {
+ rv := reflect.ValueOf(v)
+ if rv.IsNil() {
+ return "nil"
+ }
+ pv := reflect.Indirect(rv).Interface()
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
+}
+func extensionToGoStringDescriptor(m github_com_gogo_protobuf_proto.Message) string {
+ e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m)
+ if e == nil {
+ return "nil"
+ }
+ s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"
+ keys := make([]int, 0, len(e))
+ for k := range e {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+ ss := []string{}
+ for _, k := range keys {
+ ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
+ }
+ s += strings.Join(ss, ",") + "})"
+ return s
+}
diff --git a/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go
new file mode 100644
index 00000000..e0846a35
--- /dev/null
+++ b/vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go
@@ -0,0 +1,390 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package descriptor
+
+import (
+ "strings"
+)
+
+func (msg *DescriptorProto) GetMapFields() (*FieldDescriptorProto, *FieldDescriptorProto) {
+ if !msg.GetOptions().GetMapEntry() {
+ return nil, nil
+ }
+ return msg.GetField()[0], msg.GetField()[1]
+}
+
+func dotToUnderscore(r rune) rune {
+ if r == '.' {
+ return '_'
+ }
+ return r
+}
+
+func (field *FieldDescriptorProto) WireType() (wire int) {
+ switch *field.Type {
+ case FieldDescriptorProto_TYPE_DOUBLE:
+ return 1
+ case FieldDescriptorProto_TYPE_FLOAT:
+ return 5
+ case FieldDescriptorProto_TYPE_INT64:
+ return 0
+ case FieldDescriptorProto_TYPE_UINT64:
+ return 0
+ case FieldDescriptorProto_TYPE_INT32:
+ return 0
+ case FieldDescriptorProto_TYPE_UINT32:
+ return 0
+ case FieldDescriptorProto_TYPE_FIXED64:
+ return 1
+ case FieldDescriptorProto_TYPE_FIXED32:
+ return 5
+ case FieldDescriptorProto_TYPE_BOOL:
+ return 0
+ case FieldDescriptorProto_TYPE_STRING:
+ return 2
+ case FieldDescriptorProto_TYPE_GROUP:
+ return 2
+ case FieldDescriptorProto_TYPE_MESSAGE:
+ return 2
+ case FieldDescriptorProto_TYPE_BYTES:
+ return 2
+ case FieldDescriptorProto_TYPE_ENUM:
+ return 0
+ case FieldDescriptorProto_TYPE_SFIXED32:
+ return 5
+ case FieldDescriptorProto_TYPE_SFIXED64:
+ return 1
+ case FieldDescriptorProto_TYPE_SINT32:
+ return 0
+ case FieldDescriptorProto_TYPE_SINT64:
+ return 0
+ }
+ panic("unreachable")
+}
+
+func (field *FieldDescriptorProto) GetKeyUint64() (x uint64) {
+ packed := field.IsPacked()
+ wireType := field.WireType()
+ fieldNumber := field.GetNumber()
+ if packed {
+ wireType = 2
+ }
+ x = uint64(uint32(fieldNumber)<<3 | uint32(wireType))
+ return x
+}
+
+func (field *FieldDescriptorProto) GetKey3Uint64() (x uint64) {
+ packed := field.IsPacked3()
+ wireType := field.WireType()
+ fieldNumber := field.GetNumber()
+ if packed {
+ wireType = 2
+ }
+ x = uint64(uint32(fieldNumber)<<3 | uint32(wireType))
+ return x
+}
+
+func (field *FieldDescriptorProto) GetKey() []byte {
+ x := field.GetKeyUint64()
+ i := 0
+ keybuf := make([]byte, 0)
+ for i = 0; x > 127; i++ {
+ keybuf = append(keybuf, 0x80|uint8(x&0x7F))
+ x >>= 7
+ }
+ keybuf = append(keybuf, uint8(x))
+ return keybuf
+}
+
+func (field *FieldDescriptorProto) GetKey3() []byte {
+ x := field.GetKey3Uint64()
+ i := 0
+ keybuf := make([]byte, 0)
+ for i = 0; x > 127; i++ {
+ keybuf = append(keybuf, 0x80|uint8(x&0x7F))
+ x >>= 7
+ }
+ keybuf = append(keybuf, uint8(x))
+ return keybuf
+}
+
+func (desc *FileDescriptorSet) GetField(packageName, messageName, fieldName string) *FieldDescriptorProto {
+ msg := desc.GetMessage(packageName, messageName)
+ if msg == nil {
+ return nil
+ }
+ for _, field := range msg.GetField() {
+ if field.GetName() == fieldName {
+ return field
+ }
+ }
+ return nil
+}
+
+func (file *FileDescriptorProto) GetMessage(typeName string) *DescriptorProto {
+ for _, msg := range file.GetMessageType() {
+ if msg.GetName() == typeName {
+ return msg
+ }
+ nes := file.GetNestedMessage(msg, strings.TrimPrefix(typeName, msg.GetName()+"."))
+ if nes != nil {
+ return nes
+ }
+ }
+ return nil
+}
+
+func (file *FileDescriptorProto) GetNestedMessage(msg *DescriptorProto, typeName string) *DescriptorProto {
+ for _, nes := range msg.GetNestedType() {
+ if nes.GetName() == typeName {
+ return nes
+ }
+ res := file.GetNestedMessage(nes, strings.TrimPrefix(typeName, nes.GetName()+"."))
+ if res != nil {
+ return res
+ }
+ }
+ return nil
+}
+
+func (desc *FileDescriptorSet) GetMessage(packageName string, typeName string) *DescriptorProto {
+ for _, file := range desc.GetFile() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
+ continue
+ }
+ for _, msg := range file.GetMessageType() {
+ if msg.GetName() == typeName {
+ return msg
+ }
+ }
+ for _, msg := range file.GetMessageType() {
+ for _, nes := range msg.GetNestedType() {
+ if nes.GetName() == typeName {
+ return nes
+ }
+ if msg.GetName()+"."+nes.GetName() == typeName {
+ return nes
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (desc *FileDescriptorSet) IsProto3(packageName string, typeName string) bool {
+ for _, file := range desc.GetFile() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
+ continue
+ }
+ for _, msg := range file.GetMessageType() {
+ if msg.GetName() == typeName {
+ return file.GetSyntax() == "proto3"
+ }
+ }
+ for _, msg := range file.GetMessageType() {
+ for _, nes := range msg.GetNestedType() {
+ if nes.GetName() == typeName {
+ return file.GetSyntax() == "proto3"
+ }
+ if msg.GetName()+"."+nes.GetName() == typeName {
+ return file.GetSyntax() == "proto3"
+ }
+ }
+ }
+ }
+ return false
+}
+
+func (msg *DescriptorProto) IsExtendable() bool {
+ return len(msg.GetExtensionRange()) > 0
+}
+
+func (desc *FileDescriptorSet) FindExtension(packageName string, typeName string, fieldName string) (extPackageName string, field *FieldDescriptorProto) {
+ parent := desc.GetMessage(packageName, typeName)
+ if parent == nil {
+ return "", nil
+ }
+ if !parent.IsExtendable() {
+ return "", nil
+ }
+ extendee := "." + packageName + "." + typeName
+ for _, file := range desc.GetFile() {
+ for _, ext := range file.GetExtension() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) {
+ if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) {
+ continue
+ }
+ } else {
+ if ext.GetExtendee() != extendee {
+ continue
+ }
+ }
+ if ext.GetName() == fieldName {
+ return file.GetPackage(), ext
+ }
+ }
+ }
+ return "", nil
+}
+
+func (desc *FileDescriptorSet) FindExtensionByFieldNumber(packageName string, typeName string, fieldNum int32) (extPackageName string, field *FieldDescriptorProto) {
+ parent := desc.GetMessage(packageName, typeName)
+ if parent == nil {
+ return "", nil
+ }
+ if !parent.IsExtendable() {
+ return "", nil
+ }
+ extendee := "." + packageName + "." + typeName
+ for _, file := range desc.GetFile() {
+ for _, ext := range file.GetExtension() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) {
+ if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) {
+ continue
+ }
+ } else {
+ if ext.GetExtendee() != extendee {
+ continue
+ }
+ }
+ if ext.GetNumber() == fieldNum {
+ return file.GetPackage(), ext
+ }
+ }
+ }
+ return "", nil
+}
+
+func (desc *FileDescriptorSet) FindMessage(packageName string, typeName string, fieldName string) (msgPackageName string, msgName string) {
+ parent := desc.GetMessage(packageName, typeName)
+ if parent == nil {
+ return "", ""
+ }
+ field := parent.GetFieldDescriptor(fieldName)
+ if field == nil {
+ var extPackageName string
+ extPackageName, field = desc.FindExtension(packageName, typeName, fieldName)
+ if field == nil {
+ return "", ""
+ }
+ packageName = extPackageName
+ }
+ typeNames := strings.Split(field.GetTypeName(), ".")
+ if len(typeNames) == 1 {
+ msg := desc.GetMessage(packageName, typeName)
+ if msg == nil {
+ return "", ""
+ }
+ return packageName, msg.GetName()
+ }
+ if len(typeNames) > 2 {
+ for i := 1; i < len(typeNames)-1; i++ {
+ packageName = strings.Join(typeNames[1:len(typeNames)-i], ".")
+ typeName = strings.Join(typeNames[len(typeNames)-i:], ".")
+ msg := desc.GetMessage(packageName, typeName)
+ if msg != nil {
+ typeNames := strings.Split(msg.GetName(), ".")
+ if len(typeNames) == 1 {
+ return packageName, msg.GetName()
+ }
+ return strings.Join(typeNames[1:len(typeNames)-1], "."), typeNames[len(typeNames)-1]
+ }
+ }
+ }
+ return "", ""
+}
+
+func (msg *DescriptorProto) GetFieldDescriptor(fieldName string) *FieldDescriptorProto {
+ for _, field := range msg.GetField() {
+ if field.GetName() == fieldName {
+ return field
+ }
+ }
+ return nil
+}
+
+func (desc *FileDescriptorSet) GetEnum(packageName string, typeName string) *EnumDescriptorProto {
+ for _, file := range desc.GetFile() {
+ if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
+ continue
+ }
+ for _, enum := range file.GetEnumType() {
+ if enum.GetName() == typeName {
+ return enum
+ }
+ }
+ }
+ return nil
+}
+
+func (f *FieldDescriptorProto) IsEnum() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_ENUM
+}
+
+func (f *FieldDescriptorProto) IsMessage() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_MESSAGE
+}
+
+func (f *FieldDescriptorProto) IsBytes() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_BYTES
+}
+
+func (f *FieldDescriptorProto) IsRepeated() bool {
+ return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REPEATED
+}
+
+func (f *FieldDescriptorProto) IsString() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_STRING
+}
+
+func (f *FieldDescriptorProto) IsBool() bool {
+ return *f.Type == FieldDescriptorProto_TYPE_BOOL
+}
+
+func (f *FieldDescriptorProto) IsRequired() bool {
+ return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REQUIRED
+}
+
+func (f *FieldDescriptorProto) IsPacked() bool {
+ return f.Options != nil && f.GetOptions().GetPacked()
+}
+
+func (f *FieldDescriptorProto) IsPacked3() bool {
+ if f.IsRepeated() && f.IsScalar() {
+ if f.Options == nil || f.GetOptions().Packed == nil {
+ return true
+ }
+ return f.Options != nil && f.GetOptions().GetPacked()
+ }
+ return false
+}
+
+func (m *DescriptorProto) HasExtension() bool {
+ return len(m.ExtensionRange) > 0
+}
diff --git a/vendor/github.com/gomodule/redigo/LICENSE b/vendor/github.com/gomodule/redigo/LICENSE
new file mode 100644
index 00000000..67db8588
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/LICENSE
@@ -0,0 +1,175 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/vendor/github.com/gomodule/redigo/internal/commandinfo.go b/vendor/github.com/gomodule/redigo/internal/commandinfo.go
new file mode 100644
index 00000000..b763efbd
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/internal/commandinfo.go
@@ -0,0 +1,54 @@
+// Copyright 2014 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package internal // import "github.com/gomodule/redigo/internal"
+
+import (
+ "strings"
+)
+
+const (
+ WatchState = 1 << iota
+ MultiState
+ SubscribeState
+ MonitorState
+)
+
+type CommandInfo struct {
+ Set, Clear int
+}
+
+var commandInfos = map[string]CommandInfo{
+ "WATCH": {Set: WatchState},
+ "UNWATCH": {Clear: WatchState},
+ "MULTI": {Set: MultiState},
+ "EXEC": {Clear: WatchState | MultiState},
+ "DISCARD": {Clear: WatchState | MultiState},
+ "PSUBSCRIBE": {Set: SubscribeState},
+ "SUBSCRIBE": {Set: SubscribeState},
+ "MONITOR": {Set: MonitorState},
+}
+
+func init() {
+ for n, ci := range commandInfos {
+ commandInfos[strings.ToLower(n)] = ci
+ }
+}
+
+func LookupCommandInfo(commandName string) CommandInfo {
+ if ci, ok := commandInfos[commandName]; ok {
+ return ci
+ }
+ return commandInfos[strings.ToUpper(commandName)]
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/conn.go b/vendor/github.com/gomodule/redigo/redis/conn.go
new file mode 100644
index 00000000..5aa0f32f
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/conn.go
@@ -0,0 +1,673 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "net/url"
+ "regexp"
+ "strconv"
+ "sync"
+ "time"
+)
+
+var (
+ _ ConnWithTimeout = (*conn)(nil)
+)
+
+// conn is the low-level implementation of Conn
+type conn struct {
+ // Shared
+ mu sync.Mutex
+ pending int
+ err error
+ conn net.Conn
+
+ // Read
+ readTimeout time.Duration
+ br *bufio.Reader
+
+ // Write
+ writeTimeout time.Duration
+ bw *bufio.Writer
+
+ // Scratch space for formatting argument length.
+ // '*' or '$', length, "\r\n"
+ lenScratch [32]byte
+
+ // Scratch space for formatting integers and floats.
+ numScratch [40]byte
+}
+
+// DialTimeout acts like Dial but takes timeouts for establishing the
+// connection to the server, writing a command and reading a reply.
+//
+// Deprecated: Use Dial with options instead.
+func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error) {
+ return Dial(network, address,
+ DialConnectTimeout(connectTimeout),
+ DialReadTimeout(readTimeout),
+ DialWriteTimeout(writeTimeout))
+}
+
+// DialOption specifies an option for dialing a Redis server.
+type DialOption struct {
+ f func(*dialOptions)
+}
+
+type dialOptions struct {
+ readTimeout time.Duration
+ writeTimeout time.Duration
+ dialer *net.Dialer
+ dial func(network, addr string) (net.Conn, error)
+ db int
+ password string
+ useTLS bool
+ skipVerify bool
+ tlsConfig *tls.Config
+}
+
+// DialReadTimeout specifies the timeout for reading a single command reply.
+func DialReadTimeout(d time.Duration) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.readTimeout = d
+ }}
+}
+
+// DialWriteTimeout specifies the timeout for writing a single command.
+func DialWriteTimeout(d time.Duration) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.writeTimeout = d
+ }}
+}
+
+// DialConnectTimeout specifies the timeout for connecting to the Redis server when
+// no DialNetDial option is specified.
+func DialConnectTimeout(d time.Duration) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.dialer.Timeout = d
+ }}
+}
+
+// DialKeepAlive specifies the keep-alive period for TCP connections to the Redis server
+// when no DialNetDial option is specified.
+// If zero, keep-alives are not enabled. If no DialKeepAlive option is specified then
+// the default of 5 minutes is used to ensure that half-closed TCP sessions are detected.
+func DialKeepAlive(d time.Duration) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.dialer.KeepAlive = d
+ }}
+}
+
+// DialNetDial specifies a custom dial function for creating TCP
+// connections, otherwise a net.Dialer customized via the other options is used.
+// DialNetDial overrides DialConnectTimeout and DialKeepAlive.
+func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.dial = dial
+ }}
+}
+
+// DialDatabase specifies the database to select when dialing a connection.
+func DialDatabase(db int) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.db = db
+ }}
+}
+
+// DialPassword specifies the password to use when connecting to
+// the Redis server.
+func DialPassword(password string) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.password = password
+ }}
+}
+
+// DialTLSConfig specifies the config to use when a TLS connection is dialed.
+// Has no effect when not dialing a TLS connection.
+func DialTLSConfig(c *tls.Config) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.tlsConfig = c
+ }}
+}
+
+// DialTLSSkipVerify disables server name verification when connecting over
+// TLS. Has no effect when not dialing a TLS connection.
+func DialTLSSkipVerify(skip bool) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.skipVerify = skip
+ }}
+}
+
+// DialUseTLS specifies whether TLS should be used when connecting to the
+// server. This option is ignore by DialURL.
+func DialUseTLS(useTLS bool) DialOption {
+ return DialOption{func(do *dialOptions) {
+ do.useTLS = useTLS
+ }}
+}
+
+// Dial connects to the Redis server at the given network and
+// address using the specified options.
+func Dial(network, address string, options ...DialOption) (Conn, error) {
+ do := dialOptions{
+ dialer: &net.Dialer{
+ KeepAlive: time.Minute * 5,
+ },
+ }
+ for _, option := range options {
+ option.f(&do)
+ }
+ if do.dial == nil {
+ do.dial = do.dialer.Dial
+ }
+
+ netConn, err := do.dial(network, address)
+ if err != nil {
+ return nil, err
+ }
+
+ if do.useTLS {
+ var tlsConfig *tls.Config
+ if do.tlsConfig == nil {
+ tlsConfig = &tls.Config{InsecureSkipVerify: do.skipVerify}
+ } else {
+ tlsConfig = cloneTLSConfig(do.tlsConfig)
+ }
+ if tlsConfig.ServerName == "" {
+ host, _, err := net.SplitHostPort(address)
+ if err != nil {
+ netConn.Close()
+ return nil, err
+ }
+ tlsConfig.ServerName = host
+ }
+
+ tlsConn := tls.Client(netConn, tlsConfig)
+ if err := tlsConn.Handshake(); err != nil {
+ netConn.Close()
+ return nil, err
+ }
+ netConn = tlsConn
+ }
+
+ c := &conn{
+ conn: netConn,
+ bw: bufio.NewWriter(netConn),
+ br: bufio.NewReader(netConn),
+ readTimeout: do.readTimeout,
+ writeTimeout: do.writeTimeout,
+ }
+
+ if do.password != "" {
+ if _, err := c.Do("AUTH", do.password); err != nil {
+ netConn.Close()
+ return nil, err
+ }
+ }
+
+ if do.db != 0 {
+ if _, err := c.Do("SELECT", do.db); err != nil {
+ netConn.Close()
+ return nil, err
+ }
+ }
+
+ return c, nil
+}
+
+var pathDBRegexp = regexp.MustCompile(`/(\d*)\z`)
+
+// DialURL connects to a Redis server at the given URL using the Redis
+// URI scheme. URLs should follow the draft IANA specification for the
+// scheme (https://www.iana.org/assignments/uri-schemes/prov/redis).
+func DialURL(rawurl string, options ...DialOption) (Conn, error) {
+ u, err := url.Parse(rawurl)
+ if err != nil {
+ return nil, err
+ }
+
+ if u.Scheme != "redis" && u.Scheme != "rediss" {
+ return nil, fmt.Errorf("invalid redis URL scheme: %s", u.Scheme)
+ }
+
+ // As per the IANA draft spec, the host defaults to localhost and
+ // the port defaults to 6379.
+ host, port, err := net.SplitHostPort(u.Host)
+ if err != nil {
+ // assume port is missing
+ host = u.Host
+ port = "6379"
+ }
+ if host == "" {
+ host = "localhost"
+ }
+ address := net.JoinHostPort(host, port)
+
+ if u.User != nil {
+ password, isSet := u.User.Password()
+ if isSet {
+ options = append(options, DialPassword(password))
+ }
+ }
+
+ match := pathDBRegexp.FindStringSubmatch(u.Path)
+ if len(match) == 2 {
+ db := 0
+ if len(match[1]) > 0 {
+ db, err = strconv.Atoi(match[1])
+ if err != nil {
+ return nil, fmt.Errorf("invalid database: %s", u.Path[1:])
+ }
+ }
+ if db != 0 {
+ options = append(options, DialDatabase(db))
+ }
+ } else if u.Path != "" {
+ return nil, fmt.Errorf("invalid database: %s", u.Path[1:])
+ }
+
+ options = append(options, DialUseTLS(u.Scheme == "rediss"))
+
+ return Dial("tcp", address, options...)
+}
+
+// NewConn returns a new Redigo connection for the given net connection.
+func NewConn(netConn net.Conn, readTimeout, writeTimeout time.Duration) Conn {
+ return &conn{
+ conn: netConn,
+ bw: bufio.NewWriter(netConn),
+ br: bufio.NewReader(netConn),
+ readTimeout: readTimeout,
+ writeTimeout: writeTimeout,
+ }
+}
+
+func (c *conn) Close() error {
+ c.mu.Lock()
+ err := c.err
+ if c.err == nil {
+ c.err = errors.New("redigo: closed")
+ err = c.conn.Close()
+ }
+ c.mu.Unlock()
+ return err
+}
+
+func (c *conn) fatal(err error) error {
+ c.mu.Lock()
+ if c.err == nil {
+ c.err = err
+ // Close connection to force errors on subsequent calls and to unblock
+ // other reader or writer.
+ c.conn.Close()
+ }
+ c.mu.Unlock()
+ return err
+}
+
+func (c *conn) Err() error {
+ c.mu.Lock()
+ err := c.err
+ c.mu.Unlock()
+ return err
+}
+
+func (c *conn) writeLen(prefix byte, n int) error {
+ c.lenScratch[len(c.lenScratch)-1] = '\n'
+ c.lenScratch[len(c.lenScratch)-2] = '\r'
+ i := len(c.lenScratch) - 3
+ for {
+ c.lenScratch[i] = byte('0' + n%10)
+ i -= 1
+ n = n / 10
+ if n == 0 {
+ break
+ }
+ }
+ c.lenScratch[i] = prefix
+ _, err := c.bw.Write(c.lenScratch[i:])
+ return err
+}
+
+func (c *conn) writeString(s string) error {
+ c.writeLen('$', len(s))
+ c.bw.WriteString(s)
+ _, err := c.bw.WriteString("\r\n")
+ return err
+}
+
+func (c *conn) writeBytes(p []byte) error {
+ c.writeLen('$', len(p))
+ c.bw.Write(p)
+ _, err := c.bw.WriteString("\r\n")
+ return err
+}
+
+func (c *conn) writeInt64(n int64) error {
+ return c.writeBytes(strconv.AppendInt(c.numScratch[:0], n, 10))
+}
+
+func (c *conn) writeFloat64(n float64) error {
+ return c.writeBytes(strconv.AppendFloat(c.numScratch[:0], n, 'g', -1, 64))
+}
+
+func (c *conn) writeCommand(cmd string, args []interface{}) error {
+ c.writeLen('*', 1+len(args))
+ if err := c.writeString(cmd); err != nil {
+ return err
+ }
+ for _, arg := range args {
+ if err := c.writeArg(arg, true); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (c *conn) writeArg(arg interface{}, argumentTypeOK bool) (err error) {
+ switch arg := arg.(type) {
+ case string:
+ return c.writeString(arg)
+ case []byte:
+ return c.writeBytes(arg)
+ case int:
+ return c.writeInt64(int64(arg))
+ case int64:
+ return c.writeInt64(arg)
+ case float64:
+ return c.writeFloat64(arg)
+ case bool:
+ if arg {
+ return c.writeString("1")
+ } else {
+ return c.writeString("0")
+ }
+ case nil:
+ return c.writeString("")
+ case Argument:
+ if argumentTypeOK {
+ return c.writeArg(arg.RedisArg(), false)
+ }
+ // See comment in default clause below.
+ var buf bytes.Buffer
+ fmt.Fprint(&buf, arg)
+ return c.writeBytes(buf.Bytes())
+ default:
+ // This default clause is intended to handle builtin numeric types.
+ // The function should return an error for other types, but this is not
+ // done for compatibility with previous versions of the package.
+ var buf bytes.Buffer
+ fmt.Fprint(&buf, arg)
+ return c.writeBytes(buf.Bytes())
+ }
+}
+
+type protocolError string
+
+func (pe protocolError) Error() string {
+ return fmt.Sprintf("redigo: %s (possible server error or unsupported concurrent read by application)", string(pe))
+}
+
+func (c *conn) readLine() ([]byte, error) {
+ p, err := c.br.ReadSlice('\n')
+ if err == bufio.ErrBufferFull {
+ return nil, protocolError("long response line")
+ }
+ if err != nil {
+ return nil, err
+ }
+ i := len(p) - 2
+ if i < 0 || p[i] != '\r' {
+ return nil, protocolError("bad response line terminator")
+ }
+ return p[:i], nil
+}
+
+// parseLen parses bulk string and array lengths.
+func parseLen(p []byte) (int, error) {
+ if len(p) == 0 {
+ return -1, protocolError("malformed length")
+ }
+
+ if p[0] == '-' && len(p) == 2 && p[1] == '1' {
+ // handle $-1 and $-1 null replies.
+ return -1, nil
+ }
+
+ var n int
+ for _, b := range p {
+ n *= 10
+ if b < '0' || b > '9' {
+ return -1, protocolError("illegal bytes in length")
+ }
+ n += int(b - '0')
+ }
+
+ return n, nil
+}
+
+// parseInt parses an integer reply.
+func parseInt(p []byte) (interface{}, error) {
+ if len(p) == 0 {
+ return 0, protocolError("malformed integer")
+ }
+
+ var negate bool
+ if p[0] == '-' {
+ negate = true
+ p = p[1:]
+ if len(p) == 0 {
+ return 0, protocolError("malformed integer")
+ }
+ }
+
+ var n int64
+ for _, b := range p {
+ n *= 10
+ if b < '0' || b > '9' {
+ return 0, protocolError("illegal bytes in length")
+ }
+ n += int64(b - '0')
+ }
+
+ if negate {
+ n = -n
+ }
+ return n, nil
+}
+
+var (
+ okReply interface{} = "OK"
+ pongReply interface{} = "PONG"
+)
+
+func (c *conn) readReply() (interface{}, error) {
+ line, err := c.readLine()
+ if err != nil {
+ return nil, err
+ }
+ if len(line) == 0 {
+ return nil, protocolError("short response line")
+ }
+ switch line[0] {
+ case '+':
+ switch {
+ case len(line) == 3 && line[1] == 'O' && line[2] == 'K':
+ // Avoid allocation for frequent "+OK" response.
+ return okReply, nil
+ case len(line) == 5 && line[1] == 'P' && line[2] == 'O' && line[3] == 'N' && line[4] == 'G':
+ // Avoid allocation in PING command benchmarks :)
+ return pongReply, nil
+ default:
+ return string(line[1:]), nil
+ }
+ case '-':
+ return Error(string(line[1:])), nil
+ case ':':
+ return parseInt(line[1:])
+ case '$':
+ n, err := parseLen(line[1:])
+ if n < 0 || err != nil {
+ return nil, err
+ }
+ p := make([]byte, n)
+ _, err = io.ReadFull(c.br, p)
+ if err != nil {
+ return nil, err
+ }
+ if line, err := c.readLine(); err != nil {
+ return nil, err
+ } else if len(line) != 0 {
+ return nil, protocolError("bad bulk string format")
+ }
+ return p, nil
+ case '*':
+ n, err := parseLen(line[1:])
+ if n < 0 || err != nil {
+ return nil, err
+ }
+ r := make([]interface{}, n)
+ for i := range r {
+ r[i], err = c.readReply()
+ if err != nil {
+ return nil, err
+ }
+ }
+ return r, nil
+ }
+ return nil, protocolError("unexpected response line")
+}
+
+func (c *conn) Send(cmd string, args ...interface{}) error {
+ c.mu.Lock()
+ c.pending += 1
+ c.mu.Unlock()
+ if c.writeTimeout != 0 {
+ c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
+ }
+ if err := c.writeCommand(cmd, args); err != nil {
+ return c.fatal(err)
+ }
+ return nil
+}
+
+func (c *conn) Flush() error {
+ if c.writeTimeout != 0 {
+ c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
+ }
+ if err := c.bw.Flush(); err != nil {
+ return c.fatal(err)
+ }
+ return nil
+}
+
+func (c *conn) Receive() (interface{}, error) {
+ return c.ReceiveWithTimeout(c.readTimeout)
+}
+
+func (c *conn) ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err error) {
+ var deadline time.Time
+ if timeout != 0 {
+ deadline = time.Now().Add(timeout)
+ }
+ c.conn.SetReadDeadline(deadline)
+
+ if reply, err = c.readReply(); err != nil {
+ return nil, c.fatal(err)
+ }
+ // When using pub/sub, the number of receives can be greater than the
+ // number of sends. To enable normal use of the connection after
+ // unsubscribing from all channels, we do not decrement pending to a
+ // negative value.
+ //
+ // The pending field is decremented after the reply is read to handle the
+ // case where Receive is called before Send.
+ c.mu.Lock()
+ if c.pending > 0 {
+ c.pending -= 1
+ }
+ c.mu.Unlock()
+ if err, ok := reply.(Error); ok {
+ return nil, err
+ }
+ return
+}
+
+func (c *conn) Do(cmd string, args ...interface{}) (interface{}, error) {
+ return c.DoWithTimeout(c.readTimeout, cmd, args...)
+}
+
+func (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...interface{}) (interface{}, error) {
+ c.mu.Lock()
+ pending := c.pending
+ c.pending = 0
+ c.mu.Unlock()
+
+ if cmd == "" && pending == 0 {
+ return nil, nil
+ }
+
+ if c.writeTimeout != 0 {
+ c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
+ }
+
+ if cmd != "" {
+ if err := c.writeCommand(cmd, args); err != nil {
+ return nil, c.fatal(err)
+ }
+ }
+
+ if err := c.bw.Flush(); err != nil {
+ return nil, c.fatal(err)
+ }
+
+ var deadline time.Time
+ if readTimeout != 0 {
+ deadline = time.Now().Add(readTimeout)
+ }
+ c.conn.SetReadDeadline(deadline)
+
+ if cmd == "" {
+ reply := make([]interface{}, pending)
+ for i := range reply {
+ r, e := c.readReply()
+ if e != nil {
+ return nil, c.fatal(e)
+ }
+ reply[i] = r
+ }
+ return reply, nil
+ }
+
+ var err error
+ var reply interface{}
+ for i := 0; i <= pending; i++ {
+ var e error
+ if reply, e = c.readReply(); e != nil {
+ return nil, c.fatal(e)
+ }
+ if e, ok := reply.(Error); ok && err == nil {
+ err = e
+ }
+ }
+ return reply, err
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/doc.go b/vendor/github.com/gomodule/redigo/redis/doc.go
new file mode 100644
index 00000000..70ec1ea6
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/doc.go
@@ -0,0 +1,177 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+// Package redis is a client for the Redis database.
+//
+// The Redigo FAQ (https://github.com/gomodule/redigo/wiki/FAQ) contains more
+// documentation about this package.
+//
+// Connections
+//
+// The Conn interface is the primary interface for working with Redis.
+// Applications create connections by calling the Dial, DialWithTimeout or
+// NewConn functions. In the future, functions will be added for creating
+// sharded and other types of connections.
+//
+// The application must call the connection Close method when the application
+// is done with the connection.
+//
+// Executing Commands
+//
+// The Conn interface has a generic method for executing Redis commands:
+//
+// Do(commandName string, args ...interface{}) (reply interface{}, err error)
+//
+// The Redis command reference (http://redis.io/commands) lists the available
+// commands. An example of using the Redis APPEND command is:
+//
+// n, err := conn.Do("APPEND", "key", "value")
+//
+// The Do method converts command arguments to bulk strings for transmission
+// to the server as follows:
+//
+// Go Type Conversion
+// []byte Sent as is
+// string Sent as is
+// int, int64 strconv.FormatInt(v)
+// float64 strconv.FormatFloat(v, 'g', -1, 64)
+// bool true -> "1", false -> "0"
+// nil ""
+// all other types fmt.Fprint(w, v)
+//
+// Redis command reply types are represented using the following Go types:
+//
+// Redis type Go type
+// error redis.Error
+// integer int64
+// simple string string
+// bulk string []byte or nil if value not present.
+// array []interface{} or nil if value not present.
+//
+// Use type assertions or the reply helper functions to convert from
+// interface{} to the specific Go type for the command result.
+//
+// Pipelining
+//
+// Connections support pipelining using the Send, Flush and Receive methods.
+//
+// Send(commandName string, args ...interface{}) error
+// Flush() error
+// Receive() (reply interface{}, err error)
+//
+// Send writes the command to the connection's output buffer. Flush flushes the
+// connection's output buffer to the server. Receive reads a single reply from
+// the server. The following example shows a simple pipeline.
+//
+// c.Send("SET", "foo", "bar")
+// c.Send("GET", "foo")
+// c.Flush()
+// c.Receive() // reply from SET
+// v, err = c.Receive() // reply from GET
+//
+// The Do method combines the functionality of the Send, Flush and Receive
+// methods. The Do method starts by writing the command and flushing the output
+// buffer. Next, the Do method receives all pending replies including the reply
+// for the command just sent by Do. If any of the received replies is an error,
+// then Do returns the error. If there are no errors, then Do returns the last
+// reply. If the command argument to the Do method is "", then the Do method
+// will flush the output buffer and receive pending replies without sending a
+// command.
+//
+// Use the Send and Do methods to implement pipelined transactions.
+//
+// c.Send("MULTI")
+// c.Send("INCR", "foo")
+// c.Send("INCR", "bar")
+// r, err := c.Do("EXEC")
+// fmt.Println(r) // prints [1, 1]
+//
+// Concurrency
+//
+// Connections support one concurrent caller to the Receive method and one
+// concurrent caller to the Send and Flush methods. No other concurrency is
+// supported including concurrent calls to the Do method.
+//
+// For full concurrent access to Redis, use the thread-safe Pool to get, use
+// and release a connection from within a goroutine. Connections returned from
+// a Pool have the concurrency restrictions described in the previous
+// paragraph.
+//
+// Publish and Subscribe
+//
+// Use the Send, Flush and Receive methods to implement Pub/Sub subscribers.
+//
+// c.Send("SUBSCRIBE", "example")
+// c.Flush()
+// for {
+// reply, err := c.Receive()
+// if err != nil {
+// return err
+// }
+// // process pushed message
+// }
+//
+// The PubSubConn type wraps a Conn with convenience methods for implementing
+// subscribers. The Subscribe, PSubscribe, Unsubscribe and PUnsubscribe methods
+// send and flush a subscription management command. The receive method
+// converts a pushed message to convenient types for use in a type switch.
+//
+// psc := redis.PubSubConn{Conn: c}
+// psc.Subscribe("example")
+// for {
+// switch v := psc.Receive().(type) {
+// case redis.Message:
+// fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
+// case redis.Subscription:
+// fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
+// case error:
+// return v
+// }
+// }
+//
+// Reply Helpers
+//
+// The Bool, Int, Bytes, String, Strings and Values functions convert a reply
+// to a value of a specific type. To allow convenient wrapping of calls to the
+// connection Do and Receive methods, the functions take a second argument of
+// type error. If the error is non-nil, then the helper function returns the
+// error. If the error is nil, the function converts the reply to the specified
+// type:
+//
+// exists, err := redis.Bool(c.Do("EXISTS", "foo"))
+// if err != nil {
+// // handle error return from c.Do or type conversion error.
+// }
+//
+// The Scan function converts elements of a array reply to Go types:
+//
+// var value1 int
+// var value2 string
+// reply, err := redis.Values(c.Do("MGET", "key1", "key2"))
+// if err != nil {
+// // handle error
+// }
+// if _, err := redis.Scan(reply, &value1, &value2); err != nil {
+// // handle error
+// }
+//
+// Errors
+//
+// Connection methods return error replies from the server as type redis.Error.
+//
+// Call the connection Err() method to determine if the connection encountered
+// non-recoverable error such as a network error or protocol parsing error. If
+// Err() returns a non-nil value, then the connection is not usable and should
+// be closed.
+package redis // import "github.com/gomodule/redigo/redis"
diff --git a/vendor/github.com/gomodule/redigo/redis/go16.go b/vendor/github.com/gomodule/redigo/redis/go16.go
new file mode 100644
index 00000000..f6b1a7cc
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/go16.go
@@ -0,0 +1,27 @@
+// +build !go1.7
+
+package redis
+
+import "crypto/tls"
+
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+ return &tls.Config{
+ Rand: cfg.Rand,
+ Time: cfg.Time,
+ Certificates: cfg.Certificates,
+ NameToCertificate: cfg.NameToCertificate,
+ GetCertificate: cfg.GetCertificate,
+ RootCAs: cfg.RootCAs,
+ NextProtos: cfg.NextProtos,
+ ServerName: cfg.ServerName,
+ ClientAuth: cfg.ClientAuth,
+ ClientCAs: cfg.ClientCAs,
+ InsecureSkipVerify: cfg.InsecureSkipVerify,
+ CipherSuites: cfg.CipherSuites,
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites,
+ ClientSessionCache: cfg.ClientSessionCache,
+ MinVersion: cfg.MinVersion,
+ MaxVersion: cfg.MaxVersion,
+ CurvePreferences: cfg.CurvePreferences,
+ }
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/go17.go b/vendor/github.com/gomodule/redigo/redis/go17.go
new file mode 100644
index 00000000..5f363791
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/go17.go
@@ -0,0 +1,29 @@
+// +build go1.7,!go1.8
+
+package redis
+
+import "crypto/tls"
+
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+ return &tls.Config{
+ Rand: cfg.Rand,
+ Time: cfg.Time,
+ Certificates: cfg.Certificates,
+ NameToCertificate: cfg.NameToCertificate,
+ GetCertificate: cfg.GetCertificate,
+ RootCAs: cfg.RootCAs,
+ NextProtos: cfg.NextProtos,
+ ServerName: cfg.ServerName,
+ ClientAuth: cfg.ClientAuth,
+ ClientCAs: cfg.ClientCAs,
+ InsecureSkipVerify: cfg.InsecureSkipVerify,
+ CipherSuites: cfg.CipherSuites,
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites,
+ ClientSessionCache: cfg.ClientSessionCache,
+ MinVersion: cfg.MinVersion,
+ MaxVersion: cfg.MaxVersion,
+ CurvePreferences: cfg.CurvePreferences,
+ DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled,
+ Renegotiation: cfg.Renegotiation,
+ }
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/go18.go b/vendor/github.com/gomodule/redigo/redis/go18.go
new file mode 100644
index 00000000..558363be
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/go18.go
@@ -0,0 +1,9 @@
+// +build go1.8
+
+package redis
+
+import "crypto/tls"
+
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+ return cfg.Clone()
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/log.go b/vendor/github.com/gomodule/redigo/redis/log.go
new file mode 100644
index 00000000..b2996611
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/log.go
@@ -0,0 +1,134 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "time"
+)
+
+var (
+ _ ConnWithTimeout = (*loggingConn)(nil)
+)
+
+// NewLoggingConn returns a logging wrapper around a connection.
+func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn {
+ if prefix != "" {
+ prefix = prefix + "."
+ }
+ return &loggingConn{conn, logger, prefix}
+}
+
+type loggingConn struct {
+ Conn
+ logger *log.Logger
+ prefix string
+}
+
+func (c *loggingConn) Close() error {
+ err := c.Conn.Close()
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err)
+ c.logger.Output(2, buf.String())
+ return err
+}
+
+func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) {
+ const chop = 32
+ switch v := v.(type) {
+ case []byte:
+ if len(v) > chop {
+ fmt.Fprintf(buf, "%q...", v[:chop])
+ } else {
+ fmt.Fprintf(buf, "%q", v)
+ }
+ case string:
+ if len(v) > chop {
+ fmt.Fprintf(buf, "%q...", v[:chop])
+ } else {
+ fmt.Fprintf(buf, "%q", v)
+ }
+ case []interface{}:
+ if len(v) == 0 {
+ buf.WriteString("[]")
+ } else {
+ sep := "["
+ fin := "]"
+ if len(v) > chop {
+ v = v[:chop]
+ fin = "...]"
+ }
+ for _, vv := range v {
+ buf.WriteString(sep)
+ c.printValue(buf, vv)
+ sep = ", "
+ }
+ buf.WriteString(fin)
+ }
+ default:
+ fmt.Fprint(buf, v)
+ }
+}
+
+func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) {
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "%s%s(", c.prefix, method)
+ if method != "Receive" {
+ buf.WriteString(commandName)
+ for _, arg := range args {
+ buf.WriteString(", ")
+ c.printValue(&buf, arg)
+ }
+ }
+ buf.WriteString(") -> (")
+ if method != "Send" {
+ c.printValue(&buf, reply)
+ buf.WriteString(", ")
+ }
+ fmt.Fprintf(&buf, "%v)", err)
+ c.logger.Output(3, buf.String())
+}
+
+func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) {
+ reply, err := c.Conn.Do(commandName, args...)
+ c.print("Do", commandName, args, reply, err)
+ return reply, err
+}
+
+func (c *loggingConn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (interface{}, error) {
+ reply, err := DoWithTimeout(c.Conn, timeout, commandName, args...)
+ c.print("DoWithTimeout", commandName, args, reply, err)
+ return reply, err
+}
+
+func (c *loggingConn) Send(commandName string, args ...interface{}) error {
+ err := c.Conn.Send(commandName, args...)
+ c.print("Send", commandName, args, nil, err)
+ return err
+}
+
+func (c *loggingConn) Receive() (interface{}, error) {
+ reply, err := c.Conn.Receive()
+ c.print("Receive", "", nil, reply, err)
+ return reply, err
+}
+
+func (c *loggingConn) ReceiveWithTimeout(timeout time.Duration) (interface{}, error) {
+ reply, err := ReceiveWithTimeout(c.Conn, timeout)
+ c.print("ReceiveWithTimeout", "", nil, reply, err)
+ return reply, err
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/pool.go b/vendor/github.com/gomodule/redigo/redis/pool.go
new file mode 100644
index 00000000..d77da325
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/pool.go
@@ -0,0 +1,562 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/sha1"
+ "errors"
+ "io"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/gomodule/redigo/internal"
+)
+
+var (
+ _ ConnWithTimeout = (*activeConn)(nil)
+ _ ConnWithTimeout = (*errorConn)(nil)
+)
+
+var nowFunc = time.Now // for testing
+
+// ErrPoolExhausted is returned from a pool connection method (Do, Send,
+// Receive, Flush, Err) when the maximum number of database connections in the
+// pool has been reached.
+var ErrPoolExhausted = errors.New("redigo: connection pool exhausted")
+
+var (
+ errPoolClosed = errors.New("redigo: connection pool closed")
+ errConnClosed = errors.New("redigo: connection closed")
+)
+
+// Pool maintains a pool of connections. The application calls the Get method
+// to get a connection from the pool and the connection's Close method to
+// return the connection's resources to the pool.
+//
+// The following example shows how to use a pool in a web application. The
+// application creates a pool at application startup and makes it available to
+// request handlers using a package level variable. The pool configuration used
+// here is an example, not a recommendation.
+//
+// func newPool(addr string) *redis.Pool {
+// return &redis.Pool{
+// MaxIdle: 3,
+// IdleTimeout: 240 * time.Second,
+// Dial: func () (redis.Conn, error) { return redis.Dial("tcp", addr) },
+// }
+// }
+//
+// var (
+// pool *redis.Pool
+// redisServer = flag.String("redisServer", ":6379", "")
+// )
+//
+// func main() {
+// flag.Parse()
+// pool = newPool(*redisServer)
+// ...
+// }
+//
+// A request handler gets a connection from the pool and closes the connection
+// when the handler is done:
+//
+// func serveHome(w http.ResponseWriter, r *http.Request) {
+// conn := pool.Get()
+// defer conn.Close()
+// ...
+// }
+//
+// Use the Dial function to authenticate connections with the AUTH command or
+// select a database with the SELECT command:
+//
+// pool := &redis.Pool{
+// // Other pool configuration not shown in this example.
+// Dial: func () (redis.Conn, error) {
+// c, err := redis.Dial("tcp", server)
+// if err != nil {
+// return nil, err
+// }
+// if _, err := c.Do("AUTH", password); err != nil {
+// c.Close()
+// return nil, err
+// }
+// if _, err := c.Do("SELECT", db); err != nil {
+// c.Close()
+// return nil, err
+// }
+// return c, nil
+// },
+// }
+//
+// Use the TestOnBorrow function to check the health of an idle connection
+// before the connection is returned to the application. This example PINGs
+// connections that have been idle more than a minute:
+//
+// pool := &redis.Pool{
+// // Other pool configuration not shown in this example.
+// TestOnBorrow: func(c redis.Conn, t time.Time) error {
+// if time.Since(t) < time.Minute {
+// return nil
+// }
+// _, err := c.Do("PING")
+// return err
+// },
+// }
+//
+type Pool struct {
+ // Dial is an application supplied function for creating and configuring a
+ // connection.
+ //
+ // The connection returned from Dial must not be in a special state
+ // (subscribed to pubsub channel, transaction started, ...).
+ Dial func() (Conn, error)
+
+ // TestOnBorrow is an optional application supplied function for checking
+ // the health of an idle connection before the connection is used again by
+ // the application. Argument t is the time that the connection was returned
+ // to the pool. If the function returns an error, then the connection is
+ // closed.
+ TestOnBorrow func(c Conn, t time.Time) error
+
+ // Maximum number of idle connections in the pool.
+ MaxIdle int
+
+ // Maximum number of connections allocated by the pool at a given time.
+ // When zero, there is no limit on the number of connections in the pool.
+ MaxActive int
+
+ // Close connections after remaining idle for this duration. If the value
+ // is zero, then idle connections are not closed. Applications should set
+ // the timeout to a value less than the server's timeout.
+ IdleTimeout time.Duration
+
+ // If Wait is true and the pool is at the MaxActive limit, then Get() waits
+ // for a connection to be returned to the pool before returning.
+ Wait bool
+
+ // Close connections older than this duration. If the value is zero, then
+ // the pool does not close connections based on age.
+ MaxConnLifetime time.Duration
+
+ chInitialized uint32 // set to 1 when field ch is initialized
+
+ mu sync.Mutex // mu protects the following fields
+ closed bool // set to true when the pool is closed.
+ active int // the number of open connections in the pool
+ ch chan struct{} // limits open connections when p.Wait is true
+ idle idleList // idle connections
+}
+
+// NewPool creates a new pool.
+//
+// Deprecated: Initialize the Pool directory as shown in the example.
+func NewPool(newFn func() (Conn, error), maxIdle int) *Pool {
+ return &Pool{Dial: newFn, MaxIdle: maxIdle}
+}
+
+// Get gets a connection. The application must close the returned connection.
+// This method always returns a valid connection so that applications can defer
+// error handling to the first use of the connection. If there is an error
+// getting an underlying connection, then the connection Err, Do, Send, Flush
+// and Receive methods return that error.
+func (p *Pool) Get() Conn {
+ pc, err := p.get(nil)
+ if err != nil {
+ return errorConn{err}
+ }
+ return &activeConn{p: p, pc: pc}
+}
+
+// PoolStats contains pool statistics.
+type PoolStats struct {
+ // ActiveCount is the number of connections in the pool. The count includes
+ // idle connections and connections in use.
+ ActiveCount int
+ // IdleCount is the number of idle connections in the pool.
+ IdleCount int
+}
+
+// Stats returns pool's statistics.
+func (p *Pool) Stats() PoolStats {
+ p.mu.Lock()
+ stats := PoolStats{
+ ActiveCount: p.active,
+ IdleCount: p.idle.count,
+ }
+ p.mu.Unlock()
+
+ return stats
+}
+
+// ActiveCount returns the number of connections in the pool. The count
+// includes idle connections and connections in use.
+func (p *Pool) ActiveCount() int {
+ p.mu.Lock()
+ active := p.active
+ p.mu.Unlock()
+ return active
+}
+
+// IdleCount returns the number of idle connections in the pool.
+func (p *Pool) IdleCount() int {
+ p.mu.Lock()
+ idle := p.idle.count
+ p.mu.Unlock()
+ return idle
+}
+
+// Close releases the resources used by the pool.
+func (p *Pool) Close() error {
+ p.mu.Lock()
+ if p.closed {
+ p.mu.Unlock()
+ return nil
+ }
+ p.closed = true
+ p.active -= p.idle.count
+ pc := p.idle.front
+ p.idle.count = 0
+ p.idle.front, p.idle.back = nil, nil
+ if p.ch != nil {
+ close(p.ch)
+ }
+ p.mu.Unlock()
+ for ; pc != nil; pc = pc.next {
+ pc.c.Close()
+ }
+ return nil
+}
+
+func (p *Pool) lazyInit() {
+ // Fast path.
+ if atomic.LoadUint32(&p.chInitialized) == 1 {
+ return
+ }
+ // Slow path.
+ p.mu.Lock()
+ if p.chInitialized == 0 {
+ p.ch = make(chan struct{}, p.MaxActive)
+ if p.closed {
+ close(p.ch)
+ } else {
+ for i := 0; i < p.MaxActive; i++ {
+ p.ch <- struct{}{}
+ }
+ }
+ atomic.StoreUint32(&p.chInitialized, 1)
+ }
+ p.mu.Unlock()
+}
+
+// get prunes stale connections and returns a connection from the idle list or
+// creates a new connection.
+func (p *Pool) get(ctx interface {
+ Done() <-chan struct{}
+ Err() error
+}) (*poolConn, error) {
+
+ // Handle limit for p.Wait == true.
+ if p.Wait && p.MaxActive > 0 {
+ p.lazyInit()
+ if ctx == nil {
+ <-p.ch
+ } else {
+ select {
+ case <-p.ch:
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+ }
+
+ p.mu.Lock()
+
+ // Prune stale connections at the back of the idle list.
+ if p.IdleTimeout > 0 {
+ n := p.idle.count
+ for i := 0; i < n && p.idle.back != nil && p.idle.back.t.Add(p.IdleTimeout).Before(nowFunc()); i++ {
+ pc := p.idle.back
+ p.idle.popBack()
+ p.mu.Unlock()
+ pc.c.Close()
+ p.mu.Lock()
+ p.active--
+ }
+ }
+
+ // Get idle connection from the front of idle list.
+ for p.idle.front != nil {
+ pc := p.idle.front
+ p.idle.popFront()
+ p.mu.Unlock()
+ if (p.TestOnBorrow == nil || p.TestOnBorrow(pc.c, pc.t) == nil) &&
+ (p.MaxConnLifetime == 0 || nowFunc().Sub(pc.created) < p.MaxConnLifetime) {
+ return pc, nil
+ }
+ pc.c.Close()
+ p.mu.Lock()
+ p.active--
+ }
+
+ // Check for pool closed before dialing a new connection.
+ if p.closed {
+ p.mu.Unlock()
+ return nil, errors.New("redigo: get on closed pool")
+ }
+
+ // Handle limit for p.Wait == false.
+ if !p.Wait && p.MaxActive > 0 && p.active >= p.MaxActive {
+ p.mu.Unlock()
+ return nil, ErrPoolExhausted
+ }
+
+ p.active++
+ p.mu.Unlock()
+ c, err := p.Dial()
+ if err != nil {
+ c = nil
+ p.mu.Lock()
+ p.active--
+ if p.ch != nil && !p.closed {
+ p.ch <- struct{}{}
+ }
+ p.mu.Unlock()
+ }
+ return &poolConn{c: c, created: nowFunc()}, err
+}
+
+func (p *Pool) put(pc *poolConn, forceClose bool) error {
+ p.mu.Lock()
+ if !p.closed && !forceClose {
+ pc.t = nowFunc()
+ p.idle.pushFront(pc)
+ if p.idle.count > p.MaxIdle {
+ pc = p.idle.back
+ p.idle.popBack()
+ } else {
+ pc = nil
+ }
+ }
+
+ if pc != nil {
+ p.mu.Unlock()
+ pc.c.Close()
+ p.mu.Lock()
+ p.active--
+ }
+
+ if p.ch != nil && !p.closed {
+ p.ch <- struct{}{}
+ }
+ p.mu.Unlock()
+ return nil
+}
+
+type activeConn struct {
+ p *Pool
+ pc *poolConn
+ state int
+}
+
+var (
+ sentinel []byte
+ sentinelOnce sync.Once
+)
+
+func initSentinel() {
+ p := make([]byte, 64)
+ if _, err := rand.Read(p); err == nil {
+ sentinel = p
+ } else {
+ h := sha1.New()
+ io.WriteString(h, "Oops, rand failed. Use time instead.")
+ io.WriteString(h, strconv.FormatInt(time.Now().UnixNano(), 10))
+ sentinel = h.Sum(nil)
+ }
+}
+
+func (ac *activeConn) Close() error {
+ pc := ac.pc
+ if pc == nil {
+ return nil
+ }
+ ac.pc = nil
+
+ if ac.state&internal.MultiState != 0 {
+ pc.c.Send("DISCARD")
+ ac.state &^= (internal.MultiState | internal.WatchState)
+ } else if ac.state&internal.WatchState != 0 {
+ pc.c.Send("UNWATCH")
+ ac.state &^= internal.WatchState
+ }
+ if ac.state&internal.SubscribeState != 0 {
+ pc.c.Send("UNSUBSCRIBE")
+ pc.c.Send("PUNSUBSCRIBE")
+ // To detect the end of the message stream, ask the server to echo
+ // a sentinel value and read until we see that value.
+ sentinelOnce.Do(initSentinel)
+ pc.c.Send("ECHO", sentinel)
+ pc.c.Flush()
+ for {
+ p, err := pc.c.Receive()
+ if err != nil {
+ break
+ }
+ if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) {
+ ac.state &^= internal.SubscribeState
+ break
+ }
+ }
+ }
+ pc.c.Do("")
+ ac.p.put(pc, ac.state != 0 || pc.c.Err() != nil)
+ return nil
+}
+
+func (ac *activeConn) Err() error {
+ pc := ac.pc
+ if pc == nil {
+ return errConnClosed
+ }
+ return pc.c.Err()
+}
+
+func (ac *activeConn) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
+ pc := ac.pc
+ if pc == nil {
+ return nil, errConnClosed
+ }
+ ci := internal.LookupCommandInfo(commandName)
+ ac.state = (ac.state | ci.Set) &^ ci.Clear
+ return pc.c.Do(commandName, args...)
+}
+
+func (ac *activeConn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error) {
+ pc := ac.pc
+ if pc == nil {
+ return nil, errConnClosed
+ }
+ cwt, ok := pc.c.(ConnWithTimeout)
+ if !ok {
+ return nil, errTimeoutNotSupported
+ }
+ ci := internal.LookupCommandInfo(commandName)
+ ac.state = (ac.state | ci.Set) &^ ci.Clear
+ return cwt.DoWithTimeout(timeout, commandName, args...)
+}
+
+func (ac *activeConn) Send(commandName string, args ...interface{}) error {
+ pc := ac.pc
+ if pc == nil {
+ return errConnClosed
+ }
+ ci := internal.LookupCommandInfo(commandName)
+ ac.state = (ac.state | ci.Set) &^ ci.Clear
+ return pc.c.Send(commandName, args...)
+}
+
+func (ac *activeConn) Flush() error {
+ pc := ac.pc
+ if pc == nil {
+ return errConnClosed
+ }
+ return pc.c.Flush()
+}
+
+func (ac *activeConn) Receive() (reply interface{}, err error) {
+ pc := ac.pc
+ if pc == nil {
+ return nil, errConnClosed
+ }
+ return pc.c.Receive()
+}
+
+func (ac *activeConn) ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err error) {
+ pc := ac.pc
+ if pc == nil {
+ return nil, errConnClosed
+ }
+ cwt, ok := pc.c.(ConnWithTimeout)
+ if !ok {
+ return nil, errTimeoutNotSupported
+ }
+ return cwt.ReceiveWithTimeout(timeout)
+}
+
+type errorConn struct{ err error }
+
+func (ec errorConn) Do(string, ...interface{}) (interface{}, error) { return nil, ec.err }
+func (ec errorConn) DoWithTimeout(time.Duration, string, ...interface{}) (interface{}, error) {
+ return nil, ec.err
+}
+func (ec errorConn) Send(string, ...interface{}) error { return ec.err }
+func (ec errorConn) Err() error { return ec.err }
+func (ec errorConn) Close() error { return nil }
+func (ec errorConn) Flush() error { return ec.err }
+func (ec errorConn) Receive() (interface{}, error) { return nil, ec.err }
+func (ec errorConn) ReceiveWithTimeout(time.Duration) (interface{}, error) { return nil, ec.err }
+
+type idleList struct {
+ count int
+ front, back *poolConn
+}
+
+type poolConn struct {
+ c Conn
+ t time.Time
+ created time.Time
+ next, prev *poolConn
+}
+
+func (l *idleList) pushFront(pc *poolConn) {
+ pc.next = l.front
+ pc.prev = nil
+ if l.count == 0 {
+ l.back = pc
+ } else {
+ l.front.prev = pc
+ }
+ l.front = pc
+ l.count++
+ return
+}
+
+func (l *idleList) popFront() {
+ pc := l.front
+ l.count--
+ if l.count == 0 {
+ l.front, l.back = nil, nil
+ } else {
+ pc.next.prev = nil
+ l.front = pc.next
+ }
+ pc.next, pc.prev = nil, nil
+}
+
+func (l *idleList) popBack() {
+ pc := l.back
+ l.count--
+ if l.count == 0 {
+ l.front, l.back = nil, nil
+ } else {
+ pc.prev.next = nil
+ l.back = pc.prev
+ }
+ pc.next, pc.prev = nil, nil
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/pool17.go b/vendor/github.com/gomodule/redigo/redis/pool17.go
new file mode 100644
index 00000000..c1ea18ee
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/pool17.go
@@ -0,0 +1,35 @@
+// Copyright 2018 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+// +build go1.7
+
+package redis
+
+import "context"
+
+// GetContext gets a connection using the provided context.
+//
+// The provided Context must be non-nil. If the context expires before the
+// connection is complete, an error is returned. Any expiration on the context
+// will not affect the returned connection.
+//
+// If the function completes without error, then the application must close the
+// returned connection.
+func (p *Pool) GetContext(ctx context.Context) (Conn, error) {
+ pc, err := p.get(ctx)
+ if err != nil {
+ return errorConn{err}, err
+ }
+ return &activeConn{p: p, pc: pc}, nil
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/pubsub.go b/vendor/github.com/gomodule/redigo/redis/pubsub.go
new file mode 100644
index 00000000..2da60211
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/pubsub.go
@@ -0,0 +1,148 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "errors"
+ "time"
+)
+
+// Subscription represents a subscribe or unsubscribe notification.
+type Subscription struct {
+ // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe"
+ Kind string
+
+ // The channel that was changed.
+ Channel string
+
+ // The current number of subscriptions for connection.
+ Count int
+}
+
+// Message represents a message notification.
+type Message struct {
+ // The originating channel.
+ Channel string
+
+ // The matched pattern, if any
+ Pattern string
+
+ // The message data.
+ Data []byte
+}
+
+// Pong represents a pubsub pong notification.
+type Pong struct {
+ Data string
+}
+
+// PubSubConn wraps a Conn with convenience methods for subscribers.
+type PubSubConn struct {
+ Conn Conn
+}
+
+// Close closes the connection.
+func (c PubSubConn) Close() error {
+ return c.Conn.Close()
+}
+
+// Subscribe subscribes the connection to the specified channels.
+func (c PubSubConn) Subscribe(channel ...interface{}) error {
+ c.Conn.Send("SUBSCRIBE", channel...)
+ return c.Conn.Flush()
+}
+
+// PSubscribe subscribes the connection to the given patterns.
+func (c PubSubConn) PSubscribe(channel ...interface{}) error {
+ c.Conn.Send("PSUBSCRIBE", channel...)
+ return c.Conn.Flush()
+}
+
+// Unsubscribe unsubscribes the connection from the given channels, or from all
+// of them if none is given.
+func (c PubSubConn) Unsubscribe(channel ...interface{}) error {
+ c.Conn.Send("UNSUBSCRIBE", channel...)
+ return c.Conn.Flush()
+}
+
+// PUnsubscribe unsubscribes the connection from the given patterns, or from all
+// of them if none is given.
+func (c PubSubConn) PUnsubscribe(channel ...interface{}) error {
+ c.Conn.Send("PUNSUBSCRIBE", channel...)
+ return c.Conn.Flush()
+}
+
+// Ping sends a PING to the server with the specified data.
+//
+// The connection must be subscribed to at least one channel or pattern when
+// calling this method.
+func (c PubSubConn) Ping(data string) error {
+ c.Conn.Send("PING", data)
+ return c.Conn.Flush()
+}
+
+// Receive returns a pushed message as a Subscription, Message, Pong or error.
+// The return value is intended to be used directly in a type switch as
+// illustrated in the PubSubConn example.
+func (c PubSubConn) Receive() interface{} {
+ return c.receiveInternal(c.Conn.Receive())
+}
+
+// ReceiveWithTimeout is like Receive, but it allows the application to
+// override the connection's default timeout.
+func (c PubSubConn) ReceiveWithTimeout(timeout time.Duration) interface{} {
+ return c.receiveInternal(ReceiveWithTimeout(c.Conn, timeout))
+}
+
+func (c PubSubConn) receiveInternal(replyArg interface{}, errArg error) interface{} {
+ reply, err := Values(replyArg, errArg)
+ if err != nil {
+ return err
+ }
+
+ var kind string
+ reply, err = Scan(reply, &kind)
+ if err != nil {
+ return err
+ }
+
+ switch kind {
+ case "message":
+ var m Message
+ if _, err := Scan(reply, &m.Channel, &m.Data); err != nil {
+ return err
+ }
+ return m
+ case "pmessage":
+ var m Message
+ if _, err := Scan(reply, &m.Pattern, &m.Channel, &m.Data); err != nil {
+ return err
+ }
+ return m
+ case "subscribe", "psubscribe", "unsubscribe", "punsubscribe":
+ s := Subscription{Kind: kind}
+ if _, err := Scan(reply, &s.Channel, &s.Count); err != nil {
+ return err
+ }
+ return s
+ case "pong":
+ var p Pong
+ if _, err := Scan(reply, &p.Data); err != nil {
+ return err
+ }
+ return p
+ }
+ return errors.New("redigo: unknown pubsub notification")
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/redis.go b/vendor/github.com/gomodule/redigo/redis/redis.go
new file mode 100644
index 00000000..141fa4a9
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/redis.go
@@ -0,0 +1,117 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "errors"
+ "time"
+)
+
+// Error represents an error returned in a command reply.
+type Error string
+
+func (err Error) Error() string { return string(err) }
+
+// Conn represents a connection to a Redis server.
+type Conn interface {
+ // Close closes the connection.
+ Close() error
+
+ // Err returns a non-nil value when the connection is not usable.
+ Err() error
+
+ // Do sends a command to the server and returns the received reply.
+ Do(commandName string, args ...interface{}) (reply interface{}, err error)
+
+ // Send writes the command to the client's output buffer.
+ Send(commandName string, args ...interface{}) error
+
+ // Flush flushes the output buffer to the Redis server.
+ Flush() error
+
+ // Receive receives a single reply from the Redis server
+ Receive() (reply interface{}, err error)
+}
+
+// Argument is the interface implemented by an object which wants to control how
+// the object is converted to Redis bulk strings.
+type Argument interface {
+ // RedisArg returns a value to be encoded as a bulk string per the
+ // conversions listed in the section 'Executing Commands'.
+ // Implementations should typically return a []byte or string.
+ RedisArg() interface{}
+}
+
+// Scanner is implemented by an object which wants to control its value is
+// interpreted when read from Redis.
+type Scanner interface {
+ // RedisScan assigns a value from a Redis value. The argument src is one of
+ // the reply types listed in the section `Executing Commands`.
+ //
+ // An error should be returned if the value cannot be stored without
+ // loss of information.
+ RedisScan(src interface{}) error
+}
+
+// ConnWithTimeout is an optional interface that allows the caller to override
+// a connection's default read timeout. This interface is useful for executing
+// the BLPOP, BRPOP, BRPOPLPUSH, XREAD and other commands that block at the
+// server.
+//
+// A connection's default read timeout is set with the DialReadTimeout dial
+// option. Applications should rely on the default timeout for commands that do
+// not block at the server.
+//
+// All of the Conn implementations in this package satisfy the ConnWithTimeout
+// interface.
+//
+// Use the DoWithTimeout and ReceiveWithTimeout helper functions to simplify
+// use of this interface.
+type ConnWithTimeout interface {
+ Conn
+
+ // Do sends a command to the server and returns the received reply.
+ // The timeout overrides the read timeout set when dialing the
+ // connection.
+ DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error)
+
+ // Receive receives a single reply from the Redis server. The timeout
+ // overrides the read timeout set when dialing the connection.
+ ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err error)
+}
+
+var errTimeoutNotSupported = errors.New("redis: connection does not support ConnWithTimeout")
+
+// DoWithTimeout executes a Redis command with the specified read timeout. If
+// the connection does not satisfy the ConnWithTimeout interface, then an error
+// is returned.
+func DoWithTimeout(c Conn, timeout time.Duration, cmd string, args ...interface{}) (interface{}, error) {
+ cwt, ok := c.(ConnWithTimeout)
+ if !ok {
+ return nil, errTimeoutNotSupported
+ }
+ return cwt.DoWithTimeout(timeout, cmd, args...)
+}
+
+// ReceiveWithTimeout receives a reply with the specified read timeout. If the
+// connection does not satisfy the ConnWithTimeout interface, then an error is
+// returned.
+func ReceiveWithTimeout(c Conn, timeout time.Duration) (interface{}, error) {
+ cwt, ok := c.(ConnWithTimeout)
+ if !ok {
+ return nil, errTimeoutNotSupported
+ }
+ return cwt.ReceiveWithTimeout(timeout)
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/reply.go b/vendor/github.com/gomodule/redigo/redis/reply.go
new file mode 100644
index 00000000..c2b3b2b6
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/reply.go
@@ -0,0 +1,479 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+)
+
+// ErrNil indicates that a reply value is nil.
+var ErrNil = errors.New("redigo: nil returned")
+
+// Int is a helper that converts a command reply to an integer. If err is not
+// equal to nil, then Int returns 0, err. Otherwise, Int converts the
+// reply to an int as follows:
+//
+// Reply type Result
+// integer int(reply), nil
+// bulk string parsed reply, nil
+// nil 0, ErrNil
+// other 0, error
+func Int(reply interface{}, err error) (int, error) {
+ if err != nil {
+ return 0, err
+ }
+ switch reply := reply.(type) {
+ case int64:
+ x := int(reply)
+ if int64(x) != reply {
+ return 0, strconv.ErrRange
+ }
+ return x, nil
+ case []byte:
+ n, err := strconv.ParseInt(string(reply), 10, 0)
+ return int(n), err
+ case nil:
+ return 0, ErrNil
+ case Error:
+ return 0, reply
+ }
+ return 0, fmt.Errorf("redigo: unexpected type for Int, got type %T", reply)
+}
+
+// Int64 is a helper that converts a command reply to 64 bit integer. If err is
+// not equal to nil, then Int returns 0, err. Otherwise, Int64 converts the
+// reply to an int64 as follows:
+//
+// Reply type Result
+// integer reply, nil
+// bulk string parsed reply, nil
+// nil 0, ErrNil
+// other 0, error
+func Int64(reply interface{}, err error) (int64, error) {
+ if err != nil {
+ return 0, err
+ }
+ switch reply := reply.(type) {
+ case int64:
+ return reply, nil
+ case []byte:
+ n, err := strconv.ParseInt(string(reply), 10, 64)
+ return n, err
+ case nil:
+ return 0, ErrNil
+ case Error:
+ return 0, reply
+ }
+ return 0, fmt.Errorf("redigo: unexpected type for Int64, got type %T", reply)
+}
+
+var errNegativeInt = errors.New("redigo: unexpected value for Uint64")
+
+// Uint64 is a helper that converts a command reply to 64 bit integer. If err is
+// not equal to nil, then Int returns 0, err. Otherwise, Int64 converts the
+// reply to an int64 as follows:
+//
+// Reply type Result
+// integer reply, nil
+// bulk string parsed reply, nil
+// nil 0, ErrNil
+// other 0, error
+func Uint64(reply interface{}, err error) (uint64, error) {
+ if err != nil {
+ return 0, err
+ }
+ switch reply := reply.(type) {
+ case int64:
+ if reply < 0 {
+ return 0, errNegativeInt
+ }
+ return uint64(reply), nil
+ case []byte:
+ n, err := strconv.ParseUint(string(reply), 10, 64)
+ return n, err
+ case nil:
+ return 0, ErrNil
+ case Error:
+ return 0, reply
+ }
+ return 0, fmt.Errorf("redigo: unexpected type for Uint64, got type %T", reply)
+}
+
+// Float64 is a helper that converts a command reply to 64 bit float. If err is
+// not equal to nil, then Float64 returns 0, err. Otherwise, Float64 converts
+// the reply to an int as follows:
+//
+// Reply type Result
+// bulk string parsed reply, nil
+// nil 0, ErrNil
+// other 0, error
+func Float64(reply interface{}, err error) (float64, error) {
+ if err != nil {
+ return 0, err
+ }
+ switch reply := reply.(type) {
+ case []byte:
+ n, err := strconv.ParseFloat(string(reply), 64)
+ return n, err
+ case nil:
+ return 0, ErrNil
+ case Error:
+ return 0, reply
+ }
+ return 0, fmt.Errorf("redigo: unexpected type for Float64, got type %T", reply)
+}
+
+// String is a helper that converts a command reply to a string. If err is not
+// equal to nil, then String returns "", err. Otherwise String converts the
+// reply to a string as follows:
+//
+// Reply type Result
+// bulk string string(reply), nil
+// simple string reply, nil
+// nil "", ErrNil
+// other "", error
+func String(reply interface{}, err error) (string, error) {
+ if err != nil {
+ return "", err
+ }
+ switch reply := reply.(type) {
+ case []byte:
+ return string(reply), nil
+ case string:
+ return reply, nil
+ case nil:
+ return "", ErrNil
+ case Error:
+ return "", reply
+ }
+ return "", fmt.Errorf("redigo: unexpected type for String, got type %T", reply)
+}
+
+// Bytes is a helper that converts a command reply to a slice of bytes. If err
+// is not equal to nil, then Bytes returns nil, err. Otherwise Bytes converts
+// the reply to a slice of bytes as follows:
+//
+// Reply type Result
+// bulk string reply, nil
+// simple string []byte(reply), nil
+// nil nil, ErrNil
+// other nil, error
+func Bytes(reply interface{}, err error) ([]byte, error) {
+ if err != nil {
+ return nil, err
+ }
+ switch reply := reply.(type) {
+ case []byte:
+ return reply, nil
+ case string:
+ return []byte(reply), nil
+ case nil:
+ return nil, ErrNil
+ case Error:
+ return nil, reply
+ }
+ return nil, fmt.Errorf("redigo: unexpected type for Bytes, got type %T", reply)
+}
+
+// Bool is a helper that converts a command reply to a boolean. If err is not
+// equal to nil, then Bool returns false, err. Otherwise Bool converts the
+// reply to boolean as follows:
+//
+// Reply type Result
+// integer value != 0, nil
+// bulk string strconv.ParseBool(reply)
+// nil false, ErrNil
+// other false, error
+func Bool(reply interface{}, err error) (bool, error) {
+ if err != nil {
+ return false, err
+ }
+ switch reply := reply.(type) {
+ case int64:
+ return reply != 0, nil
+ case []byte:
+ return strconv.ParseBool(string(reply))
+ case nil:
+ return false, ErrNil
+ case Error:
+ return false, reply
+ }
+ return false, fmt.Errorf("redigo: unexpected type for Bool, got type %T", reply)
+}
+
+// MultiBulk is a helper that converts an array command reply to a []interface{}.
+//
+// Deprecated: Use Values instead.
+func MultiBulk(reply interface{}, err error) ([]interface{}, error) { return Values(reply, err) }
+
+// Values is a helper that converts an array command reply to a []interface{}.
+// If err is not equal to nil, then Values returns nil, err. Otherwise, Values
+// converts the reply as follows:
+//
+// Reply type Result
+// array reply, nil
+// nil nil, ErrNil
+// other nil, error
+func Values(reply interface{}, err error) ([]interface{}, error) {
+ if err != nil {
+ return nil, err
+ }
+ switch reply := reply.(type) {
+ case []interface{}:
+ return reply, nil
+ case nil:
+ return nil, ErrNil
+ case Error:
+ return nil, reply
+ }
+ return nil, fmt.Errorf("redigo: unexpected type for Values, got type %T", reply)
+}
+
+func sliceHelper(reply interface{}, err error, name string, makeSlice func(int), assign func(int, interface{}) error) error {
+ if err != nil {
+ return err
+ }
+ switch reply := reply.(type) {
+ case []interface{}:
+ makeSlice(len(reply))
+ for i := range reply {
+ if reply[i] == nil {
+ continue
+ }
+ if err := assign(i, reply[i]); err != nil {
+ return err
+ }
+ }
+ return nil
+ case nil:
+ return ErrNil
+ case Error:
+ return reply
+ }
+ return fmt.Errorf("redigo: unexpected type for %s, got type %T", name, reply)
+}
+
+// Float64s is a helper that converts an array command reply to a []float64. If
+// err is not equal to nil, then Float64s returns nil, err. Nil array items are
+// converted to 0 in the output slice. Floats64 returns an error if an array
+// item is not a bulk string or nil.
+func Float64s(reply interface{}, err error) ([]float64, error) {
+ var result []float64
+ err = sliceHelper(reply, err, "Float64s", func(n int) { result = make([]float64, n) }, func(i int, v interface{}) error {
+ p, ok := v.([]byte)
+ if !ok {
+ return fmt.Errorf("redigo: unexpected element type for Floats64, got type %T", v)
+ }
+ f, err := strconv.ParseFloat(string(p), 64)
+ result[i] = f
+ return err
+ })
+ return result, err
+}
+
+// Strings is a helper that converts an array command reply to a []string. If
+// err is not equal to nil, then Strings returns nil, err. Nil array items are
+// converted to "" in the output slice. Strings returns an error if an array
+// item is not a bulk string or nil.
+func Strings(reply interface{}, err error) ([]string, error) {
+ var result []string
+ err = sliceHelper(reply, err, "Strings", func(n int) { result = make([]string, n) }, func(i int, v interface{}) error {
+ switch v := v.(type) {
+ case string:
+ result[i] = v
+ return nil
+ case []byte:
+ result[i] = string(v)
+ return nil
+ default:
+ return fmt.Errorf("redigo: unexpected element type for Strings, got type %T", v)
+ }
+ })
+ return result, err
+}
+
+// ByteSlices is a helper that converts an array command reply to a [][]byte.
+// If err is not equal to nil, then ByteSlices returns nil, err. Nil array
+// items are stay nil. ByteSlices returns an error if an array item is not a
+// bulk string or nil.
+func ByteSlices(reply interface{}, err error) ([][]byte, error) {
+ var result [][]byte
+ err = sliceHelper(reply, err, "ByteSlices", func(n int) { result = make([][]byte, n) }, func(i int, v interface{}) error {
+ p, ok := v.([]byte)
+ if !ok {
+ return fmt.Errorf("redigo: unexpected element type for ByteSlices, got type %T", v)
+ }
+ result[i] = p
+ return nil
+ })
+ return result, err
+}
+
+// Int64s is a helper that converts an array command reply to a []int64.
+// If err is not equal to nil, then Int64s returns nil, err. Nil array
+// items are stay nil. Int64s returns an error if an array item is not a
+// bulk string or nil.
+func Int64s(reply interface{}, err error) ([]int64, error) {
+ var result []int64
+ err = sliceHelper(reply, err, "Int64s", func(n int) { result = make([]int64, n) }, func(i int, v interface{}) error {
+ switch v := v.(type) {
+ case int64:
+ result[i] = v
+ return nil
+ case []byte:
+ n, err := strconv.ParseInt(string(v), 10, 64)
+ result[i] = n
+ return err
+ default:
+ return fmt.Errorf("redigo: unexpected element type for Int64s, got type %T", v)
+ }
+ })
+ return result, err
+}
+
+// Ints is a helper that converts an array command reply to a []in.
+// If err is not equal to nil, then Ints returns nil, err. Nil array
+// items are stay nil. Ints returns an error if an array item is not a
+// bulk string or nil.
+func Ints(reply interface{}, err error) ([]int, error) {
+ var result []int
+ err = sliceHelper(reply, err, "Ints", func(n int) { result = make([]int, n) }, func(i int, v interface{}) error {
+ switch v := v.(type) {
+ case int64:
+ n := int(v)
+ if int64(n) != v {
+ return strconv.ErrRange
+ }
+ result[i] = n
+ return nil
+ case []byte:
+ n, err := strconv.Atoi(string(v))
+ result[i] = n
+ return err
+ default:
+ return fmt.Errorf("redigo: unexpected element type for Ints, got type %T", v)
+ }
+ })
+ return result, err
+}
+
+// StringMap is a helper that converts an array of strings (alternating key, value)
+// into a map[string]string. The HGETALL and CONFIG GET commands return replies in this format.
+// Requires an even number of values in result.
+func StringMap(result interface{}, err error) (map[string]string, error) {
+ values, err := Values(result, err)
+ if err != nil {
+ return nil, err
+ }
+ if len(values)%2 != 0 {
+ return nil, errors.New("redigo: StringMap expects even number of values result")
+ }
+ m := make(map[string]string, len(values)/2)
+ for i := 0; i < len(values); i += 2 {
+ key, okKey := values[i].([]byte)
+ value, okValue := values[i+1].([]byte)
+ if !okKey || !okValue {
+ return nil, errors.New("redigo: StringMap key not a bulk string value")
+ }
+ m[string(key)] = string(value)
+ }
+ return m, nil
+}
+
+// IntMap is a helper that converts an array of strings (alternating key, value)
+// into a map[string]int. The HGETALL commands return replies in this format.
+// Requires an even number of values in result.
+func IntMap(result interface{}, err error) (map[string]int, error) {
+ values, err := Values(result, err)
+ if err != nil {
+ return nil, err
+ }
+ if len(values)%2 != 0 {
+ return nil, errors.New("redigo: IntMap expects even number of values result")
+ }
+ m := make(map[string]int, len(values)/2)
+ for i := 0; i < len(values); i += 2 {
+ key, ok := values[i].([]byte)
+ if !ok {
+ return nil, errors.New("redigo: IntMap key not a bulk string value")
+ }
+ value, err := Int(values[i+1], nil)
+ if err != nil {
+ return nil, err
+ }
+ m[string(key)] = value
+ }
+ return m, nil
+}
+
+// Int64Map is a helper that converts an array of strings (alternating key, value)
+// into a map[string]int64. The HGETALL commands return replies in this format.
+// Requires an even number of values in result.
+func Int64Map(result interface{}, err error) (map[string]int64, error) {
+ values, err := Values(result, err)
+ if err != nil {
+ return nil, err
+ }
+ if len(values)%2 != 0 {
+ return nil, errors.New("redigo: Int64Map expects even number of values result")
+ }
+ m := make(map[string]int64, len(values)/2)
+ for i := 0; i < len(values); i += 2 {
+ key, ok := values[i].([]byte)
+ if !ok {
+ return nil, errors.New("redigo: Int64Map key not a bulk string value")
+ }
+ value, err := Int64(values[i+1], nil)
+ if err != nil {
+ return nil, err
+ }
+ m[string(key)] = value
+ }
+ return m, nil
+}
+
+// Positions is a helper that converts an array of positions (lat, long)
+// into a [][2]float64. The GEOPOS command returns replies in this format.
+func Positions(result interface{}, err error) ([]*[2]float64, error) {
+ values, err := Values(result, err)
+ if err != nil {
+ return nil, err
+ }
+ positions := make([]*[2]float64, len(values))
+ for i := range values {
+ if values[i] == nil {
+ continue
+ }
+ p, ok := values[i].([]interface{})
+ if !ok {
+ return nil, fmt.Errorf("redigo: unexpected element type for interface slice, got type %T", values[i])
+ }
+ if len(p) != 2 {
+ return nil, fmt.Errorf("redigo: unexpected number of values for a member position, got %d", len(p))
+ }
+ lat, err := Float64(p[0], nil)
+ if err != nil {
+ return nil, err
+ }
+ long, err := Float64(p[1], nil)
+ if err != nil {
+ return nil, err
+ }
+ positions[i] = &[2]float64{lat, long}
+ }
+ return positions, nil
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/scan.go b/vendor/github.com/gomodule/redigo/redis/scan.go
new file mode 100644
index 00000000..ef9551bd
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/scan.go
@@ -0,0 +1,585 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+func ensureLen(d reflect.Value, n int) {
+ if n > d.Cap() {
+ d.Set(reflect.MakeSlice(d.Type(), n, n))
+ } else {
+ d.SetLen(n)
+ }
+}
+
+func cannotConvert(d reflect.Value, s interface{}) error {
+ var sname string
+ switch s.(type) {
+ case string:
+ sname = "Redis simple string"
+ case Error:
+ sname = "Redis error"
+ case int64:
+ sname = "Redis integer"
+ case []byte:
+ sname = "Redis bulk string"
+ case []interface{}:
+ sname = "Redis array"
+ default:
+ sname = reflect.TypeOf(s).String()
+ }
+ return fmt.Errorf("cannot convert from %s to %s", sname, d.Type())
+}
+
+func convertAssignBulkString(d reflect.Value, s []byte) (err error) {
+ switch d.Type().Kind() {
+ case reflect.Float32, reflect.Float64:
+ var x float64
+ x, err = strconv.ParseFloat(string(s), d.Type().Bits())
+ d.SetFloat(x)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ var x int64
+ x, err = strconv.ParseInt(string(s), 10, d.Type().Bits())
+ d.SetInt(x)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ var x uint64
+ x, err = strconv.ParseUint(string(s), 10, d.Type().Bits())
+ d.SetUint(x)
+ case reflect.Bool:
+ var x bool
+ x, err = strconv.ParseBool(string(s))
+ d.SetBool(x)
+ case reflect.String:
+ d.SetString(string(s))
+ case reflect.Slice:
+ if d.Type().Elem().Kind() != reflect.Uint8 {
+ err = cannotConvert(d, s)
+ } else {
+ d.SetBytes(s)
+ }
+ default:
+ err = cannotConvert(d, s)
+ }
+ return
+}
+
+func convertAssignInt(d reflect.Value, s int64) (err error) {
+ switch d.Type().Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ d.SetInt(s)
+ if d.Int() != s {
+ err = strconv.ErrRange
+ d.SetInt(0)
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ if s < 0 {
+ err = strconv.ErrRange
+ } else {
+ x := uint64(s)
+ d.SetUint(x)
+ if d.Uint() != x {
+ err = strconv.ErrRange
+ d.SetUint(0)
+ }
+ }
+ case reflect.Bool:
+ d.SetBool(s != 0)
+ default:
+ err = cannotConvert(d, s)
+ }
+ return
+}
+
+func convertAssignValue(d reflect.Value, s interface{}) (err error) {
+ if d.Kind() != reflect.Ptr {
+ if d.CanAddr() {
+ d2 := d.Addr()
+ if d2.CanInterface() {
+ if scanner, ok := d2.Interface().(Scanner); ok {
+ return scanner.RedisScan(s)
+ }
+ }
+ }
+ } else if d.CanInterface() {
+ // Already a reflect.Ptr
+ if d.IsNil() {
+ d.Set(reflect.New(d.Type().Elem()))
+ }
+ if scanner, ok := d.Interface().(Scanner); ok {
+ return scanner.RedisScan(s)
+ }
+ }
+
+ switch s := s.(type) {
+ case []byte:
+ err = convertAssignBulkString(d, s)
+ case int64:
+ err = convertAssignInt(d, s)
+ default:
+ err = cannotConvert(d, s)
+ }
+ return err
+}
+
+func convertAssignArray(d reflect.Value, s []interface{}) error {
+ if d.Type().Kind() != reflect.Slice {
+ return cannotConvert(d, s)
+ }
+ ensureLen(d, len(s))
+ for i := 0; i < len(s); i++ {
+ if err := convertAssignValue(d.Index(i), s[i]); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func convertAssign(d interface{}, s interface{}) (err error) {
+ if scanner, ok := d.(Scanner); ok {
+ return scanner.RedisScan(s)
+ }
+
+ // Handle the most common destination types using type switches and
+ // fall back to reflection for all other types.
+ switch s := s.(type) {
+ case nil:
+ // ignore
+ case []byte:
+ switch d := d.(type) {
+ case *string:
+ *d = string(s)
+ case *int:
+ *d, err = strconv.Atoi(string(s))
+ case *bool:
+ *d, err = strconv.ParseBool(string(s))
+ case *[]byte:
+ *d = s
+ case *interface{}:
+ *d = s
+ case nil:
+ // skip value
+ default:
+ if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
+ err = cannotConvert(d, s)
+ } else {
+ err = convertAssignBulkString(d.Elem(), s)
+ }
+ }
+ case int64:
+ switch d := d.(type) {
+ case *int:
+ x := int(s)
+ if int64(x) != s {
+ err = strconv.ErrRange
+ x = 0
+ }
+ *d = x
+ case *bool:
+ *d = s != 0
+ case *interface{}:
+ *d = s
+ case nil:
+ // skip value
+ default:
+ if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
+ err = cannotConvert(d, s)
+ } else {
+ err = convertAssignInt(d.Elem(), s)
+ }
+ }
+ case string:
+ switch d := d.(type) {
+ case *string:
+ *d = s
+ case *interface{}:
+ *d = s
+ case nil:
+ // skip value
+ default:
+ err = cannotConvert(reflect.ValueOf(d), s)
+ }
+ case []interface{}:
+ switch d := d.(type) {
+ case *[]interface{}:
+ *d = s
+ case *interface{}:
+ *d = s
+ case nil:
+ // skip value
+ default:
+ if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
+ err = cannotConvert(d, s)
+ } else {
+ err = convertAssignArray(d.Elem(), s)
+ }
+ }
+ case Error:
+ err = s
+ default:
+ err = cannotConvert(reflect.ValueOf(d), s)
+ }
+ return
+}
+
+// Scan copies from src to the values pointed at by dest.
+//
+// Scan uses RedisScan if available otherwise:
+//
+// The values pointed at by dest must be an integer, float, boolean, string,
+// []byte, interface{} or slices of these types. Scan uses the standard strconv
+// package to convert bulk strings to numeric and boolean types.
+//
+// If a dest value is nil, then the corresponding src value is skipped.
+//
+// If a src element is nil, then the corresponding dest value is not modified.
+//
+// To enable easy use of Scan in a loop, Scan returns the slice of src
+// following the copied values.
+func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
+ if len(src) < len(dest) {
+ return nil, errors.New("redigo.Scan: array short")
+ }
+ var err error
+ for i, d := range dest {
+ err = convertAssign(d, src[i])
+ if err != nil {
+ err = fmt.Errorf("redigo.Scan: cannot assign to dest %d: %v", i, err)
+ break
+ }
+ }
+ return src[len(dest):], err
+}
+
+type fieldSpec struct {
+ name string
+ index []int
+ omitEmpty bool
+}
+
+type structSpec struct {
+ m map[string]*fieldSpec
+ l []*fieldSpec
+}
+
+func (ss *structSpec) fieldSpec(name []byte) *fieldSpec {
+ return ss.m[string(name)]
+}
+
+func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *structSpec) {
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ switch {
+ case f.PkgPath != "" && !f.Anonymous:
+ // Ignore unexported fields.
+ case f.Anonymous:
+ // TODO: Handle pointers. Requires change to decoder and
+ // protection against infinite recursion.
+ if f.Type.Kind() == reflect.Struct {
+ compileStructSpec(f.Type, depth, append(index, i), ss)
+ }
+ default:
+ fs := &fieldSpec{name: f.Name}
+ tag := f.Tag.Get("redis")
+ p := strings.Split(tag, ",")
+ if len(p) > 0 {
+ if p[0] == "-" {
+ continue
+ }
+ if len(p[0]) > 0 {
+ fs.name = p[0]
+ }
+ for _, s := range p[1:] {
+ switch s {
+ case "omitempty":
+ fs.omitEmpty = true
+ default:
+ panic(fmt.Errorf("redigo: unknown field tag %s for type %s", s, t.Name()))
+ }
+ }
+ }
+ d, found := depth[fs.name]
+ if !found {
+ d = 1 << 30
+ }
+ switch {
+ case len(index) == d:
+ // At same depth, remove from result.
+ delete(ss.m, fs.name)
+ j := 0
+ for i := 0; i < len(ss.l); i++ {
+ if fs.name != ss.l[i].name {
+ ss.l[j] = ss.l[i]
+ j += 1
+ }
+ }
+ ss.l = ss.l[:j]
+ case len(index) < d:
+ fs.index = make([]int, len(index)+1)
+ copy(fs.index, index)
+ fs.index[len(index)] = i
+ depth[fs.name] = len(index)
+ ss.m[fs.name] = fs
+ ss.l = append(ss.l, fs)
+ }
+ }
+ }
+}
+
+var (
+ structSpecMutex sync.RWMutex
+ structSpecCache = make(map[reflect.Type]*structSpec)
+ defaultFieldSpec = &fieldSpec{}
+)
+
+func structSpecForType(t reflect.Type) *structSpec {
+
+ structSpecMutex.RLock()
+ ss, found := structSpecCache[t]
+ structSpecMutex.RUnlock()
+ if found {
+ return ss
+ }
+
+ structSpecMutex.Lock()
+ defer structSpecMutex.Unlock()
+ ss, found = structSpecCache[t]
+ if found {
+ return ss
+ }
+
+ ss = &structSpec{m: make(map[string]*fieldSpec)}
+ compileStructSpec(t, make(map[string]int), nil, ss)
+ structSpecCache[t] = ss
+ return ss
+}
+
+var errScanStructValue = errors.New("redigo.ScanStruct: value must be non-nil pointer to a struct")
+
+// ScanStruct scans alternating names and values from src to a struct. The
+// HGETALL and CONFIG GET commands return replies in this format.
+//
+// ScanStruct uses exported field names to match values in the response. Use
+// 'redis' field tag to override the name:
+//
+// Field int `redis:"myName"`
+//
+// Fields with the tag redis:"-" are ignored.
+//
+// Each field uses RedisScan if available otherwise:
+// Integer, float, boolean, string and []byte fields are supported. Scan uses the
+// standard strconv package to convert bulk string values to numeric and
+// boolean types.
+//
+// If a src element is nil, then the corresponding field is not modified.
+func ScanStruct(src []interface{}, dest interface{}) error {
+ d := reflect.ValueOf(dest)
+ if d.Kind() != reflect.Ptr || d.IsNil() {
+ return errScanStructValue
+ }
+ d = d.Elem()
+ if d.Kind() != reflect.Struct {
+ return errScanStructValue
+ }
+ ss := structSpecForType(d.Type())
+
+ if len(src)%2 != 0 {
+ return errors.New("redigo.ScanStruct: number of values not a multiple of 2")
+ }
+
+ for i := 0; i < len(src); i += 2 {
+ s := src[i+1]
+ if s == nil {
+ continue
+ }
+ name, ok := src[i].([]byte)
+ if !ok {
+ return fmt.Errorf("redigo.ScanStruct: key %d not a bulk string value", i)
+ }
+ fs := ss.fieldSpec(name)
+ if fs == nil {
+ continue
+ }
+ if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
+ return fmt.Errorf("redigo.ScanStruct: cannot assign field %s: %v", fs.name, err)
+ }
+ }
+ return nil
+}
+
+var (
+ errScanSliceValue = errors.New("redigo.ScanSlice: dest must be non-nil pointer to a struct")
+)
+
+// ScanSlice scans src to the slice pointed to by dest. The elements the dest
+// slice must be integer, float, boolean, string, struct or pointer to struct
+// values.
+//
+// Struct fields must be integer, float, boolean or string values. All struct
+// fields are used unless a subset is specified using fieldNames.
+func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error {
+ d := reflect.ValueOf(dest)
+ if d.Kind() != reflect.Ptr || d.IsNil() {
+ return errScanSliceValue
+ }
+ d = d.Elem()
+ if d.Kind() != reflect.Slice {
+ return errScanSliceValue
+ }
+
+ isPtr := false
+ t := d.Type().Elem()
+ if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
+ isPtr = true
+ t = t.Elem()
+ }
+
+ if t.Kind() != reflect.Struct {
+ ensureLen(d, len(src))
+ for i, s := range src {
+ if s == nil {
+ continue
+ }
+ if err := convertAssignValue(d.Index(i), s); err != nil {
+ return fmt.Errorf("redigo.ScanSlice: cannot assign element %d: %v", i, err)
+ }
+ }
+ return nil
+ }
+
+ ss := structSpecForType(t)
+ fss := ss.l
+ if len(fieldNames) > 0 {
+ fss = make([]*fieldSpec, len(fieldNames))
+ for i, name := range fieldNames {
+ fss[i] = ss.m[name]
+ if fss[i] == nil {
+ return fmt.Errorf("redigo.ScanSlice: ScanSlice bad field name %s", name)
+ }
+ }
+ }
+
+ if len(fss) == 0 {
+ return errors.New("redigo.ScanSlice: no struct fields")
+ }
+
+ n := len(src) / len(fss)
+ if n*len(fss) != len(src) {
+ return errors.New("redigo.ScanSlice: length not a multiple of struct field count")
+ }
+
+ ensureLen(d, n)
+ for i := 0; i < n; i++ {
+ d := d.Index(i)
+ if isPtr {
+ if d.IsNil() {
+ d.Set(reflect.New(t))
+ }
+ d = d.Elem()
+ }
+ for j, fs := range fss {
+ s := src[i*len(fss)+j]
+ if s == nil {
+ continue
+ }
+ if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
+ return fmt.Errorf("redigo.ScanSlice: cannot assign element %d to field %s: %v", i*len(fss)+j, fs.name, err)
+ }
+ }
+ }
+ return nil
+}
+
+// Args is a helper for constructing command arguments from structured values.
+type Args []interface{}
+
+// Add returns the result of appending value to args.
+func (args Args) Add(value ...interface{}) Args {
+ return append(args, value...)
+}
+
+// AddFlat returns the result of appending the flattened value of v to args.
+//
+// Maps are flattened by appending the alternating keys and map values to args.
+//
+// Slices are flattened by appending the slice elements to args.
+//
+// Structs are flattened by appending the alternating names and values of
+// exported fields to args. If v is a nil struct pointer, then nothing is
+// appended. The 'redis' field tag overrides struct field names. See ScanStruct
+// for more information on the use of the 'redis' field tag.
+//
+// Other types are appended to args as is.
+func (args Args) AddFlat(v interface{}) Args {
+ rv := reflect.ValueOf(v)
+ switch rv.Kind() {
+ case reflect.Struct:
+ args = flattenStruct(args, rv)
+ case reflect.Slice:
+ for i := 0; i < rv.Len(); i++ {
+ args = append(args, rv.Index(i).Interface())
+ }
+ case reflect.Map:
+ for _, k := range rv.MapKeys() {
+ args = append(args, k.Interface(), rv.MapIndex(k).Interface())
+ }
+ case reflect.Ptr:
+ if rv.Type().Elem().Kind() == reflect.Struct {
+ if !rv.IsNil() {
+ args = flattenStruct(args, rv.Elem())
+ }
+ } else {
+ args = append(args, v)
+ }
+ default:
+ args = append(args, v)
+ }
+ return args
+}
+
+func flattenStruct(args Args, v reflect.Value) Args {
+ ss := structSpecForType(v.Type())
+ for _, fs := range ss.l {
+ fv := v.FieldByIndex(fs.index)
+ if fs.omitEmpty {
+ var empty = false
+ switch fv.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ empty = fv.Len() == 0
+ case reflect.Bool:
+ empty = !fv.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ empty = fv.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ empty = fv.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ empty = fv.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ empty = fv.IsNil()
+ }
+ if empty {
+ continue
+ }
+ }
+ args = append(args, fs.name, fv.Interface())
+ }
+ return args
+}
diff --git a/vendor/github.com/gomodule/redigo/redis/script.go b/vendor/github.com/gomodule/redigo/redis/script.go
new file mode 100644
index 00000000..0ef1c821
--- /dev/null
+++ b/vendor/github.com/gomodule/redigo/redis/script.go
@@ -0,0 +1,91 @@
+// Copyright 2012 Gary Burd
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package redis
+
+import (
+ "crypto/sha1"
+ "encoding/hex"
+ "io"
+ "strings"
+)
+
+// Script encapsulates the source, hash and key count for a Lua script. See
+// http://redis.io/commands/eval for information on scripts in Redis.
+type Script struct {
+ keyCount int
+ src string
+ hash string
+}
+
+// NewScript returns a new script object. If keyCount is greater than or equal
+// to zero, then the count is automatically inserted in the EVAL command
+// argument list. If keyCount is less than zero, then the application supplies
+// the count as the first value in the keysAndArgs argument to the Do, Send and
+// SendHash methods.
+func NewScript(keyCount int, src string) *Script {
+ h := sha1.New()
+ io.WriteString(h, src)
+ return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))}
+}
+
+func (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} {
+ var args []interface{}
+ if s.keyCount < 0 {
+ args = make([]interface{}, 1+len(keysAndArgs))
+ args[0] = spec
+ copy(args[1:], keysAndArgs)
+ } else {
+ args = make([]interface{}, 2+len(keysAndArgs))
+ args[0] = spec
+ args[1] = s.keyCount
+ copy(args[2:], keysAndArgs)
+ }
+ return args
+}
+
+// Hash returns the script hash.
+func (s *Script) Hash() string {
+ return s.hash
+}
+
+// Do evaluates the script. Under the covers, Do optimistically evaluates the
+// script using the EVALSHA command. If the command fails because the script is
+// not loaded, then Do evaluates the script using the EVAL command (thus
+// causing the script to load).
+func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) {
+ v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...)
+ if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") {
+ v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...)
+ }
+ return v, err
+}
+
+// SendHash evaluates the script without waiting for the reply. The script is
+// evaluated with the EVALSHA command. The application must ensure that the
+// script is loaded by a previous call to Send, Do or Load methods.
+func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error {
+ return c.Send("EVALSHA", s.args(s.hash, keysAndArgs)...)
+}
+
+// Send evaluates the script without waiting for the reply.
+func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error {
+ return c.Send("EVAL", s.args(s.src, keysAndArgs)...)
+}
+
+// Load loads the script without evaluating it.
+func (s *Script) Load(c Conn) error {
+ _, err := c.Do("SCRIPT", "LOAD", s.src)
+ return err
+}
diff --git a/vendor/github.com/gorilla/context/LICENSE b/vendor/github.com/gorilla/context/LICENSE
new file mode 100644
index 00000000..0e5fb872
--- /dev/null
+++ b/vendor/github.com/gorilla/context/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/gorilla/context/context.go b/vendor/github.com/gorilla/context/context.go
new file mode 100644
index 00000000..81cb128b
--- /dev/null
+++ b/vendor/github.com/gorilla/context/context.go
@@ -0,0 +1,143 @@
+// Copyright 2012 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package context
+
+import (
+ "net/http"
+ "sync"
+ "time"
+)
+
+var (
+ mutex sync.RWMutex
+ data = make(map[*http.Request]map[interface{}]interface{})
+ datat = make(map[*http.Request]int64)
+)
+
+// Set stores a value for a given key in a given request.
+func Set(r *http.Request, key, val interface{}) {
+ mutex.Lock()
+ if data[r] == nil {
+ data[r] = make(map[interface{}]interface{})
+ datat[r] = time.Now().Unix()
+ }
+ data[r][key] = val
+ mutex.Unlock()
+}
+
+// Get returns a value stored for a given key in a given request.
+func Get(r *http.Request, key interface{}) interface{} {
+ mutex.RLock()
+ if ctx := data[r]; ctx != nil {
+ value := ctx[key]
+ mutex.RUnlock()
+ return value
+ }
+ mutex.RUnlock()
+ return nil
+}
+
+// GetOk returns stored value and presence state like multi-value return of map access.
+func GetOk(r *http.Request, key interface{}) (interface{}, bool) {
+ mutex.RLock()
+ if _, ok := data[r]; ok {
+ value, ok := data[r][key]
+ mutex.RUnlock()
+ return value, ok
+ }
+ mutex.RUnlock()
+ return nil, false
+}
+
+// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests.
+func GetAll(r *http.Request) map[interface{}]interface{} {
+ mutex.RLock()
+ if context, ok := data[r]; ok {
+ result := make(map[interface{}]interface{}, len(context))
+ for k, v := range context {
+ result[k] = v
+ }
+ mutex.RUnlock()
+ return result
+ }
+ mutex.RUnlock()
+ return nil
+}
+
+// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if
+// the request was registered.
+func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) {
+ mutex.RLock()
+ context, ok := data[r]
+ result := make(map[interface{}]interface{}, len(context))
+ for k, v := range context {
+ result[k] = v
+ }
+ mutex.RUnlock()
+ return result, ok
+}
+
+// Delete removes a value stored for a given key in a given request.
+func Delete(r *http.Request, key interface{}) {
+ mutex.Lock()
+ if data[r] != nil {
+ delete(data[r], key)
+ }
+ mutex.Unlock()
+}
+
+// Clear removes all values stored for a given request.
+//
+// This is usually called by a handler wrapper to clean up request
+// variables at the end of a request lifetime. See ClearHandler().
+func Clear(r *http.Request) {
+ mutex.Lock()
+ clear(r)
+ mutex.Unlock()
+}
+
+// clear is Clear without the lock.
+func clear(r *http.Request) {
+ delete(data, r)
+ delete(datat, r)
+}
+
+// Purge removes request data stored for longer than maxAge, in seconds.
+// It returns the amount of requests removed.
+//
+// If maxAge <= 0, all request data is removed.
+//
+// This is only used for sanity check: in case context cleaning was not
+// properly set some request data can be kept forever, consuming an increasing
+// amount of memory. In case this is detected, Purge() must be called
+// periodically until the problem is fixed.
+func Purge(maxAge int) int {
+ mutex.Lock()
+ count := 0
+ if maxAge <= 0 {
+ count = len(data)
+ data = make(map[*http.Request]map[interface{}]interface{})
+ datat = make(map[*http.Request]int64)
+ } else {
+ min := time.Now().Unix() - int64(maxAge)
+ for r := range data {
+ if datat[r] < min {
+ clear(r)
+ count++
+ }
+ }
+ }
+ mutex.Unlock()
+ return count
+}
+
+// ClearHandler wraps an http.Handler and clears request values at the end
+// of a request lifetime.
+func ClearHandler(h http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ defer Clear(r)
+ h.ServeHTTP(w, r)
+ })
+}
diff --git a/vendor/github.com/gorilla/context/doc.go b/vendor/github.com/gorilla/context/doc.go
new file mode 100644
index 00000000..448d1bfc
--- /dev/null
+++ b/vendor/github.com/gorilla/context/doc.go
@@ -0,0 +1,88 @@
+// Copyright 2012 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package context stores values shared during a request lifetime.
+
+Note: gorilla/context, having been born well before `context.Context` existed,
+does not play well > with the shallow copying of the request that
+[`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext)
+(added to net/http Go 1.7 onwards) performs. You should either use *just*
+gorilla/context, or moving forward, the new `http.Request.Context()`.
+
+For example, a router can set variables extracted from the URL and later
+application handlers can access those values, or it can be used to store
+sessions values to be saved at the end of a request. There are several
+others common uses.
+
+The idea was posted by Brad Fitzpatrick to the go-nuts mailing list:
+
+ http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53
+
+Here's the basic usage: first define the keys that you will need. The key
+type is interface{} so a key can be of any type that supports equality.
+Here we define a key using a custom int type to avoid name collisions:
+
+ package foo
+
+ import (
+ "github.com/gorilla/context"
+ )
+
+ type key int
+
+ const MyKey key = 0
+
+Then set a variable. Variables are bound to an http.Request object, so you
+need a request instance to set a value:
+
+ context.Set(r, MyKey, "bar")
+
+The application can later access the variable using the same key you provided:
+
+ func MyHandler(w http.ResponseWriter, r *http.Request) {
+ // val is "bar".
+ val := context.Get(r, foo.MyKey)
+
+ // returns ("bar", true)
+ val, ok := context.GetOk(r, foo.MyKey)
+ // ...
+ }
+
+And that's all about the basic usage. We discuss some other ideas below.
+
+Any type can be stored in the context. To enforce a given type, make the key
+private and wrap Get() and Set() to accept and return values of a specific
+type:
+
+ type key int
+
+ const mykey key = 0
+
+ // GetMyKey returns a value for this package from the request values.
+ func GetMyKey(r *http.Request) SomeType {
+ if rv := context.Get(r, mykey); rv != nil {
+ return rv.(SomeType)
+ }
+ return nil
+ }
+
+ // SetMyKey sets a value for this package in the request values.
+ func SetMyKey(r *http.Request, val SomeType) {
+ context.Set(r, mykey, val)
+ }
+
+Variables must be cleared at the end of a request, to remove all values
+that were stored. This can be done in an http.Handler, after a request was
+served. Just call Clear() passing the request:
+
+ context.Clear(r)
+
+...or use ClearHandler(), which conveniently wraps an http.Handler to clear
+variables at the end of a request lifetime.
+
+The Routers from the packages gorilla/mux and gorilla/pat call Clear()
+so if you are using either of them you don't need to clear the context manually.
+*/
+package context
diff --git a/vendor/github.com/gorilla/mux/LICENSE b/vendor/github.com/gorilla/mux/LICENSE
new file mode 100644
index 00000000..0e5fb872
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/gorilla/mux/context_gorilla.go b/vendor/github.com/gorilla/mux/context_gorilla.go
new file mode 100644
index 00000000..d7adaa8f
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/context_gorilla.go
@@ -0,0 +1,26 @@
+// +build !go1.7
+
+package mux
+
+import (
+ "net/http"
+
+ "github.com/gorilla/context"
+)
+
+func contextGet(r *http.Request, key interface{}) interface{} {
+ return context.Get(r, key)
+}
+
+func contextSet(r *http.Request, key, val interface{}) *http.Request {
+ if val == nil {
+ return r
+ }
+
+ context.Set(r, key, val)
+ return r
+}
+
+func contextClear(r *http.Request) {
+ context.Clear(r)
+}
diff --git a/vendor/github.com/gorilla/mux/context_native.go b/vendor/github.com/gorilla/mux/context_native.go
new file mode 100644
index 00000000..209cbea7
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/context_native.go
@@ -0,0 +1,24 @@
+// +build go1.7
+
+package mux
+
+import (
+ "context"
+ "net/http"
+)
+
+func contextGet(r *http.Request, key interface{}) interface{} {
+ return r.Context().Value(key)
+}
+
+func contextSet(r *http.Request, key, val interface{}) *http.Request {
+ if val == nil {
+ return r
+ }
+
+ return r.WithContext(context.WithValue(r.Context(), key, val))
+}
+
+func contextClear(r *http.Request) {
+ return
+}
diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go
new file mode 100644
index 00000000..38957dee
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/doc.go
@@ -0,0 +1,306 @@
+// Copyright 2012 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package mux implements a request router and dispatcher.
+
+The name mux stands for "HTTP request multiplexer". Like the standard
+http.ServeMux, mux.Router matches incoming requests against a list of
+registered routes and calls a handler for the route that matches the URL
+or other conditions. The main features are:
+
+ * Requests can be matched based on URL host, path, path prefix, schemes,
+ header and query values, HTTP methods or using custom matchers.
+ * URL hosts, paths and query values can have variables with an optional
+ regular expression.
+ * Registered URLs can be built, or "reversed", which helps maintaining
+ references to resources.
+ * Routes can be used as subrouters: nested routes are only tested if the
+ parent route matches. This is useful to define groups of routes that
+ share common conditions like a host, a path prefix or other repeated
+ attributes. As a bonus, this optimizes request matching.
+ * It implements the http.Handler interface so it is compatible with the
+ standard http.ServeMux.
+
+Let's start registering a couple of URL paths and handlers:
+
+ func main() {
+ r := mux.NewRouter()
+ r.HandleFunc("/", HomeHandler)
+ r.HandleFunc("/products", ProductsHandler)
+ r.HandleFunc("/articles", ArticlesHandler)
+ http.Handle("/", r)
+ }
+
+Here we register three routes mapping URL paths to handlers. This is
+equivalent to how http.HandleFunc() works: if an incoming request URL matches
+one of the paths, the corresponding handler is called passing
+(http.ResponseWriter, *http.Request) as parameters.
+
+Paths can have variables. They are defined using the format {name} or
+{name:pattern}. If a regular expression pattern is not defined, the matched
+variable will be anything until the next slash. For example:
+
+ r := mux.NewRouter()
+ r.HandleFunc("/products/{key}", ProductHandler)
+ r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
+ r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
+
+Groups can be used inside patterns, as long as they are non-capturing (?:re). For example:
+
+ r.HandleFunc("/articles/{category}/{sort:(?:asc|desc|new)}", ArticlesCategoryHandler)
+
+The names are used to create a map of route variables which can be retrieved
+calling mux.Vars():
+
+ vars := mux.Vars(request)
+ category := vars["category"]
+
+Note that if any capturing groups are present, mux will panic() during parsing. To prevent
+this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to
+"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably
+when capturing groups were present.
+
+And this is all you need to know about the basic usage. More advanced options
+are explained below.
+
+Routes can also be restricted to a domain or subdomain. Just define a host
+pattern to be matched. They can also have variables:
+
+ r := mux.NewRouter()
+ // Only matches if domain is "www.example.com".
+ r.Host("www.example.com")
+ // Matches a dynamic subdomain.
+ r.Host("{subdomain:[a-z]+}.domain.com")
+
+There are several other matchers that can be added. To match path prefixes:
+
+ r.PathPrefix("/products/")
+
+...or HTTP methods:
+
+ r.Methods("GET", "POST")
+
+...or URL schemes:
+
+ r.Schemes("https")
+
+...or header values:
+
+ r.Headers("X-Requested-With", "XMLHttpRequest")
+
+...or query values:
+
+ r.Queries("key", "value")
+
+...or to use a custom matcher function:
+
+ r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool {
+ return r.ProtoMajor == 0
+ })
+
+...and finally, it is possible to combine several matchers in a single route:
+
+ r.HandleFunc("/products", ProductsHandler).
+ Host("www.example.com").
+ Methods("GET").
+ Schemes("http")
+
+Setting the same matching conditions again and again can be boring, so we have
+a way to group several routes that share the same requirements.
+We call it "subrouting".
+
+For example, let's say we have several URLs that should only match when the
+host is "www.example.com". Create a route for that host and get a "subrouter"
+from it:
+
+ r := mux.NewRouter()
+ s := r.Host("www.example.com").Subrouter()
+
+Then register routes in the subrouter:
+
+ s.HandleFunc("/products/", ProductsHandler)
+ s.HandleFunc("/products/{key}", ProductHandler)
+ s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
+
+The three URL paths we registered above will only be tested if the domain is
+"www.example.com", because the subrouter is tested first. This is not
+only convenient, but also optimizes request matching. You can create
+subrouters combining any attribute matchers accepted by a route.
+
+Subrouters can be used to create domain or path "namespaces": you define
+subrouters in a central place and then parts of the app can register its
+paths relatively to a given subrouter.
+
+There's one more thing about subroutes. When a subrouter has a path prefix,
+the inner routes use it as base for their paths:
+
+ r := mux.NewRouter()
+ s := r.PathPrefix("/products").Subrouter()
+ // "/products/"
+ s.HandleFunc("/", ProductsHandler)
+ // "/products/{key}/"
+ s.HandleFunc("/{key}/", ProductHandler)
+ // "/products/{key}/details"
+ s.HandleFunc("/{key}/details", ProductDetailsHandler)
+
+Note that the path provided to PathPrefix() represents a "wildcard": calling
+PathPrefix("/static/").Handler(...) means that the handler will be passed any
+request that matches "/static/*". This makes it easy to serve static files with mux:
+
+ func main() {
+ var dir string
+
+ flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir")
+ flag.Parse()
+ r := mux.NewRouter()
+
+ // This will serve files under http://localhost:8000/static/
+ r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(dir))))
+
+ srv := &http.Server{
+ Handler: r,
+ Addr: "127.0.0.1:8000",
+ // Good practice: enforce timeouts for servers you create!
+ WriteTimeout: 15 * time.Second,
+ ReadTimeout: 15 * time.Second,
+ }
+
+ log.Fatal(srv.ListenAndServe())
+ }
+
+Now let's see how to build registered URLs.
+
+Routes can be named. All routes that define a name can have their URLs built,
+or "reversed". We define a name calling Name() on a route. For example:
+
+ r := mux.NewRouter()
+ r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+ Name("article")
+
+To build a URL, get the route and call the URL() method, passing a sequence of
+key/value pairs for the route variables. For the previous route, we would do:
+
+ url, err := r.Get("article").URL("category", "technology", "id", "42")
+
+...and the result will be a url.URL with the following path:
+
+ "/articles/technology/42"
+
+This also works for host and query value variables:
+
+ r := mux.NewRouter()
+ r.Host("{subdomain}.domain.com").
+ Path("/articles/{category}/{id:[0-9]+}").
+ Queries("filter", "{filter}").
+ HandlerFunc(ArticleHandler).
+ Name("article")
+
+ // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla"
+ url, err := r.Get("article").URL("subdomain", "news",
+ "category", "technology",
+ "id", "42",
+ "filter", "gorilla")
+
+All variables defined in the route are required, and their values must
+conform to the corresponding patterns. These requirements guarantee that a
+generated URL will always match a registered route -- the only exception is
+for explicitly defined "build-only" routes which never match.
+
+Regex support also exists for matching Headers within a route. For example, we could do:
+
+ r.HeadersRegexp("Content-Type", "application/(text|json)")
+
+...and the route will match both requests with a Content-Type of `application/json` as well as
+`application/text`
+
+There's also a way to build only the URL host or path for a route:
+use the methods URLHost() or URLPath() instead. For the previous route,
+we would do:
+
+ // "http://news.domain.com/"
+ host, err := r.Get("article").URLHost("subdomain", "news")
+
+ // "/articles/technology/42"
+ path, err := r.Get("article").URLPath("category", "technology", "id", "42")
+
+And if you use subrouters, host and path defined separately can be built
+as well:
+
+ r := mux.NewRouter()
+ s := r.Host("{subdomain}.domain.com").Subrouter()
+ s.Path("/articles/{category}/{id:[0-9]+}").
+ HandlerFunc(ArticleHandler).
+ Name("article")
+
+ // "http://news.domain.com/articles/technology/42"
+ url, err := r.Get("article").URL("subdomain", "news",
+ "category", "technology",
+ "id", "42")
+
+Mux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking.
+
+ type MiddlewareFunc func(http.Handler) http.Handler
+
+Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed to it, and then calls the handler passed as parameter to the MiddlewareFunc (closures can access variables from the context where they are created).
+
+A very basic middleware which logs the URI of the request being handled could be written as:
+
+ func simpleMw(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ // Do stuff here
+ log.Println(r.RequestURI)
+ // Call the next handler, which can be another middleware in the chain, or the final handler.
+ next.ServeHTTP(w, r)
+ })
+ }
+
+Middlewares can be added to a router using `Router.Use()`:
+
+ r := mux.NewRouter()
+ r.HandleFunc("/", handler)
+ r.Use(simpleMw)
+
+A more complex authentication middleware, which maps session token to users, could be written as:
+
+ // Define our struct
+ type authenticationMiddleware struct {
+ tokenUsers map[string]string
+ }
+
+ // Initialize it somewhere
+ func (amw *authenticationMiddleware) Populate() {
+ amw.tokenUsers["00000000"] = "user0"
+ amw.tokenUsers["aaaaaaaa"] = "userA"
+ amw.tokenUsers["05f717e5"] = "randomUser"
+ amw.tokenUsers["deadbeef"] = "user0"
+ }
+
+ // Middleware function, which will be called for each request
+ func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ token := r.Header.Get("X-Session-Token")
+
+ if user, found := amw.tokenUsers[token]; found {
+ // We found the token in our map
+ log.Printf("Authenticated user %s\n", user)
+ next.ServeHTTP(w, r)
+ } else {
+ http.Error(w, "Forbidden", http.StatusForbidden)
+ }
+ })
+ }
+
+ r := mux.NewRouter()
+ r.HandleFunc("/", handler)
+
+ amw := authenticationMiddleware{}
+ amw.Populate()
+
+ r.Use(amw.Middleware)
+
+Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to.
+
+*/
+package mux
diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go
new file mode 100644
index 00000000..ceb812ce
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/middleware.go
@@ -0,0 +1,72 @@
+package mux
+
+import (
+ "net/http"
+ "strings"
+)
+
+// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler.
+// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed
+// to it, and then calls the handler passed as parameter to the MiddlewareFunc.
+type MiddlewareFunc func(http.Handler) http.Handler
+
+// middleware interface is anything which implements a MiddlewareFunc named Middleware.
+type middleware interface {
+ Middleware(handler http.Handler) http.Handler
+}
+
+// Middleware allows MiddlewareFunc to implement the middleware interface.
+func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler {
+ return mw(handler)
+}
+
+// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.
+func (r *Router) Use(mwf ...MiddlewareFunc) {
+ for _, fn := range mwf {
+ r.middlewares = append(r.middlewares, fn)
+ }
+}
+
+// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.
+func (r *Router) useInterface(mw middleware) {
+ r.middlewares = append(r.middlewares, mw)
+}
+
+// CORSMethodMiddleware sets the Access-Control-Allow-Methods response header
+// on a request, by matching routes based only on paths. It also handles
+// OPTIONS requests, by settings Access-Control-Allow-Methods, and then
+// returning without calling the next http handler.
+func CORSMethodMiddleware(r *Router) MiddlewareFunc {
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ var allMethods []string
+
+ err := r.Walk(func(route *Route, _ *Router, _ []*Route) error {
+ for _, m := range route.matchers {
+ if _, ok := m.(*routeRegexp); ok {
+ if m.Match(req, &RouteMatch{}) {
+ methods, err := route.GetMethods()
+ if err != nil {
+ return err
+ }
+
+ allMethods = append(allMethods, methods...)
+ }
+ break
+ }
+ }
+ return nil
+ })
+
+ if err == nil {
+ w.Header().Set("Access-Control-Allow-Methods", strings.Join(append(allMethods, "OPTIONS"), ","))
+
+ if req.Method == "OPTIONS" {
+ return
+ }
+ }
+
+ next.ServeHTTP(w, req)
+ })
+ }
+}
diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go
new file mode 100644
index 00000000..4bbafa51
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/mux.go
@@ -0,0 +1,588 @@
+// Copyright 2012 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mux
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "path"
+ "regexp"
+)
+
+var (
+ // ErrMethodMismatch is returned when the method in the request does not match
+ // the method defined against the route.
+ ErrMethodMismatch = errors.New("method is not allowed")
+ // ErrNotFound is returned when no route match is found.
+ ErrNotFound = errors.New("no matching route was found")
+)
+
+// NewRouter returns a new router instance.
+func NewRouter() *Router {
+ return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
+}
+
+// Router registers routes to be matched and dispatches a handler.
+//
+// It implements the http.Handler interface, so it can be registered to serve
+// requests:
+//
+// var router = mux.NewRouter()
+//
+// func main() {
+// http.Handle("/", router)
+// }
+//
+// Or, for Google App Engine, register it in a init() function:
+//
+// func init() {
+// http.Handle("/", router)
+// }
+//
+// This will send all incoming requests to the router.
+type Router struct {
+ // Configurable Handler to be used when no route matches.
+ NotFoundHandler http.Handler
+
+ // Configurable Handler to be used when the request method does not match the route.
+ MethodNotAllowedHandler http.Handler
+
+ // Parent route, if this is a subrouter.
+ parent parentRoute
+ // Routes to be matched, in order.
+ routes []*Route
+ // Routes by name for URL building.
+ namedRoutes map[string]*Route
+ // See Router.StrictSlash(). This defines the flag for new routes.
+ strictSlash bool
+ // See Router.SkipClean(). This defines the flag for new routes.
+ skipClean bool
+ // If true, do not clear the request context after handling the request.
+ // This has no effect when go1.7+ is used, since the context is stored
+ // on the request itself.
+ KeepContext bool
+ // see Router.UseEncodedPath(). This defines a flag for all routes.
+ useEncodedPath bool
+ // Slice of middlewares to be called after a match is found
+ middlewares []middleware
+}
+
+// Match attempts to match the given request against the router's registered routes.
+//
+// If the request matches a route of this router or one of its subrouters the Route,
+// Handler, and Vars fields of the the match argument are filled and this function
+// returns true.
+//
+// If the request does not match any of this router's or its subrouters' routes
+// then this function returns false. If available, a reason for the match failure
+// will be filled in the match argument's MatchErr field. If the match failure type
+// (eg: not found) has a registered handler, the handler is assigned to the Handler
+// field of the match argument.
+func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
+ for _, route := range r.routes {
+ if route.Match(req, match) {
+ // Build middleware chain if no error was found
+ if match.MatchErr == nil {
+ for i := len(r.middlewares) - 1; i >= 0; i-- {
+ match.Handler = r.middlewares[i].Middleware(match.Handler)
+ }
+ }
+ return true
+ }
+ }
+
+ if match.MatchErr == ErrMethodMismatch {
+ if r.MethodNotAllowedHandler != nil {
+ match.Handler = r.MethodNotAllowedHandler
+ return true
+ }
+
+ return false
+ }
+
+ // Closest match for a router (includes sub-routers)
+ if r.NotFoundHandler != nil {
+ match.Handler = r.NotFoundHandler
+ match.MatchErr = ErrNotFound
+ return true
+ }
+
+ match.MatchErr = ErrNotFound
+ return false
+}
+
+// ServeHTTP dispatches the handler registered in the matched route.
+//
+// When there is a match, the route variables can be retrieved calling
+// mux.Vars(request).
+func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ if !r.skipClean {
+ path := req.URL.Path
+ if r.useEncodedPath {
+ path = req.URL.EscapedPath()
+ }
+ // Clean path to canonical form and redirect.
+ if p := cleanPath(path); p != path {
+
+ // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
+ // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
+ // http://code.google.com/p/go/issues/detail?id=5252
+ url := *req.URL
+ url.Path = p
+ p = url.String()
+
+ w.Header().Set("Location", p)
+ w.WriteHeader(http.StatusMovedPermanently)
+ return
+ }
+ }
+ var match RouteMatch
+ var handler http.Handler
+ if r.Match(req, &match) {
+ handler = match.Handler
+ req = setVars(req, match.Vars)
+ req = setCurrentRoute(req, match.Route)
+ }
+
+ if handler == nil && match.MatchErr == ErrMethodMismatch {
+ handler = methodNotAllowedHandler()
+ }
+
+ if handler == nil {
+ handler = http.NotFoundHandler()
+ }
+
+ if !r.KeepContext {
+ defer contextClear(req)
+ }
+
+ handler.ServeHTTP(w, req)
+}
+
+// Get returns a route registered with the given name.
+func (r *Router) Get(name string) *Route {
+ return r.getNamedRoutes()[name]
+}
+
+// GetRoute returns a route registered with the given name. This method
+// was renamed to Get() and remains here for backwards compatibility.
+func (r *Router) GetRoute(name string) *Route {
+ return r.getNamedRoutes()[name]
+}
+
+// StrictSlash defines the trailing slash behavior for new routes. The initial
+// value is false.
+//
+// When true, if the route path is "/path/", accessing "/path" will perform a redirect
+// to the former and vice versa. In other words, your application will always
+// see the path as specified in the route.
+//
+// When false, if the route path is "/path", accessing "/path/" will not match
+// this route and vice versa.
+//
+// The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for
+// routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed
+// request will be made as a GET by most clients. Use middleware or client settings
+// to modify this behaviour as needed.
+//
+// Special case: when a route sets a path prefix using the PathPrefix() method,
+// strict slash is ignored for that route because the redirect behavior can't
+// be determined from a prefix alone. However, any subrouters created from that
+// route inherit the original StrictSlash setting.
+func (r *Router) StrictSlash(value bool) *Router {
+ r.strictSlash = value
+ return r
+}
+
+// SkipClean defines the path cleaning behaviour for new routes. The initial
+// value is false. Users should be careful about which routes are not cleaned
+//
+// When true, if the route path is "/path//to", it will remain with the double
+// slash. This is helpful if you have a route like: /fetch/http://xkcd.com/534/
+//
+// When false, the path will be cleaned, so /fetch/http://xkcd.com/534/ will
+// become /fetch/http/xkcd.com/534
+func (r *Router) SkipClean(value bool) *Router {
+ r.skipClean = value
+ return r
+}
+
+// UseEncodedPath tells the router to match the encoded original path
+// to the routes.
+// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to".
+//
+// If not called, the router will match the unencoded path to the routes.
+// For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to"
+func (r *Router) UseEncodedPath() *Router {
+ r.useEncodedPath = true
+ return r
+}
+
+// ----------------------------------------------------------------------------
+// parentRoute
+// ----------------------------------------------------------------------------
+
+func (r *Router) getBuildScheme() string {
+ if r.parent != nil {
+ return r.parent.getBuildScheme()
+ }
+ return ""
+}
+
+// getNamedRoutes returns the map where named routes are registered.
+func (r *Router) getNamedRoutes() map[string]*Route {
+ if r.namedRoutes == nil {
+ if r.parent != nil {
+ r.namedRoutes = r.parent.getNamedRoutes()
+ } else {
+ r.namedRoutes = make(map[string]*Route)
+ }
+ }
+ return r.namedRoutes
+}
+
+// getRegexpGroup returns regexp definitions from the parent route, if any.
+func (r *Router) getRegexpGroup() *routeRegexpGroup {
+ if r.parent != nil {
+ return r.parent.getRegexpGroup()
+ }
+ return nil
+}
+
+func (r *Router) buildVars(m map[string]string) map[string]string {
+ if r.parent != nil {
+ m = r.parent.buildVars(m)
+ }
+ return m
+}
+
+// ----------------------------------------------------------------------------
+// Route factories
+// ----------------------------------------------------------------------------
+
+// NewRoute registers an empty route.
+func (r *Router) NewRoute() *Route {
+ route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean, useEncodedPath: r.useEncodedPath}
+ r.routes = append(r.routes, route)
+ return route
+}
+
+// Handle registers a new route with a matcher for the URL path.
+// See Route.Path() and Route.Handler().
+func (r *Router) Handle(path string, handler http.Handler) *Route {
+ return r.NewRoute().Path(path).Handler(handler)
+}
+
+// HandleFunc registers a new route with a matcher for the URL path.
+// See Route.Path() and Route.HandlerFunc().
+func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,
+ *http.Request)) *Route {
+ return r.NewRoute().Path(path).HandlerFunc(f)
+}
+
+// Headers registers a new route with a matcher for request header values.
+// See Route.Headers().
+func (r *Router) Headers(pairs ...string) *Route {
+ return r.NewRoute().Headers(pairs...)
+}
+
+// Host registers a new route with a matcher for the URL host.
+// See Route.Host().
+func (r *Router) Host(tpl string) *Route {
+ return r.NewRoute().Host(tpl)
+}
+
+// MatcherFunc registers a new route with a custom matcher function.
+// See Route.MatcherFunc().
+func (r *Router) MatcherFunc(f MatcherFunc) *Route {
+ return r.NewRoute().MatcherFunc(f)
+}
+
+// Methods registers a new route with a matcher for HTTP methods.
+// See Route.Methods().
+func (r *Router) Methods(methods ...string) *Route {
+ return r.NewRoute().Methods(methods...)
+}
+
+// Path registers a new route with a matcher for the URL path.
+// See Route.Path().
+func (r *Router) Path(tpl string) *Route {
+ return r.NewRoute().Path(tpl)
+}
+
+// PathPrefix registers a new route with a matcher for the URL path prefix.
+// See Route.PathPrefix().
+func (r *Router) PathPrefix(tpl string) *Route {
+ return r.NewRoute().PathPrefix(tpl)
+}
+
+// Queries registers a new route with a matcher for URL query values.
+// See Route.Queries().
+func (r *Router) Queries(pairs ...string) *Route {
+ return r.NewRoute().Queries(pairs...)
+}
+
+// Schemes registers a new route with a matcher for URL schemes.
+// See Route.Schemes().
+func (r *Router) Schemes(schemes ...string) *Route {
+ return r.NewRoute().Schemes(schemes...)
+}
+
+// BuildVarsFunc registers a new route with a custom function for modifying
+// route variables before building a URL.
+func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route {
+ return r.NewRoute().BuildVarsFunc(f)
+}
+
+// Walk walks the router and all its sub-routers, calling walkFn for each route
+// in the tree. The routes are walked in the order they were added. Sub-routers
+// are explored depth-first.
+func (r *Router) Walk(walkFn WalkFunc) error {
+ return r.walk(walkFn, []*Route{})
+}
+
+// SkipRouter is used as a return value from WalkFuncs to indicate that the
+// router that walk is about to descend down to should be skipped.
+var SkipRouter = errors.New("skip this router")
+
+// WalkFunc is the type of the function called for each route visited by Walk.
+// At every invocation, it is given the current route, and the current router,
+// and a list of ancestor routes that lead to the current route.
+type WalkFunc func(route *Route, router *Router, ancestors []*Route) error
+
+func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
+ for _, t := range r.routes {
+ err := walkFn(t, r, ancestors)
+ if err == SkipRouter {
+ continue
+ }
+ if err != nil {
+ return err
+ }
+ for _, sr := range t.matchers {
+ if h, ok := sr.(*Router); ok {
+ ancestors = append(ancestors, t)
+ err := h.walk(walkFn, ancestors)
+ if err != nil {
+ return err
+ }
+ ancestors = ancestors[:len(ancestors)-1]
+ }
+ }
+ if h, ok := t.handler.(*Router); ok {
+ ancestors = append(ancestors, t)
+ err := h.walk(walkFn, ancestors)
+ if err != nil {
+ return err
+ }
+ ancestors = ancestors[:len(ancestors)-1]
+ }
+ }
+ return nil
+}
+
+// ----------------------------------------------------------------------------
+// Context
+// ----------------------------------------------------------------------------
+
+// RouteMatch stores information about a matched route.
+type RouteMatch struct {
+ Route *Route
+ Handler http.Handler
+ Vars map[string]string
+
+ // MatchErr is set to appropriate matching error
+ // It is set to ErrMethodMismatch if there is a mismatch in
+ // the request method and route method
+ MatchErr error
+}
+
+type contextKey int
+
+const (
+ varsKey contextKey = iota
+ routeKey
+)
+
+// Vars returns the route variables for the current request, if any.
+func Vars(r *http.Request) map[string]string {
+ if rv := contextGet(r, varsKey); rv != nil {
+ return rv.(map[string]string)
+ }
+ return nil
+}
+
+// CurrentRoute returns the matched route for the current request, if any.
+// This only works when called inside the handler of the matched route
+// because the matched route is stored in the request context which is cleared
+// after the handler returns, unless the KeepContext option is set on the
+// Router.
+func CurrentRoute(r *http.Request) *Route {
+ if rv := contextGet(r, routeKey); rv != nil {
+ return rv.(*Route)
+ }
+ return nil
+}
+
+func setVars(r *http.Request, val interface{}) *http.Request {
+ return contextSet(r, varsKey, val)
+}
+
+func setCurrentRoute(r *http.Request, val interface{}) *http.Request {
+ return contextSet(r, routeKey, val)
+}
+
+// ----------------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------------
+
+// cleanPath returns the canonical path for p, eliminating . and .. elements.
+// Borrowed from the net/http package.
+func cleanPath(p string) string {
+ if p == "" {
+ return "/"
+ }
+ if p[0] != '/' {
+ p = "/" + p
+ }
+ np := path.Clean(p)
+ // path.Clean removes trailing slash except for root;
+ // put the trailing slash back if necessary.
+ if p[len(p)-1] == '/' && np != "/" {
+ np += "/"
+ }
+
+ return np
+}
+
+// uniqueVars returns an error if two slices contain duplicated strings.
+func uniqueVars(s1, s2 []string) error {
+ for _, v1 := range s1 {
+ for _, v2 := range s2 {
+ if v1 == v2 {
+ return fmt.Errorf("mux: duplicated route variable %q", v2)
+ }
+ }
+ }
+ return nil
+}
+
+// checkPairs returns the count of strings passed in, and an error if
+// the count is not an even number.
+func checkPairs(pairs ...string) (int, error) {
+ length := len(pairs)
+ if length%2 != 0 {
+ return length, fmt.Errorf(
+ "mux: number of parameters must be multiple of 2, got %v", pairs)
+ }
+ return length, nil
+}
+
+// mapFromPairsToString converts variadic string parameters to a
+// string to string map.
+func mapFromPairsToString(pairs ...string) (map[string]string, error) {
+ length, err := checkPairs(pairs...)
+ if err != nil {
+ return nil, err
+ }
+ m := make(map[string]string, length/2)
+ for i := 0; i < length; i += 2 {
+ m[pairs[i]] = pairs[i+1]
+ }
+ return m, nil
+}
+
+// mapFromPairsToRegex converts variadic string parameters to a
+// string to regex map.
+func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {
+ length, err := checkPairs(pairs...)
+ if err != nil {
+ return nil, err
+ }
+ m := make(map[string]*regexp.Regexp, length/2)
+ for i := 0; i < length; i += 2 {
+ regex, err := regexp.Compile(pairs[i+1])
+ if err != nil {
+ return nil, err
+ }
+ m[pairs[i]] = regex
+ }
+ return m, nil
+}
+
+// matchInArray returns true if the given string value is in the array.
+func matchInArray(arr []string, value string) bool {
+ for _, v := range arr {
+ if v == value {
+ return true
+ }
+ }
+ return false
+}
+
+// matchMapWithString returns true if the given key/value pairs exist in a given map.
+func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool {
+ for k, v := range toCheck {
+ // Check if key exists.
+ if canonicalKey {
+ k = http.CanonicalHeaderKey(k)
+ }
+ if values := toMatch[k]; values == nil {
+ return false
+ } else if v != "" {
+ // If value was defined as an empty string we only check that the
+ // key exists. Otherwise we also check for equality.
+ valueExists := false
+ for _, value := range values {
+ if v == value {
+ valueExists = true
+ break
+ }
+ }
+ if !valueExists {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against
+// the given regex
+func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool {
+ for k, v := range toCheck {
+ // Check if key exists.
+ if canonicalKey {
+ k = http.CanonicalHeaderKey(k)
+ }
+ if values := toMatch[k]; values == nil {
+ return false
+ } else if v != nil {
+ // If value was defined as an empty string we only check that the
+ // key exists. Otherwise we also check for equality.
+ valueExists := false
+ for _, value := range values {
+ if v.MatchString(value) {
+ valueExists = true
+ break
+ }
+ }
+ if !valueExists {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// methodNotAllowed replies to the request with an HTTP status code 405.
+func methodNotAllowed(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+}
+
+// methodNotAllowedHandler returns a simple request handler
+// that replies to each request with a status code 405.
+func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) }
diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go
new file mode 100644
index 00000000..2b57e562
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/regexp.go
@@ -0,0 +1,332 @@
+// Copyright 2012 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mux
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type routeRegexpOptions struct {
+ strictSlash bool
+ useEncodedPath bool
+}
+
+type regexpType int
+
+const (
+ regexpTypePath regexpType = 0
+ regexpTypeHost regexpType = 1
+ regexpTypePrefix regexpType = 2
+ regexpTypeQuery regexpType = 3
+)
+
+// newRouteRegexp parses a route template and returns a routeRegexp,
+// used to match a host, a path or a query string.
+//
+// It will extract named variables, assemble a regexp to be matched, create
+// a "reverse" template to build URLs and compile regexps to validate variable
+// values used in URL building.
+//
+// Previously we accepted only Python-like identifiers for variable
+// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that
+// name and pattern can't be empty, and names can't contain a colon.
+func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*routeRegexp, error) {
+ // Check if it is well-formed.
+ idxs, errBraces := braceIndices(tpl)
+ if errBraces != nil {
+ return nil, errBraces
+ }
+ // Backup the original.
+ template := tpl
+ // Now let's parse it.
+ defaultPattern := "[^/]+"
+ if typ == regexpTypeQuery {
+ defaultPattern = ".*"
+ } else if typ == regexpTypeHost {
+ defaultPattern = "[^.]+"
+ }
+ // Only match strict slash if not matching
+ if typ != regexpTypePath {
+ options.strictSlash = false
+ }
+ // Set a flag for strictSlash.
+ endSlash := false
+ if options.strictSlash && strings.HasSuffix(tpl, "/") {
+ tpl = tpl[:len(tpl)-1]
+ endSlash = true
+ }
+ varsN := make([]string, len(idxs)/2)
+ varsR := make([]*regexp.Regexp, len(idxs)/2)
+ pattern := bytes.NewBufferString("")
+ pattern.WriteByte('^')
+ reverse := bytes.NewBufferString("")
+ var end int
+ var err error
+ for i := 0; i < len(idxs); i += 2 {
+ // Set all values we are interested in.
+ raw := tpl[end:idxs[i]]
+ end = idxs[i+1]
+ parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2)
+ name := parts[0]
+ patt := defaultPattern
+ if len(parts) == 2 {
+ patt = parts[1]
+ }
+ // Name or pattern can't be empty.
+ if name == "" || patt == "" {
+ return nil, fmt.Errorf("mux: missing name or pattern in %q",
+ tpl[idxs[i]:end])
+ }
+ // Build the regexp pattern.
+ fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(i/2), patt)
+
+ // Build the reverse template.
+ fmt.Fprintf(reverse, "%s%%s", raw)
+
+ // Append variable name and compiled pattern.
+ varsN[i/2] = name
+ varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt))
+ if err != nil {
+ return nil, err
+ }
+ }
+ // Add the remaining.
+ raw := tpl[end:]
+ pattern.WriteString(regexp.QuoteMeta(raw))
+ if options.strictSlash {
+ pattern.WriteString("[/]?")
+ }
+ if typ == regexpTypeQuery {
+ // Add the default pattern if the query value is empty
+ if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" {
+ pattern.WriteString(defaultPattern)
+ }
+ }
+ if typ != regexpTypePrefix {
+ pattern.WriteByte('$')
+ }
+ reverse.WriteString(raw)
+ if endSlash {
+ reverse.WriteByte('/')
+ }
+ // Compile full regexp.
+ reg, errCompile := regexp.Compile(pattern.String())
+ if errCompile != nil {
+ return nil, errCompile
+ }
+
+ // Check for capturing groups which used to work in older versions
+ if reg.NumSubexp() != len(idxs)/2 {
+ panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) +
+ "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)")
+ }
+
+ // Done!
+ return &routeRegexp{
+ template: template,
+ regexpType: typ,
+ options: options,
+ regexp: reg,
+ reverse: reverse.String(),
+ varsN: varsN,
+ varsR: varsR,
+ }, nil
+}
+
+// routeRegexp stores a regexp to match a host or path and information to
+// collect and validate route variables.
+type routeRegexp struct {
+ // The unmodified template.
+ template string
+ // The type of match
+ regexpType regexpType
+ // Options for matching
+ options routeRegexpOptions
+ // Expanded regexp.
+ regexp *regexp.Regexp
+ // Reverse template.
+ reverse string
+ // Variable names.
+ varsN []string
+ // Variable regexps (validators).
+ varsR []*regexp.Regexp
+}
+
+// Match matches the regexp against the URL host or path.
+func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
+ if r.regexpType != regexpTypeHost {
+ if r.regexpType == regexpTypeQuery {
+ return r.matchQueryString(req)
+ }
+ path := req.URL.Path
+ if r.options.useEncodedPath {
+ path = req.URL.EscapedPath()
+ }
+ return r.regexp.MatchString(path)
+ }
+
+ return r.regexp.MatchString(getHost(req))
+}
+
+// url builds a URL part using the given values.
+func (r *routeRegexp) url(values map[string]string) (string, error) {
+ urlValues := make([]interface{}, len(r.varsN))
+ for k, v := range r.varsN {
+ value, ok := values[v]
+ if !ok {
+ return "", fmt.Errorf("mux: missing route variable %q", v)
+ }
+ if r.regexpType == regexpTypeQuery {
+ value = url.QueryEscape(value)
+ }
+ urlValues[k] = value
+ }
+ rv := fmt.Sprintf(r.reverse, urlValues...)
+ if !r.regexp.MatchString(rv) {
+ // The URL is checked against the full regexp, instead of checking
+ // individual variables. This is faster but to provide a good error
+ // message, we check individual regexps if the URL doesn't match.
+ for k, v := range r.varsN {
+ if !r.varsR[k].MatchString(values[v]) {
+ return "", fmt.Errorf(
+ "mux: variable %q doesn't match, expected %q", values[v],
+ r.varsR[k].String())
+ }
+ }
+ }
+ return rv, nil
+}
+
+// getURLQuery returns a single query parameter from a request URL.
+// For a URL with foo=bar&baz=ding, we return only the relevant key
+// value pair for the routeRegexp.
+func (r *routeRegexp) getURLQuery(req *http.Request) string {
+ if r.regexpType != regexpTypeQuery {
+ return ""
+ }
+ templateKey := strings.SplitN(r.template, "=", 2)[0]
+ for key, vals := range req.URL.Query() {
+ if key == templateKey && len(vals) > 0 {
+ return key + "=" + vals[0]
+ }
+ }
+ return ""
+}
+
+func (r *routeRegexp) matchQueryString(req *http.Request) bool {
+ return r.regexp.MatchString(r.getURLQuery(req))
+}
+
+// braceIndices returns the first level curly brace indices from a string.
+// It returns an error in case of unbalanced braces.
+func braceIndices(s string) ([]int, error) {
+ var level, idx int
+ var idxs []int
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '{':
+ if level++; level == 1 {
+ idx = i
+ }
+ case '}':
+ if level--; level == 0 {
+ idxs = append(idxs, idx, i+1)
+ } else if level < 0 {
+ return nil, fmt.Errorf("mux: unbalanced braces in %q", s)
+ }
+ }
+ }
+ if level != 0 {
+ return nil, fmt.Errorf("mux: unbalanced braces in %q", s)
+ }
+ return idxs, nil
+}
+
+// varGroupName builds a capturing group name for the indexed variable.
+func varGroupName(idx int) string {
+ return "v" + strconv.Itoa(idx)
+}
+
+// ----------------------------------------------------------------------------
+// routeRegexpGroup
+// ----------------------------------------------------------------------------
+
+// routeRegexpGroup groups the route matchers that carry variables.
+type routeRegexpGroup struct {
+ host *routeRegexp
+ path *routeRegexp
+ queries []*routeRegexp
+}
+
+// setMatch extracts the variables from the URL once a route matches.
+func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {
+ // Store host variables.
+ if v.host != nil {
+ host := getHost(req)
+ matches := v.host.regexp.FindStringSubmatchIndex(host)
+ if len(matches) > 0 {
+ extractVars(host, matches, v.host.varsN, m.Vars)
+ }
+ }
+ path := req.URL.Path
+ if r.useEncodedPath {
+ path = req.URL.EscapedPath()
+ }
+ // Store path variables.
+ if v.path != nil {
+ matches := v.path.regexp.FindStringSubmatchIndex(path)
+ if len(matches) > 0 {
+ extractVars(path, matches, v.path.varsN, m.Vars)
+ // Check if we should redirect.
+ if v.path.options.strictSlash {
+ p1 := strings.HasSuffix(path, "/")
+ p2 := strings.HasSuffix(v.path.template, "/")
+ if p1 != p2 {
+ u, _ := url.Parse(req.URL.String())
+ if p1 {
+ u.Path = u.Path[:len(u.Path)-1]
+ } else {
+ u.Path += "/"
+ }
+ m.Handler = http.RedirectHandler(u.String(), 301)
+ }
+ }
+ }
+ }
+ // Store query string variables.
+ for _, q := range v.queries {
+ queryURL := q.getURLQuery(req)
+ matches := q.regexp.FindStringSubmatchIndex(queryURL)
+ if len(matches) > 0 {
+ extractVars(queryURL, matches, q.varsN, m.Vars)
+ }
+ }
+}
+
+// getHost tries its best to return the request host.
+func getHost(r *http.Request) string {
+ if r.URL.IsAbs() {
+ return r.URL.Host
+ }
+ host := r.Host
+ // Slice off any port information.
+ if i := strings.Index(host, ":"); i != -1 {
+ host = host[:i]
+ }
+ return host
+
+}
+
+func extractVars(input string, matches []int, names []string, output map[string]string) {
+ for i, name := range names {
+ output[name] = input[matches[2*i+2]:matches[2*i+3]]
+ }
+}
diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go
new file mode 100644
index 00000000..a591d735
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/route.go
@@ -0,0 +1,763 @@
+// Copyright 2012 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mux
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "regexp"
+ "strings"
+)
+
+// Route stores information to match a request and build URLs.
+type Route struct {
+ // Parent where the route was registered (a Router).
+ parent parentRoute
+ // Request handler for the route.
+ handler http.Handler
+ // List of matchers.
+ matchers []matcher
+ // Manager for the variables from host and path.
+ regexp *routeRegexpGroup
+ // If true, when the path pattern is "/path/", accessing "/path" will
+ // redirect to the former and vice versa.
+ strictSlash bool
+ // If true, when the path pattern is "/path//to", accessing "/path//to"
+ // will not redirect
+ skipClean bool
+ // If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to"
+ useEncodedPath bool
+ // The scheme used when building URLs.
+ buildScheme string
+ // If true, this route never matches: it is only used to build URLs.
+ buildOnly bool
+ // The name used to build URLs.
+ name string
+ // Error resulted from building a route.
+ err error
+
+ buildVarsFunc BuildVarsFunc
+}
+
+// SkipClean reports whether path cleaning is enabled for this route via
+// Router.SkipClean.
+func (r *Route) SkipClean() bool {
+ return r.skipClean
+}
+
+// Match matches the route against the request.
+func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
+ if r.buildOnly || r.err != nil {
+ return false
+ }
+
+ var matchErr error
+
+ // Match everything.
+ for _, m := range r.matchers {
+ if matched := m.Match(req, match); !matched {
+ if _, ok := m.(methodMatcher); ok {
+ matchErr = ErrMethodMismatch
+ continue
+ }
+ matchErr = nil
+ return false
+ }
+ }
+
+ if matchErr != nil {
+ match.MatchErr = matchErr
+ return false
+ }
+
+ if match.MatchErr == ErrMethodMismatch {
+ // We found a route which matches request method, clear MatchErr
+ match.MatchErr = nil
+ // Then override the mis-matched handler
+ match.Handler = r.handler
+ }
+
+ // Yay, we have a match. Let's collect some info about it.
+ if match.Route == nil {
+ match.Route = r
+ }
+ if match.Handler == nil {
+ match.Handler = r.handler
+ }
+ if match.Vars == nil {
+ match.Vars = make(map[string]string)
+ }
+
+ // Set variables.
+ if r.regexp != nil {
+ r.regexp.setMatch(req, match, r)
+ }
+ return true
+}
+
+// ----------------------------------------------------------------------------
+// Route attributes
+// ----------------------------------------------------------------------------
+
+// GetError returns an error resulted from building the route, if any.
+func (r *Route) GetError() error {
+ return r.err
+}
+
+// BuildOnly sets the route to never match: it is only used to build URLs.
+func (r *Route) BuildOnly() *Route {
+ r.buildOnly = true
+ return r
+}
+
+// Handler --------------------------------------------------------------------
+
+// Handler sets a handler for the route.
+func (r *Route) Handler(handler http.Handler) *Route {
+ if r.err == nil {
+ r.handler = handler
+ }
+ return r
+}
+
+// HandlerFunc sets a handler function for the route.
+func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route {
+ return r.Handler(http.HandlerFunc(f))
+}
+
+// GetHandler returns the handler for the route, if any.
+func (r *Route) GetHandler() http.Handler {
+ return r.handler
+}
+
+// Name -----------------------------------------------------------------------
+
+// Name sets the name for the route, used to build URLs.
+// If the name was registered already it will be overwritten.
+func (r *Route) Name(name string) *Route {
+ if r.name != "" {
+ r.err = fmt.Errorf("mux: route already has name %q, can't set %q",
+ r.name, name)
+ }
+ if r.err == nil {
+ r.name = name
+ r.getNamedRoutes()[name] = r
+ }
+ return r
+}
+
+// GetName returns the name for the route, if any.
+func (r *Route) GetName() string {
+ return r.name
+}
+
+// ----------------------------------------------------------------------------
+// Matchers
+// ----------------------------------------------------------------------------
+
+// matcher types try to match a request.
+type matcher interface {
+ Match(*http.Request, *RouteMatch) bool
+}
+
+// addMatcher adds a matcher to the route.
+func (r *Route) addMatcher(m matcher) *Route {
+ if r.err == nil {
+ r.matchers = append(r.matchers, m)
+ }
+ return r
+}
+
+// addRegexpMatcher adds a host or path matcher and builder to a route.
+func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error {
+ if r.err != nil {
+ return r.err
+ }
+ r.regexp = r.getRegexpGroup()
+ if typ == regexpTypePath || typ == regexpTypePrefix {
+ if len(tpl) > 0 && tpl[0] != '/' {
+ return fmt.Errorf("mux: path must start with a slash, got %q", tpl)
+ }
+ if r.regexp.path != nil {
+ tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl
+ }
+ }
+ rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{
+ strictSlash: r.strictSlash,
+ useEncodedPath: r.useEncodedPath,
+ })
+ if err != nil {
+ return err
+ }
+ for _, q := range r.regexp.queries {
+ if err = uniqueVars(rr.varsN, q.varsN); err != nil {
+ return err
+ }
+ }
+ if typ == regexpTypeHost {
+ if r.regexp.path != nil {
+ if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil {
+ return err
+ }
+ }
+ r.regexp.host = rr
+ } else {
+ if r.regexp.host != nil {
+ if err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil {
+ return err
+ }
+ }
+ if typ == regexpTypeQuery {
+ r.regexp.queries = append(r.regexp.queries, rr)
+ } else {
+ r.regexp.path = rr
+ }
+ }
+ r.addMatcher(rr)
+ return nil
+}
+
+// Headers --------------------------------------------------------------------
+
+// headerMatcher matches the request against header values.
+type headerMatcher map[string]string
+
+func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool {
+ return matchMapWithString(m, r.Header, true)
+}
+
+// Headers adds a matcher for request header values.
+// It accepts a sequence of key/value pairs to be matched. For example:
+//
+// r := mux.NewRouter()
+// r.Headers("Content-Type", "application/json",
+// "X-Requested-With", "XMLHttpRequest")
+//
+// The above route will only match if both request header values match.
+// If the value is an empty string, it will match any value if the key is set.
+func (r *Route) Headers(pairs ...string) *Route {
+ if r.err == nil {
+ var headers map[string]string
+ headers, r.err = mapFromPairsToString(pairs...)
+ return r.addMatcher(headerMatcher(headers))
+ }
+ return r
+}
+
+// headerRegexMatcher matches the request against the route given a regex for the header
+type headerRegexMatcher map[string]*regexp.Regexp
+
+func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool {
+ return matchMapWithRegex(m, r.Header, true)
+}
+
+// HeadersRegexp accepts a sequence of key/value pairs, where the value has regex
+// support. For example:
+//
+// r := mux.NewRouter()
+// r.HeadersRegexp("Content-Type", "application/(text|json)",
+// "X-Requested-With", "XMLHttpRequest")
+//
+// The above route will only match if both the request header matches both regular expressions.
+// If the value is an empty string, it will match any value if the key is set.
+// Use the start and end of string anchors (^ and $) to match an exact value.
+func (r *Route) HeadersRegexp(pairs ...string) *Route {
+ if r.err == nil {
+ var headers map[string]*regexp.Regexp
+ headers, r.err = mapFromPairsToRegex(pairs...)
+ return r.addMatcher(headerRegexMatcher(headers))
+ }
+ return r
+}
+
+// Host -----------------------------------------------------------------------
+
+// Host adds a matcher for the URL host.
+// It accepts a template with zero or more URL variables enclosed by {}.
+// Variables can define an optional regexp pattern to be matched:
+//
+// - {name} matches anything until the next dot.
+//
+// - {name:pattern} matches the given regexp pattern.
+//
+// For example:
+//
+// r := mux.NewRouter()
+// r.Host("www.example.com")
+// r.Host("{subdomain}.domain.com")
+// r.Host("{subdomain:[a-z]+}.domain.com")
+//
+// Variable names must be unique in a given route. They can be retrieved
+// calling mux.Vars(request).
+func (r *Route) Host(tpl string) *Route {
+ r.err = r.addRegexpMatcher(tpl, regexpTypeHost)
+ return r
+}
+
+// MatcherFunc ----------------------------------------------------------------
+
+// MatcherFunc is the function signature used by custom matchers.
+type MatcherFunc func(*http.Request, *RouteMatch) bool
+
+// Match returns the match for a given request.
+func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool {
+ return m(r, match)
+}
+
+// MatcherFunc adds a custom function to be used as request matcher.
+func (r *Route) MatcherFunc(f MatcherFunc) *Route {
+ return r.addMatcher(f)
+}
+
+// Methods --------------------------------------------------------------------
+
+// methodMatcher matches the request against HTTP methods.
+type methodMatcher []string
+
+func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool {
+ return matchInArray(m, r.Method)
+}
+
+// Methods adds a matcher for HTTP methods.
+// It accepts a sequence of one or more methods to be matched, e.g.:
+// "GET", "POST", "PUT".
+func (r *Route) Methods(methods ...string) *Route {
+ for k, v := range methods {
+ methods[k] = strings.ToUpper(v)
+ }
+ return r.addMatcher(methodMatcher(methods))
+}
+
+// Path -----------------------------------------------------------------------
+
+// Path adds a matcher for the URL path.
+// It accepts a template with zero or more URL variables enclosed by {}. The
+// template must start with a "/".
+// Variables can define an optional regexp pattern to be matched:
+//
+// - {name} matches anything until the next slash.
+//
+// - {name:pattern} matches the given regexp pattern.
+//
+// For example:
+//
+// r := mux.NewRouter()
+// r.Path("/products/").Handler(ProductsHandler)
+// r.Path("/products/{key}").Handler(ProductsHandler)
+// r.Path("/articles/{category}/{id:[0-9]+}").
+// Handler(ArticleHandler)
+//
+// Variable names must be unique in a given route. They can be retrieved
+// calling mux.Vars(request).
+func (r *Route) Path(tpl string) *Route {
+ r.err = r.addRegexpMatcher(tpl, regexpTypePath)
+ return r
+}
+
+// PathPrefix -----------------------------------------------------------------
+
+// PathPrefix adds a matcher for the URL path prefix. This matches if the given
+// template is a prefix of the full URL path. See Route.Path() for details on
+// the tpl argument.
+//
+// Note that it does not treat slashes specially ("/foobar/" will be matched by
+// the prefix "/foo") so you may want to use a trailing slash here.
+//
+// Also note that the setting of Router.StrictSlash() has no effect on routes
+// with a PathPrefix matcher.
+func (r *Route) PathPrefix(tpl string) *Route {
+ r.err = r.addRegexpMatcher(tpl, regexpTypePrefix)
+ return r
+}
+
+// Query ----------------------------------------------------------------------
+
+// Queries adds a matcher for URL query values.
+// It accepts a sequence of key/value pairs. Values may define variables.
+// For example:
+//
+// r := mux.NewRouter()
+// r.Queries("foo", "bar", "id", "{id:[0-9]+}")
+//
+// The above route will only match if the URL contains the defined queries
+// values, e.g.: ?foo=bar&id=42.
+//
+// It the value is an empty string, it will match any value if the key is set.
+//
+// Variables can define an optional regexp pattern to be matched:
+//
+// - {name} matches anything until the next slash.
+//
+// - {name:pattern} matches the given regexp pattern.
+func (r *Route) Queries(pairs ...string) *Route {
+ length := len(pairs)
+ if length%2 != 0 {
+ r.err = fmt.Errorf(
+ "mux: number of parameters must be multiple of 2, got %v", pairs)
+ return nil
+ }
+ for i := 0; i < length; i += 2 {
+ if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], regexpTypeQuery); r.err != nil {
+ return r
+ }
+ }
+
+ return r
+}
+
+// Schemes --------------------------------------------------------------------
+
+// schemeMatcher matches the request against URL schemes.
+type schemeMatcher []string
+
+func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool {
+ return matchInArray(m, r.URL.Scheme)
+}
+
+// Schemes adds a matcher for URL schemes.
+// It accepts a sequence of schemes to be matched, e.g.: "http", "https".
+func (r *Route) Schemes(schemes ...string) *Route {
+ for k, v := range schemes {
+ schemes[k] = strings.ToLower(v)
+ }
+ if r.buildScheme == "" && len(schemes) > 0 {
+ r.buildScheme = schemes[0]
+ }
+ return r.addMatcher(schemeMatcher(schemes))
+}
+
+// BuildVarsFunc --------------------------------------------------------------
+
+// BuildVarsFunc is the function signature used by custom build variable
+// functions (which can modify route variables before a route's URL is built).
+type BuildVarsFunc func(map[string]string) map[string]string
+
+// BuildVarsFunc adds a custom function to be used to modify build variables
+// before a route's URL is built.
+func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
+ r.buildVarsFunc = f
+ return r
+}
+
+// Subrouter ------------------------------------------------------------------
+
+// Subrouter creates a subrouter for the route.
+//
+// It will test the inner routes only if the parent route matched. For example:
+//
+// r := mux.NewRouter()
+// s := r.Host("www.example.com").Subrouter()
+// s.HandleFunc("/products/", ProductsHandler)
+// s.HandleFunc("/products/{key}", ProductHandler)
+// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
+//
+// Here, the routes registered in the subrouter won't be tested if the host
+// doesn't match.
+func (r *Route) Subrouter() *Router {
+ router := &Router{parent: r, strictSlash: r.strictSlash}
+ r.addMatcher(router)
+ return router
+}
+
+// ----------------------------------------------------------------------------
+// URL building
+// ----------------------------------------------------------------------------
+
+// URL builds a URL for the route.
+//
+// It accepts a sequence of key/value pairs for the route variables. For
+// example, given this route:
+//
+// r := mux.NewRouter()
+// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+// Name("article")
+//
+// ...a URL for it can be built using:
+//
+// url, err := r.Get("article").URL("category", "technology", "id", "42")
+//
+// ...which will return an url.URL with the following path:
+//
+// "/articles/technology/42"
+//
+// This also works for host variables:
+//
+// r := mux.NewRouter()
+// r.Host("{subdomain}.domain.com").
+// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+// Name("article")
+//
+// // url.String() will be "http://news.domain.com/articles/technology/42"
+// url, err := r.Get("article").URL("subdomain", "news",
+// "category", "technology",
+// "id", "42")
+//
+// All variables defined in the route are required, and their values must
+// conform to the corresponding patterns.
+func (r *Route) URL(pairs ...string) (*url.URL, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+ if r.regexp == nil {
+ return nil, errors.New("mux: route doesn't have a host or path")
+ }
+ values, err := r.prepareVars(pairs...)
+ if err != nil {
+ return nil, err
+ }
+ var scheme, host, path string
+ queries := make([]string, 0, len(r.regexp.queries))
+ if r.regexp.host != nil {
+ if host, err = r.regexp.host.url(values); err != nil {
+ return nil, err
+ }
+ scheme = "http"
+ if s := r.getBuildScheme(); s != "" {
+ scheme = s
+ }
+ }
+ if r.regexp.path != nil {
+ if path, err = r.regexp.path.url(values); err != nil {
+ return nil, err
+ }
+ }
+ for _, q := range r.regexp.queries {
+ var query string
+ if query, err = q.url(values); err != nil {
+ return nil, err
+ }
+ queries = append(queries, query)
+ }
+ return &url.URL{
+ Scheme: scheme,
+ Host: host,
+ Path: path,
+ RawQuery: strings.Join(queries, "&"),
+ }, nil
+}
+
+// URLHost builds the host part of the URL for a route. See Route.URL().
+//
+// The route must have a host defined.
+func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+ if r.regexp == nil || r.regexp.host == nil {
+ return nil, errors.New("mux: route doesn't have a host")
+ }
+ values, err := r.prepareVars(pairs...)
+ if err != nil {
+ return nil, err
+ }
+ host, err := r.regexp.host.url(values)
+ if err != nil {
+ return nil, err
+ }
+ u := &url.URL{
+ Scheme: "http",
+ Host: host,
+ }
+ if s := r.getBuildScheme(); s != "" {
+ u.Scheme = s
+ }
+ return u, nil
+}
+
+// URLPath builds the path part of the URL for a route. See Route.URL().
+//
+// The route must have a path defined.
+func (r *Route) URLPath(pairs ...string) (*url.URL, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+ if r.regexp == nil || r.regexp.path == nil {
+ return nil, errors.New("mux: route doesn't have a path")
+ }
+ values, err := r.prepareVars(pairs...)
+ if err != nil {
+ return nil, err
+ }
+ path, err := r.regexp.path.url(values)
+ if err != nil {
+ return nil, err
+ }
+ return &url.URL{
+ Path: path,
+ }, nil
+}
+
+// GetPathTemplate returns the template used to build the
+// route match.
+// This is useful for building simple REST API documentation and for instrumentation
+// against third-party services.
+// An error will be returned if the route does not define a path.
+func (r *Route) GetPathTemplate() (string, error) {
+ if r.err != nil {
+ return "", r.err
+ }
+ if r.regexp == nil || r.regexp.path == nil {
+ return "", errors.New("mux: route doesn't have a path")
+ }
+ return r.regexp.path.template, nil
+}
+
+// GetPathRegexp returns the expanded regular expression used to match route path.
+// This is useful for building simple REST API documentation and for instrumentation
+// against third-party services.
+// An error will be returned if the route does not define a path.
+func (r *Route) GetPathRegexp() (string, error) {
+ if r.err != nil {
+ return "", r.err
+ }
+ if r.regexp == nil || r.regexp.path == nil {
+ return "", errors.New("mux: route does not have a path")
+ }
+ return r.regexp.path.regexp.String(), nil
+}
+
+// GetQueriesRegexp returns the expanded regular expressions used to match the
+// route queries.
+// This is useful for building simple REST API documentation and for instrumentation
+// against third-party services.
+// An error will be returned if the route does not have queries.
+func (r *Route) GetQueriesRegexp() ([]string, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+ if r.regexp == nil || r.regexp.queries == nil {
+ return nil, errors.New("mux: route doesn't have queries")
+ }
+ var queries []string
+ for _, query := range r.regexp.queries {
+ queries = append(queries, query.regexp.String())
+ }
+ return queries, nil
+}
+
+// GetQueriesTemplates returns the templates used to build the
+// query matching.
+// This is useful for building simple REST API documentation and for instrumentation
+// against third-party services.
+// An error will be returned if the route does not define queries.
+func (r *Route) GetQueriesTemplates() ([]string, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+ if r.regexp == nil || r.regexp.queries == nil {
+ return nil, errors.New("mux: route doesn't have queries")
+ }
+ var queries []string
+ for _, query := range r.regexp.queries {
+ queries = append(queries, query.template)
+ }
+ return queries, nil
+}
+
+// GetMethods returns the methods the route matches against
+// This is useful for building simple REST API documentation and for instrumentation
+// against third-party services.
+// An error will be returned if route does not have methods.
+func (r *Route) GetMethods() ([]string, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+ for _, m := range r.matchers {
+ if methods, ok := m.(methodMatcher); ok {
+ return []string(methods), nil
+ }
+ }
+ return nil, errors.New("mux: route doesn't have methods")
+}
+
+// GetHostTemplate returns the template used to build the
+// route match.
+// This is useful for building simple REST API documentation and for instrumentation
+// against third-party services.
+// An error will be returned if the route does not define a host.
+func (r *Route) GetHostTemplate() (string, error) {
+ if r.err != nil {
+ return "", r.err
+ }
+ if r.regexp == nil || r.regexp.host == nil {
+ return "", errors.New("mux: route doesn't have a host")
+ }
+ return r.regexp.host.template, nil
+}
+
+// prepareVars converts the route variable pairs into a map. If the route has a
+// BuildVarsFunc, it is invoked.
+func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {
+ m, err := mapFromPairsToString(pairs...)
+ if err != nil {
+ return nil, err
+ }
+ return r.buildVars(m), nil
+}
+
+func (r *Route) buildVars(m map[string]string) map[string]string {
+ if r.parent != nil {
+ m = r.parent.buildVars(m)
+ }
+ if r.buildVarsFunc != nil {
+ m = r.buildVarsFunc(m)
+ }
+ return m
+}
+
+// ----------------------------------------------------------------------------
+// parentRoute
+// ----------------------------------------------------------------------------
+
+// parentRoute allows routes to know about parent host and path definitions.
+type parentRoute interface {
+ getBuildScheme() string
+ getNamedRoutes() map[string]*Route
+ getRegexpGroup() *routeRegexpGroup
+ buildVars(map[string]string) map[string]string
+}
+
+func (r *Route) getBuildScheme() string {
+ if r.buildScheme != "" {
+ return r.buildScheme
+ }
+ if r.parent != nil {
+ return r.parent.getBuildScheme()
+ }
+ return ""
+}
+
+// getNamedRoutes returns the map where named routes are registered.
+func (r *Route) getNamedRoutes() map[string]*Route {
+ if r.parent == nil {
+ // During tests router is not always set.
+ r.parent = NewRouter()
+ }
+ return r.parent.getNamedRoutes()
+}
+
+// getRegexpGroup returns regexp definitions from this route.
+func (r *Route) getRegexpGroup() *routeRegexpGroup {
+ if r.regexp == nil {
+ if r.parent == nil {
+ // During tests router is not always set.
+ r.parent = NewRouter()
+ }
+ regexp := r.parent.getRegexpGroup()
+ if regexp == nil {
+ r.regexp = new(routeRegexpGroup)
+ } else {
+ // Copy.
+ r.regexp = &routeRegexpGroup{
+ host: regexp.host,
+ path: regexp.path,
+ queries: regexp.queries,
+ }
+ }
+ }
+ return r.regexp
+}
diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go
new file mode 100644
index 00000000..32ecffde
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/test_helpers.go
@@ -0,0 +1,19 @@
+// Copyright 2012 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mux
+
+import "net/http"
+
+// SetURLVars sets the URL variables for the given request, to be accessed via
+// mux.Vars for testing route behaviour. Arguments are not modified, a shallow
+// copy is returned.
+//
+// This API should only be used for testing purposes; it provides a way to
+// inject variables into the request context. Alternatively, URL variables
+// can be set by making a route that captures the required variables,
+// starting a server and sending the request to that server.
+func SetURLVars(r *http.Request, val map[string]string) *http.Request {
+ return setVars(r, val)
+}
diff --git a/vendor/github.com/jonboulle/clockwork/LICENSE b/vendor/github.com/jonboulle/clockwork/LICENSE
new file mode 100644
index 00000000..5c304d1a
--- /dev/null
+++ b/vendor/github.com/jonboulle/clockwork/LICENSE
@@ -0,0 +1,201 @@
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/jonboulle/clockwork/clockwork.go b/vendor/github.com/jonboulle/clockwork/clockwork.go
new file mode 100644
index 00000000..9ec96ed2
--- /dev/null
+++ b/vendor/github.com/jonboulle/clockwork/clockwork.go
@@ -0,0 +1,169 @@
+package clockwork
+
+import (
+ "sync"
+ "time"
+)
+
+// Clock provides an interface that packages can use instead of directly
+// using the time module, so that chronology-related behavior can be tested
+type Clock interface {
+ After(d time.Duration) <-chan time.Time
+ Sleep(d time.Duration)
+ Now() time.Time
+}
+
+// FakeClock provides an interface for a clock which can be
+// manually advanced through time
+type FakeClock interface {
+ Clock
+ // Advance advances the FakeClock to a new point in time, ensuring any existing
+ // sleepers are notified appropriately before returning
+ Advance(d time.Duration)
+ // BlockUntil will block until the FakeClock has the given number of
+ // sleepers (callers of Sleep or After)
+ BlockUntil(n int)
+}
+
+// NewRealClock returns a Clock which simply delegates calls to the actual time
+// package; it should be used by packages in production.
+func NewRealClock() Clock {
+ return &realClock{}
+}
+
+// NewFakeClock returns a FakeClock implementation which can be
+// manually advanced through time for testing. The initial time of the
+// FakeClock will be an arbitrary non-zero time.
+func NewFakeClock() FakeClock {
+ // use a fixture that does not fulfill Time.IsZero()
+ return NewFakeClockAt(time.Date(1984, time.April, 4, 0, 0, 0, 0, time.UTC))
+}
+
+// NewFakeClockAt returns a FakeClock initialised at the given time.Time.
+func NewFakeClockAt(t time.Time) FakeClock {
+ return &fakeClock{
+ time: t,
+ }
+}
+
+type realClock struct{}
+
+func (rc *realClock) After(d time.Duration) <-chan time.Time {
+ return time.After(d)
+}
+
+func (rc *realClock) Sleep(d time.Duration) {
+ time.Sleep(d)
+}
+
+func (rc *realClock) Now() time.Time {
+ return time.Now()
+}
+
+type fakeClock struct {
+ sleepers []*sleeper
+ blockers []*blocker
+ time time.Time
+
+ l sync.RWMutex
+}
+
+// sleeper represents a caller of After or Sleep
+type sleeper struct {
+ until time.Time
+ done chan time.Time
+}
+
+// blocker represents a caller of BlockUntil
+type blocker struct {
+ count int
+ ch chan struct{}
+}
+
+// After mimics time.After; it waits for the given duration to elapse on the
+// fakeClock, then sends the current time on the returned channel.
+func (fc *fakeClock) After(d time.Duration) <-chan time.Time {
+ fc.l.Lock()
+ defer fc.l.Unlock()
+ now := fc.time
+ done := make(chan time.Time, 1)
+ if d.Nanoseconds() == 0 {
+ // special case - trigger immediately
+ done <- now
+ } else {
+ // otherwise, add to the set of sleepers
+ s := &sleeper{
+ until: now.Add(d),
+ done: done,
+ }
+ fc.sleepers = append(fc.sleepers, s)
+ // and notify any blockers
+ fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
+ }
+ return done
+}
+
+// notifyBlockers notifies all the blockers waiting until the
+// given number of sleepers are waiting on the fakeClock. It
+// returns an updated slice of blockers (i.e. those still waiting)
+func notifyBlockers(blockers []*blocker, count int) (newBlockers []*blocker) {
+ for _, b := range blockers {
+ if b.count == count {
+ close(b.ch)
+ } else {
+ newBlockers = append(newBlockers, b)
+ }
+ }
+ return
+}
+
+// Sleep blocks until the given duration has passed on the fakeClock
+func (fc *fakeClock) Sleep(d time.Duration) {
+ <-fc.After(d)
+}
+
+// Time returns the current time of the fakeClock
+func (fc *fakeClock) Now() time.Time {
+ fc.l.RLock()
+ t := fc.time
+ fc.l.RUnlock()
+ return t
+}
+
+// Advance advances fakeClock to a new point in time, ensuring channels from any
+// previous invocations of After are notified appropriately before returning
+func (fc *fakeClock) Advance(d time.Duration) {
+ fc.l.Lock()
+ defer fc.l.Unlock()
+ end := fc.time.Add(d)
+ var newSleepers []*sleeper
+ for _, s := range fc.sleepers {
+ if end.Sub(s.until) >= 0 {
+ s.done <- end
+ } else {
+ newSleepers = append(newSleepers, s)
+ }
+ }
+ fc.sleepers = newSleepers
+ fc.blockers = notifyBlockers(fc.blockers, len(fc.sleepers))
+ fc.time = end
+}
+
+// BlockUntil will block until the fakeClock has the given number of sleepers
+// (callers of Sleep or After)
+func (fc *fakeClock) BlockUntil(n int) {
+ fc.l.Lock()
+ // Fast path: current number of sleepers is what we're looking for
+ if len(fc.sleepers) == n {
+ fc.l.Unlock()
+ return
+ }
+ // Otherwise, set up a new blocker
+ b := &blocker{
+ count: n,
+ ch: make(chan struct{}),
+ }
+ fc.blockers = append(fc.blockers, b)
+ fc.l.Unlock()
+ <-b.ch
+}
diff --git a/vendor/github.com/knative/test-infra/CONTRIBUTING.md b/vendor/github.com/knative/test-infra/CONTRIBUTING.md
new file mode 100644
index 00000000..bcfe857f
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/CONTRIBUTING.md
@@ -0,0 +1,3 @@
+# Contribution guidelines
+
+So you want to hack on Knative Test Infrastructure? Yay! Please refer to Knative's overall [contribution guidelines](https://github.com/knative/docs/blob/master/community/CONTRIBUTING.md) to find out how you can help.
diff --git a/vendor/github.com/knative/test-infra/LICENSE b/vendor/github.com/knative/test-infra/LICENSE
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/knative/test-infra/OWNERS b/vendor/github.com/knative/test-infra/OWNERS
new file mode 100644
index 00000000..ed29d401
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/OWNERS
@@ -0,0 +1,7 @@
+# The OWNERS file is used by prow to automatically merge approved PRs.
+
+approvers:
+- adrcunha
+- jessiezcc
+- srinivashegde86
+- steuhs
diff --git a/vendor/github.com/knative/test-infra/README.md b/vendor/github.com/knative/test-infra/README.md
new file mode 100644
index 00000000..aef58d8b
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/README.md
@@ -0,0 +1,12 @@
+# Knative Test Infrastructure
+
+The `test-infra` repository contains a collection of tools for testing Knative, collecting metrics
+and displaying test results.
+
+## High level architecture
+
+Knative uses [Prow](https://github.com/kubernetes/test-infra/tree/master/prow) to schedule testing and update issues.
+
+### E2E Testing
+
+Our E2E testing uses [kubetest](https://github.com/kubernetes/test-infra/blob/master/kubetest) to build/deploy/test Knative clusters.
diff --git a/vendor/github.com/knative/test-infra/WORKSPACE b/vendor/github.com/knative/test-infra/WORKSPACE
new file mode 100644
index 00000000..91db673d
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/WORKSPACE
@@ -0,0 +1,52 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Required rules for building kubernetes/test-infra
+# These all come from http://github.com/kubernetes/test-infra/blob/master/WORKSPACE
+
+http_archive(
+ name = "io_bazel_rules_go",
+ sha256 = "1868ff68d6079e31b2f09b828b58d62e57ca8e9636edff699247c9108518570b",
+ url = "https://github.com/bazelbuild/rules_go/releases/download/0.11.1/rules_go-0.11.1.tar.gz",
+)
+
+load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
+
+go_rules_dependencies()
+
+go_register_toolchains(
+ go_version = "1.10.2",
+)
+
+git_repository(
+ name = "io_bazel_rules_k8s",
+ commit = "3756369d4920033c32c12d16207e8ee14fee1b18",
+ remote = "https://github.com/bazelbuild/rules_k8s.git",
+)
+
+http_archive(
+ name = "io_bazel_rules_docker",
+ sha256 = "cef4e7adfc1df999891e086bf42bed9092cfdf374adb902f18de2c1d6e1e0197",
+ strip_prefix = "rules_docker-198367210c55fba5dded22274adde1a289801dc4",
+ urls = ["https://github.com/bazelbuild/rules_docker/archive/198367210c55fba5dded22274adde1a289801dc4.tar.gz"],
+)
+
+# External repositories
+
+git_repository(
+ name = "k8s",
+ remote = "http://github.com/kubernetes/test-infra.git",
+ commit = "dd12621d6178838097847abf5842ad8d08fc9308", # HEAD as of 8/1/2018
+)
+
diff --git a/vendor/github.com/knative/test-infra/ci/README.md b/vendor/github.com/knative/test-infra/ci/README.md
new file mode 100644
index 00000000..51b28edd
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/README.md
@@ -0,0 +1,3 @@
+# Continuous Integration / Continuous Deployment system
+
+This directory contains the configs for all systems related to Knative's CI/CD system.
diff --git a/vendor/github.com/knative/test-infra/ci/gubernator/README.md b/vendor/github.com/knative/test-infra/ci/gubernator/README.md
new file mode 100644
index 00000000..ea82acbc
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/gubernator/README.md
@@ -0,0 +1,5 @@
+# Gubernator config
+
+This directory contains the config for our [Gubernator](https://github.com/kubernetes/test-infra/tree/master/gubernator) instance.
+
+* `config.yaml` Gubernator configuration.
diff --git a/vendor/github.com/knative/test-infra/ci/gubernator/config.yaml b/vendor/github.com/knative/test-infra/ci/gubernator/config.yaml
new file mode 100644
index 00000000..e2f4879c
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/gubernator/config.yaml
@@ -0,0 +1,58 @@
+
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+default_external_services:
+ gcs_pull_prefix: knative-prow/pr-logs/pull
+ prow_url: prow.knative.dev
+default_org: knative
+default_repo: serving
+external_services:
+ knative:
+ gcs_bucket: knative-prow/
+ gcs_pull_prefix: knative-prow/pr-logs/pull
+ prow_url: prow.knative.dev
+jobs:
+ knative-prow/pr-logs/directory/:
+ - pull-knative-serving-build-tests
+ - pull-knative-serving-integration-tests
+ - pull-knative-serving-unit-tests
+ - pull-knative-eventing-build-tests
+ - pull-knative-eventing-integration-tests
+ - pull-knative-eventing-unit-tests
+ - pull-knative-docs-build-tests
+ - pull-knative-docs-unit-tests
+ - pull-knative-docs-integration-tests
+ - pull-knative-build-templates-unit-tests
+ - pull-knative-build-templates-build-tests
+ - pull-knative-build-templates-integration-tests
+ - pull-knative-build-pipeline-build-tests
+ - pull-knative-build-pipeline-unit-tests
+ - pull-knative-build-build-tests
+ - pull-knative-build-unit-tests
+ - pull-knative-build-integration-tests
+ - pull-knative-pkg-build-tests
+ - pull-knative-pkg-unit-tests
+ - pull-knative-pkg-integration-tests
+ - ci-knative-serving-continuous
+ - ci-knative-serving-release
+ - ci-knative-serving-playground
+ - ci-knative-build-continuous
+ - ci-knative-build-release
+ - ci-knative-eventing-continuous
+ - ci-knative-eventing-release
+ - ci-knative-build-templates-continuous
+ - ci-knative-docs-continuous
+ - ci-knative-pkg-continuous
+recursive_artifacts: false
diff --git a/vendor/github.com/knative/test-infra/ci/prow/Makefile b/vendor/github.com/knative/test-infra/ci/prow/Makefile
new file mode 100644
index 00000000..9b6fcfbe
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/Makefile
@@ -0,0 +1,42 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CLUSTER ?= prow
+PROJECT ?= knative-tests
+ZONE ?= us-central1-f
+JOB_NAMESPACE ?= test-pods
+
+PROW_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
+
+get-cluster-credentials:
+ gcloud container clusters get-credentials "$(CLUSTER)" --project="$(PROJECT)" --zone="$(ZONE)"
+
+update-config: get-cluster-credentials
+ kubectl create configmap config --from-file=config.yaml=config.yaml --dry-run -o yaml | kubectl replace configmap config -f -
+
+update-plugins: get-cluster-credentials
+ kubectl create configmap plugins --from-file=plugins.yaml=plugins.yaml --dry-run -o yaml | kubectl replace configmap plugins -f -
+
+update-boskos: get-cluster-credentials
+ kubectl apply -f boskos/config.yaml
+
+update-boskos-config: get-cluster-credentials
+ kubectl create configmap resources --from-file=config=boskos/resources.yaml --dry-run -o yaml | kubectl --namespace="$(JOB_NAMESPACE)" replace configmap resources -f -
+
+update-cluster: get-cluster-credentials
+ kubectl apply -f cluster.yaml
+
+test:
+ bazel run @k8s//prow/cmd/config -- --plugin-config=$(PROW_DIR)/plugins.yaml
+ bazel run @k8s//prow/cmd/config -- --config-path=$(PROW_DIR)/config.yaml
diff --git a/vendor/github.com/knative/test-infra/ci/prow/README.md b/vendor/github.com/knative/test-infra/ci/prow/README.md
new file mode 100644
index 00000000..04fd12e6
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/README.md
@@ -0,0 +1,10 @@
+# Prow config
+
+This directory contains the config for our [Prow](https://github.com/kubernetes/test-infra/tree/master/prow) instance.
+
+* `boskos` Configuration for the Boskos instance.
+* `Makefile` Commands to interact with the Prow instance regarding updates.
+* `cluster.yaml` Configuration of the Prow cluster.
+* `config.yaml` Configuration of the Prow jobs.
+* `config_start.yaml` Initial, empty configuration for Prow.
+* `plugins.yaml` Configuration of the Prow plugins.
diff --git a/vendor/github.com/knative/test-infra/ci/prow/boskos/README.md b/vendor/github.com/knative/test-infra/ci/prow/boskos/README.md
new file mode 100644
index 00000000..8e6e90ab
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/boskos/README.md
@@ -0,0 +1,6 @@
+# Boskos config
+
+This directory contains the config for our [Boskos](https://github.com/kubernetes/test-infra/tree/master/boskos) instance.
+
+* `config.yaml` Boskos configuration.
+* `resources.yaml` Pool of projects used by Boskos.
diff --git a/vendor/github.com/knative/test-infra/ci/prow/boskos/config.yaml b/vendor/github.com/knative/test-infra/ci/prow/boskos/config.yaml
new file mode 100644
index 00000000..a444d6cf
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/boskos/config.yaml
@@ -0,0 +1,152 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Boskos deployment for Knative Prow instance
+---
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ labels:
+ app: boskos
+ name: boskos-storage
+ namespace: test-pods
+spec:
+ claimRef:
+ name: boskos-volume-boskos-0
+ namespace: test-pods
+ capacity:
+ storage: 1Gi
+ accessModes:
+ - ReadWriteOnce
+ persistentVolumeReclaimPolicy: Retain
+ gcePersistentDisk:
+ pdName: boskos-storage
+ fsType: ext4
+---
+# Start of StatefulSet
+apiVersion: apps/v1beta1
+kind: StatefulSet
+metadata:
+ name: boskos
+ namespace: test-pods
+spec:
+ serviceName: "boskos"
+ replicas: 1 # one canonical source of resources
+ template:
+ metadata:
+ labels:
+ app: boskos
+ namespace: test-pods
+ spec:
+ serviceAccountName: "boskos"
+ terminationGracePeriodSeconds: 30
+ containers:
+ - name: boskos
+ image: gcr.io/k8s-testimages/boskos:v20180405-12e892d69
+ args:
+ - --storage=/store/boskos.json
+ - --config=/etc/config/config
+ - --namespace=test-pods
+ ports:
+ - containerPort: 8080
+ protocol: TCP
+ volumeMounts:
+ - name: boskos-volume
+ mountPath: /store
+ - name: boskos-config
+ mountPath: /etc/config
+ readOnly: true
+ volumes:
+ - name: boskos-config
+ configMap:
+ name: resources
+ volumeClaimTemplates:
+ - metadata:
+ name: boskos-volume
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: boskos
+ resources:
+ requests:
+ storage: 1Gi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: boskos
+ namespace: test-pods
+spec:
+ selector:
+ app: boskos
+ ports:
+ - name: default
+ protocol: TCP
+ port: 80
+ targetPort: 8080
+---
+# Janitor
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: boskos-janitor
+ labels:
+ app: boskos-janitor
+ namespace: test-pods
+spec:
+ replicas: 3 # 3 distributed janitor instances
+ template:
+ metadata:
+ labels:
+ app: boskos-janitor
+ spec:
+ serviceAccountName: "boskos"
+ terminationGracePeriodSeconds: 300
+ containers:
+ - name: boskos-janitor
+ image: gcr.io/k8s-testimages/janitor:v20180619-83c62c891
+ args:
+ - --service-account=/etc/service-account/service-account.json
+ - --resource-type=gke-project
+ - --pool-size=10
+ volumeMounts:
+ - mountPath: /etc/service-account
+ name: service
+ readOnly: true
+ volumes:
+ - name: service
+ secret:
+ secretName: service-account
+---
+# Reaper
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: boskos-reaper
+ labels:
+ app: boskos-reaper
+ namespace: test-pods
+spec:
+ replicas: 1 # one canonical source of resources
+ template:
+ metadata:
+ labels:
+ app: boskos-reaper
+ spec:
+ serviceAccountName: "boskos"
+ terminationGracePeriodSeconds: 30
+ containers:
+ - name: boskos-reaper
+ image: gcr.io/k8s-testimages/reaper:v20180402-43203f868
+ args:
+ - --resource-type=gke-project
diff --git a/vendor/github.com/knative/test-infra/ci/prow/boskos/config_start.yaml b/vendor/github.com/knative/test-infra/ci/prow/boskos/config_start.yaml
new file mode 100644
index 00000000..dc8d66b6
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/boskos/config_start.yaml
@@ -0,0 +1,23 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Initial configuration of Boskos
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: resources
+ namespace: test-pods
+data:
+ resources: ""
diff --git a/vendor/github.com/knative/test-infra/ci/prow/boskos/resources.yaml b/vendor/github.com/knative/test-infra/ci/prow/boskos/resources.yaml
new file mode 100644
index 00000000..26e098f4
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/boskos/resources.yaml
@@ -0,0 +1,28 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+resources:
+- names:
+ - knative-boskos-01
+ - knative-boskos-02
+ - knative-boskos-03
+ - knative-boskos-04
+ - knative-boskos-05
+ - knative-boskos-06
+ - knative-boskos-07
+ - knative-boskos-08
+ - knative-boskos-09
+ - knative-boskos-10
+ state: dirty
+ type: gke-project
diff --git a/vendor/github.com/knative/test-infra/ci/prow/cluster.yaml b/vendor/github.com/knative/test-infra/ci/prow/cluster.yaml
new file mode 100644
index 00000000..98e73b5f
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/cluster.yaml
@@ -0,0 +1,350 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file contains Kubernetes YAML files for the most important prow components.
+---
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+ name: prowjobs.prow.k8s.io
+spec:
+ group: prow.k8s.io
+ version: v1
+ names:
+ kind: ProwJob
+ singular: prowjob
+ plural: prowjobs
+ scope: Namespaced
+ validation:
+ openAPIV3Schema:
+ properties:
+ spec:
+ properties:
+ max_concurrency:
+ type: integer
+ minimum: 0
+ type:
+ type: string
+ enum:
+ - "presubmit"
+ - "postsubmit"
+ - "periodic"
+ - "batch"
+ status:
+ properties:
+ state:
+ type: string
+ enum:
+ - "triggered"
+ - "pending"
+ - "success"
+ - "failure"
+ - "aborted"
+ - "error"
+ anyOf:
+ - not:
+ properties:
+ state:
+ type: string
+ enum:
+ - "success"
+ - "failure"
+ - "error"
+ - "aborted"
+ - required:
+ - completionTime
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: hook
+ labels:
+ app: hook
+spec:
+ replicas: 2
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 1
+ template:
+ metadata:
+ labels:
+ app: hook
+ spec:
+ serviceAccountName: "hook"
+ terminationGracePeriodSeconds: 180
+ containers:
+ - name: hook
+ image: gcr.io/k8s-prow/hook:v20180803-387a62015
+ imagePullPolicy: Always
+ args:
+ - --dry-run=false
+ ports:
+ - name: http
+ containerPort: 8888
+ volumeMounts:
+ - name: hmac
+ mountPath: /etc/webhook
+ readOnly: true
+ - name: oauth
+ mountPath: /etc/github
+ readOnly: true
+ - name: config
+ mountPath: /etc/config
+ readOnly: true
+ - name: plugins
+ mountPath: /etc/plugins
+ readOnly: true
+ volumes:
+ - name: hmac
+ secret:
+ secretName: hmac-token
+ - name: oauth
+ secret:
+ secretName: oauth-token
+ - name: config
+ configMap:
+ name: config
+ - name: plugins
+ configMap:
+ name: plugins
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: hook
+spec:
+ selector:
+ app: hook
+ ports:
+ - port: 8888
+ type: NodePort
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: plank
+ labels:
+ app: plank
+spec:
+ replicas: 1 # Do not scale up.
+ template:
+ metadata:
+ labels:
+ app: plank
+ spec:
+ serviceAccountName: "plank"
+ containers:
+ - name: plank
+ image: gcr.io/k8s-prow/plank:v20180709-7109caeb1
+ args:
+ - --dry-run=false
+ volumeMounts:
+ - name: oauth
+ mountPath: /etc/github
+ readOnly: true
+ - name: config
+ mountPath: /etc/config
+ readOnly: true
+ volumes:
+ - name: oauth
+ secret:
+ secretName: oauth-token
+ - name: config
+ configMap:
+ name: config
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: sinker
+ labels:
+ app: sinker
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: sinker
+ spec:
+ serviceAccountName: "sinker"
+ containers:
+ - name: sinker
+ image: gcr.io/k8s-prow/sinker:v20180709-7109caeb1
+ volumeMounts:
+ - name: config
+ mountPath: /etc/config
+ readOnly: true
+ volumes:
+ - name: config
+ configMap:
+ name: config
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: deck
+ labels:
+ app: deck
+spec:
+ replicas: 2
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 1
+ template:
+ metadata:
+ labels:
+ app: deck
+ spec:
+ serviceAccountName: "deck"
+ terminationGracePeriodSeconds: 30
+ containers:
+ - name: deck
+ image: gcr.io/k8s-prow/deck:v20180709-7109caeb1
+ args:
+ - --hook-url=http://hook:8888/plugin-help
+ - --tide-url=http://tide/
+ ports:
+ - name: http
+ containerPort: 8080
+ volumeMounts:
+ - name: config
+ mountPath: /etc/config
+ readOnly: true
+ volumes:
+ - name: config
+ configMap:
+ name: config
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: deck
+spec:
+ selector:
+ app: deck
+ ports:
+ - port: 80
+ targetPort: 8080
+ type: NodePort
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: horologium
+ labels:
+ app: horologium
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: horologium
+ spec:
+ serviceAccountName: "horologium"
+ terminationGracePeriodSeconds: 30
+ containers:
+ - name: horologium
+ image: gcr.io/k8s-prow/horologium:v20180709-7109caeb1
+ volumeMounts:
+ - name: config
+ mountPath: /etc/config
+ readOnly: true
+ volumes:
+ - name: config
+ configMap:
+ name: config
+
+# Ingresses
+
+---
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: deck-ing
+ annotations:
+ kubernetes.io/ingress.class: "gce"
+ kubernetes.io/ingress.global-static-ip-name: prow-ingress
+spec:
+ tls:
+ - secretName: tls-secret
+ hosts:
+ - prow.knative.dev
+ rules:
+ - host: prow.knative.dev
+ http:
+ paths:
+ - path: /*
+ backend:
+ serviceName: deck
+ servicePort: 80
+ - path: /hook
+ backend:
+ serviceName: hook
+ servicePort: 8888
+
+# Tide
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: tide
+spec:
+ selector:
+ app: tide
+ ports:
+ - port: 80
+ targetPort: 8888
+ type: NodePort
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: tide
+ labels:
+ app: tide
+spec:
+ replicas: 1 # Do not scale up.
+ template:
+ metadata:
+ labels:
+ app: tide
+ spec:
+ serviceAccountName: "tide"
+ containers:
+ - name: tide
+ image: gcr.io/k8s-prow/tide:v20180808-68cee5a41
+ args:
+ - --dry-run=false
+ ports:
+ - name: http
+ containerPort: 8888
+ volumeMounts:
+ - name: oauth
+ mountPath: /etc/github
+ readOnly: true
+ - name: config
+ mountPath: /etc/config
+ readOnly: true
+ volumes:
+ - name: oauth
+ secret:
+ secretName: oauth-token
+ - name: config
+ configMap:
+ name: config
+
diff --git a/vendor/github.com/knative/test-infra/ci/prow/config.yaml b/vendor/github.com/knative/test-infra/ci/prow/config.yaml
new file mode 100644
index 00000000..5a492465
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/config.yaml
@@ -0,0 +1,2002 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+plank:
+ job_url_template: 'https://gubernator.knative.dev/build/knative-prow/{{if or (eq .Spec.Type "presubmit") (eq .Spec.Type "batch")}}pr-logs/pull{{with .Spec.Refs}}/{{.Org}}_{{.Repo}}{{end}}{{else}}logs{{end}}{{if eq .Spec.Type "presubmit"}}/{{with index .Spec.Refs.Pulls 0}}{{.Number}}{{end}}{{else if eq .Spec.Type "batch"}}/batch{{end}}/{{.Spec.Job}}/{{.Status.BuildID}}/'
+ report_template: '[Full PR test history](https://gubernator.knative.dev/pr/{{.Spec.Refs.Org}}_{{.Spec.Refs.Repo}}/{{with index .Spec.Refs.Pulls 0}}{{.Number}}{{end}}). [Your PR dashboard](https://gubernator.knative.dev/pr/{{with index .Spec.Refs.Pulls 0}}{{.Author}}{{end}}).'
+ pod_pending_timeout: 60m
+ default_decoration_config:
+ timeout: 7200000000000 # 2h
+ grace_period: 15000000000 # 15s
+ utility_images:
+ clonerefs: "gcr.io/k8s-prow/clonerefs@sha256:b62ba1f379ac19c5ec9ee7bcab14d3f0b3c31cea9cdd4bc491e98e2c5f346c07"
+ initupload: "gcr.io/k8s-prow/initupload@sha256:58f89f2aae68f7dc46aaf05c7e8204c4f26b53ec9ce30353d1c27ce44a60d121"
+ entrypoint: "gcr.io/k8s-prow/entrypoint:v20180512-0255926d1"
+ sidecar: "gcr.io/k8s-prow/sidecar@sha256:8807b2565f4d2699920542fcf890878824b1ede4198d7ff46bca53feb064ed44"
+ gcs_configuration:
+ bucket: "knative-prow"
+ path_strategy: "explicit"
+ gcs_credentials_secret: "service-account"
+
+prowjob_namespace: default
+pod_namespace: test-pods
+log_level: info
+
+branch-protection:
+ orgs:
+ knative:
+ # Protect all branches in knative
+ # This means all prow jobs with "always_run" set are required
+ # to pass before tide can merge the PR.
+ # Currently this is manually enabled by the knative org admins,
+ # but it's stated here for documentation and reference purposes.
+ protect: true
+ # Admins can overrule checks
+ enforce_admins: false
+
+tide:
+ queries:
+ - repos:
+ - knative/build
+ - knative/build-pipeline
+ - knative/build-templates
+ - knative/serving
+ - knative/eventing
+ - knative/docs
+ - knative/test-infra
+ - knative/pkg
+ labels:
+ - lgtm
+ - approved
+ missingLabels:
+ - do-not-merge/hold
+ - do-not-merge/work-in-progress
+ merge_method:
+ knative: squash
+ target_url: https://prow.knative.dev/tide.html
+
+presets:
+- labels:
+ preset-service-account: "true"
+ env:
+ - name: GOOGLE_APPLICATION_CREDENTIALS
+ value: /etc/service-account/service-account.json
+ volumes:
+ - name: service
+ secret:
+ secretName: service-account
+ volumeMounts:
+ - name: service
+ mountPath: /etc/service-account
+ readOnly: true
+- labels:
+ preset-k8s-ssh: "true"
+ env:
+ - name: USER
+ value: prow
+ - name: JENKINS_GCE_SSH_PRIVATE_KEY_FILE
+ value: /etc/ssh-key-secret/ssh-private
+ - name: JENKINS_GCE_SSH_PUBLIC_KEY_FILE
+ value: /etc/ssh-key-secret/ssh-public
+ volumes:
+ - name: ssh
+ secret:
+ defaultMode: 0400
+ secretName: ssh-key-secret
+ volumeMounts:
+ - name: ssh
+ mountPath: /etc/ssh-key-secret
+ readOnly: true
+# storage / caching presets
+- labels:
+ preset-bazel-scratch-dir: "true"
+ env:
+ - name: TEST_TMPDIR
+ value: /bazel-scratch/.cache/bazel
+ volumes:
+ - name: bazel-scratch
+ emptyDir: {}
+ volumeMounts:
+ - name: bazel-scratch
+ mountPath: /bazel-scratch/.cache
+- labels:
+ preset-bazel-remote-cache-enabled: "false"
+ env:
+ - name: BAZEL_REMOTE_CACHE_ENABLED
+ value: "false"
+# docker-in-docker presets
+- labels:
+ preset-dind-enabled: "true"
+ env:
+ - name: DOCKER_IN_DOCKER_ENABLED
+ value: "true"
+ volumes:
+ - name: docker-graph
+ emptyDir: {}
+ volumeMounts:
+ - name: docker-graph
+ mountPath: /docker-graph
+
+presubmits:
+ knative/serving:
+ - name: pull-knative-serving-build-tests
+ agent: kubernetes
+ context: pull-knative-serving-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-serving-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-serving-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-serving-unit-tests
+ agent: kubernetes
+ context: pull-knative-serving-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-serving-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-serving-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-serving-integration-tests
+ agent: kubernetes
+ context: pull-knative-serving-integration-tests
+ always_run: true
+ rerun_command: "/test pull-knative-serving-integration-tests"
+ trigger: "(?m)^/test (all|pull-knative-serving-integration-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--integration-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-serving-go-coverage
+ labels:
+ preset-service-account: "true"
+ agent: kubernetes
+ context: pull-knative-serving-go-coverage
+ always_run: true
+ rerun_command: "/test pull-knative-serving-go-coverage"
+ trigger: "(?m)^/test (all|pull-knative-serving-go-coverage),?(\\s+|$)"
+ optional: true
+ decorate: true
+ clone_uri: "git@github.com:knative/serving.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--postsubmit-gcs-bucket=knative-prow"
+ - "--postsubmit-job-name=post-knative-serving-go-coverage"
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=50"
+ - "--github-token=/etc/github-token/token"
+ volumeMounts:
+ - name: github-token
+ mountPath: /etc/github-token
+ readOnly: true
+ volumes:
+ - name: github-token
+ secret:
+ secretName: covbot-token
+
+ - name: pull-knative-serving-go-coverage-dev
+ labels:
+ preset-service-account: "true"
+ agent: kubernetes
+ context: pull-knative-serving-go-coverage-dev
+ always_run: false
+ rerun_command: "/test pull-knative-serving-go-coverage-dev"
+ trigger: "(?m)^/test (pull-knative-serving-go-coverage-dev),?(\\s+|$)"
+ optional: true
+ decorate: true
+ clone_uri: "git@github.com:knative/serving.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage-dev:latest-dev
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--postsubmit-gcs-bucket=knative-prow"
+ - "--postsubmit-job-name=post-knative-serving-go-coverage"
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=81"
+ - "--github-token=/etc/github-token/token"
+ volumeMounts:
+ - name: github-token
+ mountPath: /etc/github-token
+ readOnly: true
+ volumes:
+ - name: github-token
+ secret:
+ secretName: covbot-token
+
+ knative/build:
+ - name: pull-knative-build-build-tests
+ agent: kubernetes
+ context: pull-knative-build-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-build-unit-tests
+ agent: kubernetes
+ context: pull-knative-build-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-build-integration-tests
+ agent: kubernetes
+ context: pull-knative-build-integration-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-integration-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-integration-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--integration-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-build-go-coverage
+ labels:
+ preset-service-account: "true"
+ agent: kubernetes
+ context: pull-knative-build-go-coverage
+ always_run: true
+ rerun_command: "/test pull-knative-build-go-coverage"
+ trigger: "(?m)^/test (all|pull-knative-build-go-coverage),?(\\s+|$)"
+ optional: true
+ decorate: true
+ clone_uri: "git@github.com:knative/build.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--postsubmit-gcs-bucket=knative-prow"
+ - "--postsubmit-job-name=post-knative-build-go-coverage"
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=50"
+ - "--github-token=/etc/github-token/token"
+ volumeMounts:
+ - name: github-token
+ mountPath: /etc/github-token
+ readOnly: true
+ volumes:
+ - name: github-token
+ secret:
+ secretName: covbot-token
+
+ knative/build-pipeline:
+ - name: pull-knative-build-pipeline-build-tests
+ agent: kubernetes
+ context: pull-knative-build-pipeline-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-pipeline-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-pipeline-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-build-pipeline-unit-tests
+ agent: kubernetes
+ context: pull-knative-build-pipeline-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-pipeline-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-pipeline-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ knative/eventing:
+ - name: pull-knative-eventing-build-tests
+ agent: kubernetes
+ context: pull-knative-eventing-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-eventing-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-eventing-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-eventing-unit-tests
+ agent: kubernetes
+ context: pull-knative-eventing-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-eventing-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-eventing-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-eventing-integration-tests
+ agent: kubernetes
+ context: pull-knative-eventing-integration-tests
+ always_run: true
+ rerun_command: "/test pull-knative-eventing-integration-tests"
+ trigger: "(?m)^/test (all|pull-knative-eventing-integration-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--integration-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-eventing-go-coverage
+ labels:
+ preset-service-account: "true"
+ agent: kubernetes
+ context: pull-knative-eventing-go-coverage
+ always_run: true
+ rerun_command: "/test pull-knative-eventing-go-coverage"
+ trigger: "(?m)^/test (all|pull-knative-eventing-go-coverage),?(\\s+|$)"
+ optional: true
+ decorate: true
+ clone_uri: "git@github.com:knative/eventing.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--postsubmit-gcs-bucket=knative-prow"
+ - "--postsubmit-job-name=post-knative-eventing-go-coverage"
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=50"
+ - "--github-token=/etc/github-token/token"
+ volumeMounts:
+ - name: github-token
+ mountPath: /etc/github-token
+ readOnly: true
+ volumes:
+ - name: github-token
+ secret:
+ secretName: covbot-token
+
+ knative/docs:
+ - name: pull-knative-docs-build-tests
+ agent: kubernetes
+ context: pull-knative-docs-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-docs-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-docs-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-docs-unit-tests
+ agent: kubernetes
+ context: pull-knative-docs-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-docs-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-docs-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-docs-integration-tests
+ agent: kubernetes
+ context: pull-knative-docs-integration-tests
+ always_run: true
+ rerun_command: "/test pull-knative-docs-integration-tests"
+ trigger: "(?m)^/test (all|pull-knative-docs-integration-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--integration-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-docs-go-coverage
+ labels:
+ preset-service-account: "true"
+ agent: kubernetes
+ context: pull-knative-docs-go-coverage
+ always_run: true
+ rerun_command: "/test pull-knative-docs-go-coverage"
+ trigger: "(?m)^/test (all|pull-knative-docs-go-coverage),?(\\s+|$)"
+ optional: true
+ decorate: true
+ clone_uri: "git@github.com:knative/docs.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--postsubmit-gcs-bucket=knative-prow"
+ - "--postsubmit-job-name=post-knative-docs-go-coverage"
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=50"
+ - "--github-token=/etc/github-token/token"
+ volumeMounts:
+ - name: github-token
+ mountPath: /etc/github-token
+ readOnly: true
+ volumes:
+ - name: github-token
+ secret:
+ secretName: covbot-token
+
+ knative/build-templates:
+ - name: pull-knative-build-templates-build-tests
+ agent: kubernetes
+ context: pull-knative-build-templates-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-templates-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-templates-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-build-templates-unit-tests
+ agent: kubernetes
+ context: pull-knative-build-templates-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-templates-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-templates-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-build-templates-integration-tests
+ agent: kubernetes
+ context: pull-knative-build-templates-integration-tests
+ always_run: true
+ rerun_command: "/test pull-knative-build-templates-integration-tests"
+ trigger: "(?m)^/test (all|pull-knative-build-templates-integration-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--integration-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ knative/pkg:
+ - name: pull-knative-pkg-build-tests
+ agent: kubernetes
+ context: pull-knative-pkg-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-pkg-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-pkg-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-pkg-unit-tests
+ agent: kubernetes
+ context: pull-knative-pkg-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-pkg-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-pkg-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-pkg-integration-tests
+ agent: kubernetes
+ context: pull-knative-pkg-integration-tests
+ always_run: true
+ rerun_command: "/test pull-knative-pkg-integration-tests"
+ trigger: "(?m)^/test (all|pull-knative-pkg-integration-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--integration-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-pkg-go-coverage
+ labels:
+ preset-service-account: "true"
+ agent: kubernetes
+ context: pull-knative-pkg-go-coverage
+ always_run: true
+ rerun_command: "/test pull-knative-pkg-go-coverage"
+ trigger: "(?m)^/test (all|pull-knative-pkg-go-coverage),?(\\s+|$)"
+ optional: true
+ decorate: true
+ clone_uri: "git@github.com:knative/pkg.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--postsubmit-gcs-bucket=knative-prow"
+ - "--postsubmit-job-name=post-knative-pkg-go-coverage"
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./apis/ ./configmap/"
+ - "--cov-threshold-percentage=50"
+ - "--github-token=/etc/github-token/token"
+ volumeMounts:
+ - name: github-token
+ mountPath: /etc/github-token
+ readOnly: true
+ volumes:
+ - name: github-token
+ secret:
+ secretName: covbot-token
+
+ knative/test-infra:
+ - name: pull-knative-test-infra-build-tests
+ agent: kubernetes
+ context: pull-knative-test-infra-build-tests
+ always_run: true
+ rerun_command: "/test pull-knative-test-infra-build-tests"
+ trigger: "(?m)^/test (all|pull-knative-test-infra-build-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--build-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-test-infra-unit-tests
+ agent: kubernetes
+ context: pull-knative-test-infra-unit-tests
+ always_run: true
+ rerun_command: "/test pull-knative-test-infra-unit-tests"
+ trigger: "(?m)^/test (all|pull-knative-test-infra-unit-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--unit-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+ - name: pull-knative-test-infra-integration-tests
+ agent: kubernetes
+ context: pull-knative-test-infra-integration-tests
+ always_run: true
+ rerun_command: "/test pull-knative-test-infra-integration-tests"
+ trigger: "(?m)^/test (all|pull-knative-test-infra-integration-tests),?(\\s+|$)"
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/$(REPO_OWNER)/$(REPO_NAME)=$(PULL_REFS)"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/pr-logs"
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--integration-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+periodics:
+- cron: "1 * * * *" # Run every hour and one minute
+ name: ci-knative-serving-continuous
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/serving"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=50" # Avoid overrun
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--all-tests"
+ - "--emit-metrics"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "1 8 * * *" # Run at 01:01PST every day (08:01 UTC)
+ name: ci-knative-serving-release
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/serving"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=90" # 1.5h
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./hack/release.sh"
+ - "--publish"
+ - "--tag-release"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "1 9 * * 6" # Run at 02:01PST every Saturday (09:01 UTC)
+ name: ci-knative-serving-playground
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/serving"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=90" # 1.5h
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./hack/deploy.sh"
+ - "knative-playground"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "5 8 * * *" # Run at 01:05PST every day (08:05 UTC)
+ name: ci-knative-serving-latency
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ decorate: true
+ ssh_key_secrets:
+ - ssh-knative
+ extra_refs:
+ - org: knative
+ repo: serving
+ base_ref: master
+ clone_uri: "git@github.com:knative/serving.git"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/metrics:latest
+ imagePullPolicy: Always
+ command:
+ - "/metrics"
+ args:
+ - "--artifacts-dir=$(ARTIFACTS)"
+ - "--service-account=/etc/service-account/service-account.json"
+- cron: "5 8 * * *" # Run at 01:05PST every day (08:05 UTC)
+ name: ci-knative-serving-api-coverage
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ decorate: true
+ ssh_key_secrets:
+ - ssh-knative
+ extra_refs:
+ - org: knative
+ repo: serving
+ base_ref: master
+ clone_uri: "git@github.com:knative/serving.git"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/apicoverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/apicoverage"
+ args:
+ - "--artifacts-dir=$(ARTIFACTS)"
+ - "--service-account=/etc/service-account/service-account.json"
+- cron: "0 1 * * *" # Run at 01:00 every day
+ name: ci-knative-serving-go-coverage
+ agent: kubernetes
+ decorate: true
+ ssh_key_secrets:
+ - ssh-knative
+ extra_refs:
+ - org: knative
+ repo: serving
+ base_ref: master
+ clone_uri: "git@github.com:knative/serving.git"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=80"
+
+- cron: "15 * * * *" # Run every hour and 15 minutes
+ name: ci-knative-build-continuous
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/build"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=50" # Avoid overrun
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--all-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "31 8 * * *" # Run at 01:31PST every day (08:31 UTC)
+ name: ci-knative-build-release
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ preset-dind-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/build"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=90" # 1.5h
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./hack/release.sh"
+ - "--publish"
+ - "--tag-release"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "0 1 * * *" # Run at 01:00 every day
+ name: ci-knative-build-go-coverage
+ agent: kubernetes
+ decorate: true
+ ssh_key_secrets:
+ - ssh-knative
+ extra_refs:
+ - org: knative
+ repo: build
+ base_ref: master
+ clone_uri: "git@github.com:knative/build.git"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=80"
+
+- cron: "50 * * * *" # Run every hour and 50 minutes
+ name: ci-knative-docs-continuous
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/docs"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=50" # Avoid overrun
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--all-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "0 1 * * *" # Run at 01:00 every day
+ name: ci-knative-docs-go-coverage
+ agent: kubernetes
+ decorate: true
+ ssh_key_secrets:
+ - ssh-knative
+ extra_refs:
+ - org: knative
+ repo: docs
+ base_ref: master
+ clone_uri: "git@github.com:knative/docs.git"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=80"
+
+- cron: "30 * * * *" # Run every hour and 30 minutes
+ name: ci-knative-eventing-continuous
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/eventing"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=50" # Avoid overrun
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--all-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "16 9 * * *" # Run at 02:16PST every day (09:16 UTC)
+ name: ci-knative-eventing-release
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/eventing"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=90" # 1.5h
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./hack/release.sh"
+ - "--publish"
+ - "--tag-release"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "0 1 * * *" # Run at 01:00 every day
+ name: ci-knative-eventing-go-coverage
+ agent: kubernetes
+ decorate: true
+ ssh_key_secrets:
+ - ssh-knative
+ extra_refs:
+ - org: knative
+ repo: eventing
+ base_ref: master
+ clone_uri: "git@github.com:knative/eventing.git"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=80"
+
+- cron: "40 * * * *" # Run every hour and 40 minutes
+ name: ci-knative-build-templates-continuous
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/build-templates"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=50" # Avoid overrun
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--all-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+
+- cron: "45 * * * *" # Run every hour and 45 minutes
+ name: ci-knative-pkg-continuous
+ agent: kubernetes
+ labels:
+ preset-service-account: "true"
+ preset-bazel-scratch-dir: "true"
+ preset-bazel-remote-cache-enabled: "true"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/prow-tests:latest
+ imagePullPolicy: Always
+ args:
+ - "--ssh=/etc/ssh-knative/ssh-knative"
+ - "--scenario=kubernetes_execute_bazel"
+ - "--clean"
+ - "--job=$(JOB_NAME)"
+ - "--repo=github.com/knative/pkg"
+ - "--root=/go/src"
+ - "--service-account=/etc/service-account/service-account.json"
+ - "--upload=gs://knative-prow/logs"
+ - "--timeout=50" # Avoid overrun
+ - "--" # end bootstrap args, scenario args below
+ - "--" # end kubernetes_execute_bazel flags (consider following flags as text)
+ - "./test/presubmit-tests.sh"
+ - "--all-tests"
+ # Bazel needs privileged mode in order to sandbox builds.
+ securityContext:
+ privileged: true
+ resources:
+ requests:
+ memory: "1Gi"
+ volumeMounts:
+ - mountPath: /etc/ssh-knative
+ name: ssh-knative
+ volumes:
+ - name: ssh-knative
+ secret:
+ defaultMode: 256
+ secretName: ssh-knative
+- cron: "0 1 * * *" # Run at 01:00 every day
+ name: ci-knative-pkg-go-coverage
+ agent: kubernetes
+ decorate: true
+ ssh_key_secrets:
+ - ssh-knative
+ extra_refs:
+ - org: knative
+ repo: pkg
+ base_ref: master
+ clone_uri: "git@github.com:knative/pkg.git"
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./apis/ ./configmap/"
+ - "--cov-threshold-percentage=80"
+
+postsubmits:
+ knative/serving:
+ - name: post-knative-serving-go-coverage
+ branches:
+ - master
+ agent: kubernetes
+ decorate: true
+ clone_uri: "git@github.com:knative/serving.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=0"
+ - name: post-knative-serving-go-coverage-dev
+ branches:
+ - master
+ agent: kubernetes
+ decorate: true
+ clone_uri: "git@github.com:knative/serving.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage-dev:latest-dev
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=0"
+
+ knative/build:
+ - name: post-knative-build-go-coverage
+ branches:
+ - master
+ agent: kubernetes
+ decorate: true
+ clone_uri: "git@github.com:knative/build.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=0"
+
+ knative/docs:
+ - name: post-knative-docs-go-coverage
+ branches:
+ - master
+ agent: kubernetes
+ decorate: true
+ clone_uri: "git@github.com:knative/docs.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=0"
+
+ knative/eventing:
+ - name: post-knative-eventing-go-coverage
+ branches:
+ - master
+ agent: kubernetes
+ decorate: true
+ clone_uri: "git@github.com:knative/eventing.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./pkg/"
+ - "--cov-threshold-percentage=0"
+
+ knative/pkg:
+ - name: post-knative-pkg-go-coverage
+ branches:
+ - master
+ agent: kubernetes
+ decorate: true
+ clone_uri: "git@github.com:knative/pkg.git"
+ ssh_key_secrets:
+ - ssh-knative
+ spec:
+ containers:
+ - image: gcr.io/knative-tests/test-infra/coverage:latest
+ imagePullPolicy: Always
+ command:
+ - "/coverage"
+ args:
+ - "--artifacts=$(ARTIFACTS)"
+ - "--profile-name=coverage_profile.txt"
+ - "--cov-target=./apis/ ./configmap/"
+ - "--cov-threshold-percentage=0"
+
diff --git a/vendor/github.com/knative/test-infra/ci/prow/config_start.yaml b/vendor/github.com/knative/test-infra/ci/prow/config_start.yaml
new file mode 100644
index 00000000..ada1a3e6
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/config_start.yaml
@@ -0,0 +1,339 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Initial configuration of prow cluster
+
+# Configs
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: plugins
+data:
+ plugins: ""
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: config
+data:
+ config: ""
+---
+
+# Namespaces
+
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: prow
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: test-pods
+---
+
+# Service accounts, roles and bindings
+
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+ name: "boskos"
+ namespace: test-pods
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "boskos"
+ namespace: test-pods
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: boskos
+subjects:
+- kind: ServiceAccount
+ name: "boskos"
+ namespace: test-pods
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "boskos"
+ namespace: test-pods
+rules:
+ - apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ verbs:
+ - create
+ - apiGroups:
+ - boskos.k8s.io
+ resources:
+ - resources
+ verbs:
+ - "*"
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+ name: "default"
+ namespace: test-pods
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "test-pods-default"
+ namespace: test-pods
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "test-pods-default"
+subjects:
+- kind: ServiceAccount
+ name: "default"
+ namespace: test-pods
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "test-pods-default"
+ namespace: test-pods
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - get
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+ name: "deck"
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "deck"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "deck"
+subjects:
+- kind: ServiceAccount
+ name: "deck"
+ namespace: default
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "deck"
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods/log
+ verbs:
+ - get
+ - apiGroups:
+ - "prow.k8s.io"
+ resources:
+ - prowjobs
+ verbs:
+ - get
+ - list
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+ name: "horologium"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "horologium"
+rules:
+ - apiGroups:
+ - "prow.k8s.io"
+ resources:
+ - prowjobs
+ verbs:
+ - create
+ - list
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "horologium"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "horologium"
+subjects:
+- kind: ServiceAccount
+ name: "horologium"
+ namespace: default
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+ name: "plank"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "plank"
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - create
+ - delete
+ - list
+ - apiGroups:
+ - "prow.k8s.io"
+ resources:
+ - prowjobs
+ verbs:
+ - create
+ - list
+ - update
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "plank"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "plank"
+subjects:
+- kind: ServiceAccount
+ name: "plank"
+ namespace: default
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+ name: "sinker"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "sinker"
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - pods
+ verbs:
+ - delete
+ - list
+ - apiGroups:
+ - "prow.k8s.io"
+ resources:
+ - prowjobs
+ verbs:
+ - delete
+ - list
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "sinker"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "sinker"
+subjects:
+- kind: ServiceAccount
+ name: "sinker"
+ namespace: default
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: "hook"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "hook"
+rules:
+ - apiGroups:
+ - "prow.k8s.io"
+ resources:
+ - prowjobs
+ verbs:
+ - create
+ - get
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - update
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "hook"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "hook"
+subjects:
+- kind: ServiceAccount
+ name: "hook"
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: "tide"
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "tide"
+rules:
+ - apiGroups:
+ - "prow.k8s.io"
+ resources:
+ - prowjobs
+ verbs:
+ - create
+ - get
+ - list
+ - apiGroups:
+ - ""
+ resources:
+ - configmaps
+ verbs:
+ - update
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+ name: "tide"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: "tide"
+subjects:
+- kind: ServiceAccount
+ name: "tide"
+ namespace: default
diff --git a/vendor/github.com/knative/test-infra/ci/prow/plugins.yaml b/vendor/github.com/knative/test-infra/ci/prow/plugins.yaml
new file mode 100644
index 00000000..1760e588
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/plugins.yaml
@@ -0,0 +1,41 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+approve:
+- repos:
+ - knative
+ implicit_self_approve: true
+ review_acts_as_approve: false
+
+plugins:
+ knative:
+ - approve
+ - assign
+ - blunderbuss
+ - buildifier
+ - cat
+ - dog
+ - golint
+ - heart
+ - help
+ - hold
+ - label
+ - lgtm
+ - lifecycle
+ - shrug
+ - size
+ - skip
+ - trigger
+ - wip
+ - yuks
diff --git a/vendor/github.com/knative/test-infra/ci/prow/prow_setup.md b/vendor/github.com/knative/test-infra/ci/prow/prow_setup.md
new file mode 100644
index 00000000..107ce0bb
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/prow/prow_setup.md
@@ -0,0 +1,51 @@
+# Prow setup
+
+## Creating the cluster
+
+1. Create the GKE cluster, the role bindings and the GitHub secrets. You might need to update [Makefile](./Makefile). For details, see https://github.com/kubernetes/test-infra/blob/master/prow/getting_started.md.
+
+1. Ensure the GCP projects listed in [resources.yaml](./boskos/resources.yaml) are created.
+
+1. Apply [config_start.yaml](./config_start.yaml) to the cluster.
+
+1. Apply Boskos [config_start.yaml](./boskos/config_start.yaml) to the cluster.
+
+1. Run `make update-cluster`, `make update-boskos`, `make update-config`, `make update-plugins` and `make update-boskos-config`.
+
+1. If SSL needs to be reconfigured, promote your ingress IP to static in Cloud Console, and [create the TLS secret](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls).
+
+## Expanding Boskos pool
+
+1. Create a new GCP project and add it to [resources.yaml](./boskos/resources.yaml).
+
+1. Make `knative-tests@appspot.gserviceaccount.com` an editor of the project.
+
+1. Enable the Compute Engine API for the project (e.g., by visiting https://console.developers.google.com/apis/api/compute.googleapis.com/overview?project=XXXXXXXX).
+
+1. Enable the Kubernetes Engine API for the project (e.g., by visiting https://console.cloud.google.com/apis/api/container.googleapis.com/overview?project=XXXXXXXX).
+
+1. Run `make update-boskos-config`.
+
+## Setting up Prow for a new repo
+
+1. Create the appropriate `OWNERS` files (at least one for the root dir).
+
+1. Make sure that *Knative Robots* is an Admin of the repo.
+
+1. Update the Prow config file (copy and update an existing config for another repo) and run `make update-config`.
+
+1. Wait a few minutes, check that Prow is working by entering `/woof` as a comment in any PR in the new repo.
+
+1. Set **tide** as a required status check for the master branch.
+
+### Setting up test jobs
+
+1. Have the test infrastructure in place (usually this means having `//test/presubmit-tests.sh` working).
+
+1. Update the Prow config file (copy and update an existing config for another repo) and run `make update-config` (usually this means setting up the *pull-knative-**repo**-**(build|unit|integration)**-tests* jobs).
+
+1. Update the Gubernator config with the new log dirs.
+
+1. Wait a few minutes, enter `/retest` as a comment in any PR in the repo and ensure the test jobs are executed.
+
+1. Set the new test jobs as required status checks for the master branch.
diff --git a/vendor/github.com/knative/test-infra/ci/testgrid/Makefile b/vendor/github.com/knative/test-infra/ci/testgrid/Makefile
new file mode 100644
index 00000000..5cf42d99
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/testgrid/Makefile
@@ -0,0 +1,29 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+TESTGRID_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
+
+test:
+ bazel run @k8s//testgrid/cmd/configurator -- \
+ --yaml=$(TESTGRID_DIR)/config.yaml \
+ --validate-config-file
+
+update-config:
+ifndef GOOGLE_APPLICATION_CREDENTIALS
+ $(error GOOGLE_APPLICATION_CREDENTIALS not set)
+endif
+ bazel run @k8s//testgrid/cmd/configurator -- \
+ --yaml=$(TESTGRID_DIR)/config.yaml \
+ --output=gs://knative-testgrid/config \
+ --oneshot
diff --git a/vendor/github.com/knative/test-infra/ci/testgrid/README.md b/vendor/github.com/knative/test-infra/ci/testgrid/README.md
new file mode 100644
index 00000000..7b028e04
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/testgrid/README.md
@@ -0,0 +1,6 @@
+# Testgrid config
+
+This directory contains the config for our [Testgrid](https://github.com/kubernetes/test-infra/tree/master/testgrid) instance.
+
+* `Makefile` Commands to interact with the Testgrid instance regarding updates.
+* `config.yaml` Testgrid configuration.
diff --git a/vendor/github.com/knative/test-infra/ci/testgrid/config.yaml b/vendor/github.com/knative/test-infra/ci/testgrid/config.yaml
new file mode 100644
index 00000000..df6f6ee8
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/ci/testgrid/config.yaml
@@ -0,0 +1,167 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default testgroup and dashboardtab, please do not change them
+default_test_group:
+ days_of_results: 14 # Number of days of test results to gather and serve
+ tests_name_policy: 2 # Replace the name of the test
+ ignore_pending: false # Show in-progress tests
+ column_header:
+ - configuration_value: Commit # Shows the commit number on column header
+ - configuration_value: infra-commit
+ num_columns_recent: 10 # The number of columns to consider "recent" for a variety of purposes
+ use_kubernetes_client: true # ** This field is deprecated and should always be true **
+ is_external: true # ** This field is deprecated and should always be true **
+ alert_stale_results_hours: 0 # Don't alert for staleness by default
+ num_failures_to_alert: 3 # Consider a test failed if it has 3 or more consecutive failures
+ num_passes_to_disable_alert: 1 # Consider a failing test passing if it has 1 or more consecutive passes
+
+default_dashboard_tab:
+ open_test_template: # The URL template to visit after clicking on a cell
+ url: https://gubernator.knative.dev/build//
+ file_bug_template: # The URL template to visit when filing a bug
+ url: https://github.com/knative/serving/issues/new
+ options:
+ - key: title
+ value: 'Test "" failed'
+ - key: body
+ value:
+ attach_bug_template: # The URL template to visit when attaching a bug
+ url: # Empty
+ options: # Empty
+ # Text to show in the about menu as a link to another view of the results
+ results_text: See these results in Gubernator
+ results_url_template: # The URL template to visit after clicking
+ url: https://gubernator.knative.dev/builds/
+ # URL for regression search links.
+ code_search_path: github.com/knative/serving/search
+ num_columns_recent: 10
+ code_search_url_template: # The URL template to visit when searching for changelists
+ url: https://github.com/knative/serving/compare/...
+
+# Test groups
+
+test_groups:
+- name: ci-knative-serving-continuous
+ gcs_prefix: knative-prow/logs/ci-knative-serving-continuous
+- name: ci-knative-serving-release
+ gcs_prefix: knative-prow/logs/ci-knative-serving-release
+- name: ci-knative-serving-playground
+ gcs_prefix: knative-prow/logs/ci-knative-serving-playground
+- name: pull-knative-serving-test-coverage
+ gcs_prefix: knative-prow/logs/ci-knative-serving-go-coverage
+ short_text_metric: coverage
+- name: ci-knative-serving-latency
+ gcs_prefix: knative-prow/logs/ci-knative-serving-latency
+ short_text_metric: latency
+- name: ci-knative-serving-api-coverage
+ gcs_prefix: knative-prow/logs/ci-knative-serving-api-coverage
+ short_text_metric: api_coverage
+- name: ci-knative-build-continuous
+ gcs_prefix: knative-prow/logs/ci-knative-build-continuous
+- name: ci-knative-build-release
+ gcs_prefix: knative-prow/logs/ci-knative-build-release
+- name: pull-knative-build-test-coverage
+ gcs_prefix: knative-prow/logs/ci-knative-build-go-coverage
+ short_text_metric: coverage
+- name: ci-knative-eventing-continuous
+ gcs_prefix: knative-prow/logs/ci-knative-eventing-continuous
+- name: ci-knative-eventing-release
+ gcs_prefix: knative-prow/logs/ci-knative-eventing-release
+- name: pull-knative-eventing-test-coverage
+ gcs_prefix: knative-prow/logs/ci-knative-eventing-go-coverage
+ short_text_metric: coverage
+- name: ci-knative-build-templates-continuous
+ gcs_prefix: knative-prow/logs/ci-knative-build-templates-continuous
+- name: ci-knative-docs-continuous
+ gcs_prefix: knative-prow/logs/ci-knative-docs-continuous
+- name: pull-knative-docs-test-coverage
+ gcs_prefix: knative-prow/logs/ci-knative-docs-go-coverage
+ short_text_metric: coverage
+- name: ci-knative-pkg-continuous
+ gcs_prefix: knative-prow/logs/ci-knative-pkg-continuous
+- name: pull-knative-pkg-test-coverage
+ gcs_prefix: knative-prow/logs/ci-knative-pkg-go-coverage
+ short_text_metric: coverage
+
+# Dashboards
+
+dashboards:
+- name: knative-serving
+ dashboard_tab:
+ - name: continuous
+ test_group_name: ci-knative-serving-continuous
+ - name: release
+ test_group_name: ci-knative-serving-release
+ - name: playground
+ test_group_name: ci-knative-serving-playground
+ - name: coverage
+ test_group_name: pull-knative-serving-test-coverage
+ base_options: 'exclude-filter-by-regex=Overall&group-by-directory=&expand-groups=&sort-by-name='
+ - name: latency
+ test_group_name: ci-knative-serving-latency
+ description: '95% latency in ms'
+ base_options: 'exclude-filter-by-regex=Overall&group-by-directory=&expand-groups=&sort-by-name='
+ - name: api-coverage
+ test_group_name: ci-knative-serving-api-coverage
+ description: 'Conformance tests API coverage.'
+ base_options: 'exclude-filter-by-regex=Overall$&group-by-directory=&expand-groups=&sort-by-name='
+- name: knative-build
+ dashboard_tab:
+ - name: continuous
+ test_group_name: ci-knative-build-continuous
+ - name: release
+ test_group_name: ci-knative-build-release
+ - name: coverage
+ test_group_name: pull-knative-build-test-coverage
+ base_options: 'exclude-filter-by-regex=Overall&group-by-directory=&expand-groups=&sort-by-name='
+- name: knative-eventing
+ dashboard_tab:
+ - name: continuous
+ test_group_name: ci-knative-eventing-continuous
+ - name: release
+ test_group_name: ci-knative-eventing-release
+ - name: coverage
+ test_group_name: pull-knative-eventing-test-coverage
+ base_options: 'exclude-filter-by-regex=Overall&group-by-directory=&expand-groups=&sort-by-name='
+- name: knative-build-templates
+ dashboard_tab:
+ - name: continuous
+ test_group_name: ci-knative-build-templates-continuous
+- name: knative-docs
+ dashboard_tab:
+ - name: continuous
+ test_group_name: ci-knative-docs-continuous
+ - name: coverage
+ test_group_name: pull-knative-docs-test-coverage
+ base_options: 'exclude-filter-by-regex=Overall&group-by-directory=&expand-groups=&sort-by-name='
+- name: knative-pkg
+ dashboard_tab:
+ - name: continuous
+ test_group_name: ci-knative-pkg-continuous
+ - name: coverage
+ test_group_name: pull-knative-pkg-test-coverage
+ base_options: 'exclude-filter-by-regex=Overall&group-by-directory=&expand-groups=&sort-by-name='
+
+# Dashboard groups
+
+dashboard_groups:
+- name: knative
+ dashboard_names:
+ - knative-serving
+ - knative-build
+ - knative-eventing
+ - knative-build-templates
+ - knative-docs
+ - knative-pkg
diff --git a/vendor/github.com/knative/test-infra/dummy.go b/vendor/github.com/knative/test-infra/dummy.go
new file mode 100644
index 00000000..c32a5c7d
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/dummy.go
@@ -0,0 +1,10 @@
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ fmt.Println("This is a dummy go file so `go dep` can be used with knative/test-infra repo")
+ fmt.Println("This file can be removed once the repo contains real, useful go code")
+}
diff --git a/vendor/github.com/knative/test-infra/images/README.md b/vendor/github.com/knative/test-infra/images/README.md
new file mode 100644
index 00000000..22b9b16e
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/images/README.md
@@ -0,0 +1,3 @@
+# Prow Job Images
+
+This directory contains custom Docker images used by our Prow jobs.
diff --git a/vendor/github.com/knative/test-infra/images/apicoverage/Dockerfile b/vendor/github.com/knative/test-infra/images/apicoverage/Dockerfile
new file mode 100644
index 00000000..897ec7d8
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/images/apicoverage/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM golang:1.10.2
+LABEL maintainer "Srinivas Hegde "
+RUN apt-get update && apt-get install -y --no-install-recommends
+
+COPY apicoverage /apicoverage
+ENTRYPOINT ["/apicoverage"]
diff --git a/vendor/github.com/knative/test-infra/images/apicoverage/Makefile b/vendor/github.com/knative/test-infra/images/apicoverage/Makefile
new file mode 100644
index 00000000..b5a87ca5
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/images/apicoverage/Makefile
@@ -0,0 +1,23 @@
+
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+REGISTRY ?= gcr.io
+PROJECT ?= knative-tests/test-infra
+PUSH ?= docker push
+
+apicoverage-image:
+ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ../../tools/apicoverage
+ docker build -t "$(REGISTRY)/$(PROJECT)/apicoverage:latest" .
+ $(PUSH) "$(REGISTRY)/$(PROJECT)/apicoverage:latest"
diff --git a/vendor/github.com/knative/test-infra/images/apicoverage/README.md b/vendor/github.com/knative/test-infra/images/apicoverage/README.md
new file mode 100644
index 00000000..b8557773
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/images/apicoverage/README.md
@@ -0,0 +1,3 @@
+# API coverage tool Image
+
+This directory contains the custom docker image used for calculating the API coverage by the conformance tests.
diff --git a/vendor/github.com/knative/test-infra/images/prow-tests/Dockerfile b/vendor/github.com/knative/test-infra/images/prow-tests/Dockerfile
new file mode 100644
index 00000000..bb3f45e1
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/images/prow-tests/Dockerfile
@@ -0,0 +1,52 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FROM gcr.io/k8s-testimages/kubekins-e2e:v20180604-68e777553-experimental
+LABEL maintainer "Adriano Cunha "
+
+# Install extras on top of base image
+
+ENV DEBIAN_FRONTEND noninteractive
+RUN apt-get update
+
+# Docker
+RUN gcloud components install docker-credential-gcr
+RUN docker-credential-gcr configure-docker
+
+# Extra tools through apt-get
+RUN apt-get install -y uuid-runtime # for uuidgen
+RUN apt-get install -y npm # for markdown-link-check
+RUN apt-get install -y rubygems # for mdl
+RUN apt-get install -y build-essential libssl-dev # for wrk
+
+# Extra tools through go get
+RUN go get -u github.com/google/go-containerregistry/cmd/ko
+RUN go get -u github.com/golang/dep/cmd/dep
+RUN go get -u github.com/mattmoor/dep-collector
+RUN go get -u github.com/google/licenseclassifier
+
+# Extra tools through npm
+RUN npm install -g markdown-link-check
+
+# Extra tools through gem
+RUN gem install mixlib-config -v 2.2.4 # required because ruby is 2.1
+RUN gem install mdl
+
+# Install wrk
+RUN git clone https://github.com/wg/wrk.git wrk
+RUN make -C wrk/
+RUN cp wrk/wrk /usr/local/bin
+
+# Extra custom tools
+ADD githubhelper .
diff --git a/vendor/github.com/knative/test-infra/images/prow-tests/Makefile b/vendor/github.com/knative/test-infra/images/prow-tests/Makefile
new file mode 100644
index 00000000..7f4cbc53
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/images/prow-tests/Makefile
@@ -0,0 +1,32 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+IMG = gcr.io/knative-tests/test-infra/prow-tests
+TAG := $(shell date +v%Y%m%d)-$(shell git describe --tags --always --dirty)
+
+all: build
+
+build:
+ make -C ../../tools/githubhelper
+ mv ../../tools/githubhelper/githubhelper .
+ docker build -t $(IMG):$(TAG) .
+ docker tag $(IMG):$(TAG) $(IMG):latest
+
+push_versioned: build
+ docker push $(IMG):$(TAG)
+
+push_latest: build
+ docker push $(IMG):latest
+
+push: push_versioned push_latest
diff --git a/vendor/github.com/knative/test-infra/images/prow-tests/README.md b/vendor/github.com/knative/test-infra/images/prow-tests/README.md
new file mode 100644
index 00000000..d3eb4437
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/images/prow-tests/README.md
@@ -0,0 +1,3 @@
+# Prow Test Job Image
+
+This directory contains the custom Docker image used by our Prow test jobs.
diff --git a/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh b/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh
index 1262f982..2218d41e 100755
--- a/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh
+++ b/vendor/github.com/knative/test-infra/scripts/e2e-tests.sh
@@ -103,12 +103,15 @@ function download_k8s() {
local gke_versions=(`echo -n ${versions//;/ /}`)
# Get first (latest) version, excluding the "-gke.#" suffix
version="${gke_versions[0]%-*}"
- echo "Latest GKE is ${version}, from [${versions//;/, /}]"
+ echo "Latest GKE is ${version}, from [${versions//;/, }]"
elif [[ "${version}" == "default" ]]; then
echo "ERROR: `default` GKE version is not supported yet"
return 1
fi
# Download k8s to staging dir
+ if [[ -z "${GOPATH}" ]]; then
+ local GOPATH=$(go env GOPATH)
+ fi
version=v${version}
local staging_dir=${GOPATH}/src/k8s.io/kubernetes/_output/gcs-stage
rm -fr ${staging_dir}
@@ -155,7 +158,7 @@ function create_test_cluster() {
header "Creating test cluster"
# Smallest cluster required to run the end-to-end-tests
local CLUSTER_CREATION_ARGS=(
- --gke-create-args="--enable-autoscaling --min-nodes=1 --max-nodes=${E2E_CLUSTER_NODES} --scopes=cloud-platform"
+ --gke-create-args="--enable-autoscaling --min-nodes=1 --max-nodes=${E2E_CLUSTER_NODES} --scopes=cloud-platform --enable-basic-auth --no-issue-client-certificate"
--gke-shape={\"default\":{\"Nodes\":${E2E_CLUSTER_NODES}\,\"MachineType\":\"${E2E_CLUSTER_MACHINE}\"}}
--provider=gke
--deployment=gke
diff --git a/vendor/github.com/knative/test-infra/scripts/library.sh b/vendor/github.com/knative/test-infra/scripts/library.sh
index d9cdb101..f5ff0a87 100755
--- a/vendor/github.com/knative/test-infra/scripts/library.sh
+++ b/vendor/github.com/knative/test-infra/scripts/library.sh
@@ -164,8 +164,21 @@ function acquire_cluster_admin_role() {
# might not have the necessary permission.
local password=$(gcloud --format="value(masterAuth.password)" \
container clusters describe $2 --zone=$3)
- kubectl config set-credentials cluster-admin \
- --username=admin --password=${password}
+ if [[ -n "${password}" ]]; then
+ # Cluster created with basic authentication
+ kubectl config set-credentials cluster-admin \
+ --username=admin --password=${password}
+ else
+ local cert=$(mktemp)
+ local key=$(mktemp)
+ echo "Certificate in ${cert}, key in ${key}"
+ gcloud --format="value(masterAuth.clientCertificate)" \
+ container clusters describe $2 --zone=$3 | base64 -d > ${cert}
+ gcloud --format="value(masterAuth.clientKey)" \
+ container clusters describe $2 --zone=$3 | base64 -d > ${key}
+ kubectl config set-credentials cluster-admin \
+ --client-certificate=${cert} --client-key=${key}
+ fi
kubectl config set-context $(kubectl config current-context) \
--user=cluster-admin
kubectl create clusterrolebinding cluster-admin-binding \
@@ -294,16 +307,36 @@ function check_licenses() {
run_dep_collector -check $@
}
-# Check links in all .md files in the repo.
-function check_links_in_markdown() {
- local checker="markdown-link-check"
+# Run the given linter on the given files, checking it exists first.
+# Parameters: $1 - tool
+# $2 - tool purpose (for error message if tool not installed)
+# $3 - tool parameters (quote if multiple parameters used)
+# $4..$n - files to run linter on
+function run_lint_tool() {
+ local checker=$1
+ local params=$3
if ! hash ${checker} 2>/dev/null; then
- warning "${checker} not installed, not checking links in .md files"
- return 0
+ warning "${checker} not installed, not $2"
+ return 127
fi
+ shift 3
local failed=0
- for md_file in $(find ${REPO_ROOT_DIR} -name \*.md); do
- ${checker} -q ${md_file} || failed=1
+ for file in $@; do
+ ${checker} ${params} ${file} || failed=1
done
return ${failed}
}
+
+# Check links in the given markdown files.
+# Parameters: $1...$n - files to inspect
+function check_links_in_markdown() {
+ # https://github.com/tcort/markdown-link-check
+ run_lint_tool markdown-link-check "checking links in markdown files" -q $@
+}
+
+# Check format of the given markdown files.
+# Parameters: $1...$n - files to inspect
+function lint_markdown() {
+ # https://github.com/markdownlint/markdownlint
+ run_lint_tool mdl "linting markdown files" "-r ~MD013" $@
+}
diff --git a/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh b/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh
index 37c00f43..b6116817 100755
--- a/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh
+++ b/vendor/github.com/knative/test-infra/scripts/presubmit-tests.sh
@@ -46,6 +46,10 @@ function exit_if_presubmit_not_required() {
if [[ -n "${PULL_PULL_SHA}" ]]; then
# On a presubmit job
local changes="$(/workspace/githubhelper -list-changed-files)"
+ if [[ -z "${changes}" ]]; then
+ header "NO CHANGED FILES REPORTED, ASSUMING IT'S AN ERROR AND RUNNING TESTS ANYWAY"
+ return
+ fi
local no_presubmit_pattern="${NO_PRESUBMIT_FILES[*]}"
local no_presubmit_pattern="\(${no_presubmit_pattern// /\\|}\)$"
echo -e "Changed files in commit ${PULL_PULL_SHA}:\n${changes}"
diff --git a/vendor/github.com/knative/test-infra/test/presubmit-tests.sh b/vendor/github.com/knative/test-infra/test/presubmit-tests.sh
new file mode 100755
index 00000000..295a23c7
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/test/presubmit-tests.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script runs the presubmit tests; it is started by prow for each PR.
+# For convenience, it can also be executed manually.
+# Running the script without parameters, or with the --all-tests
+# flag, causes all tests to be executed, in the right order.
+# Use the flags --build-tests, --unit-tests and --integration-tests
+# to run a specific set of tests.
+
+source $(dirname $0)/../scripts/presubmit-tests.sh
+
+function build_tests() {
+ header "Running build tests"
+ local failed=0
+ make -C ci/prow test || failed=1
+ make -C ci/testgrid test || failed=1
+ for script in scripts/*.sh; do
+ echo "Checking integrity of ${script}"
+ bash -c "source ${script}" || failed=1
+ done
+ return ${failed}
+}
+
+function unit_tests() {
+ header "TODO(#7): Running unit tests"
+}
+
+function integration_tests() {
+ header "TODO(#8): Running integration tests"
+}
+
+main $@
diff --git a/vendor/github.com/knative/test-infra/tools/README.md b/vendor/github.com/knative/test-infra/tools/README.md
new file mode 100644
index 00000000..d4cf2a27
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/README.md
@@ -0,0 +1,3 @@
+# Test Infrastructure tools
+
+This directory contains tools used by our Prow jobs.
diff --git a/vendor/github.com/knative/test-infra/tools/apicoverage/README.md b/vendor/github.com/knative/test-infra/tools/apicoverage/README.md
new file mode 100644
index 00000000..01ddf855
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/apicoverage/README.md
@@ -0,0 +1,14 @@
+# API Coverage Tool
+This tool is designed to show the field level coverage exercised by the conformance tests.
+
+## Read from GCS
+This tool reads the logs from the latest continous build of knative/serving. The logs have the information of which CRD objects are being created and which fields are being set for the testing.
+It uses the service account passed in or by default will use the GOOGLE_APPLICATION_CREDENTIALS variable to get the logs.
+
+## Creating Output
+This tool creates an output xml in the prow artifacts directory. The prow artifacts directory is passed in or by default will use `./artifacts` directory.
+
+This output xml will be read by testgrid and displayed on the [dashboard](https://testgrid.knative.dev/knative-serving#api-coverage).
+
+## Prow Job
+There is a daily prow job that triggers this tool that is run at 01:05 AM PST. This tool will then generate the output xml which is then displayed in the testgrid dashboard.
diff --git a/vendor/github.com/knative/test-infra/tools/apicoverage/apicoverage.go b/vendor/github.com/knative/test-infra/tools/apicoverage/apicoverage.go
new file mode 100644
index 00000000..c2e60fd6
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/apicoverage/apicoverage.go
@@ -0,0 +1,194 @@
+/*
+Copyright 2018 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// apicoverage.go parses the log file and outputs the api coverage numbers in a
+// testgrid expected output xml file
+
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+
+ "github.com/knative/serving/pkg/apis/serving/v1alpha1"
+)
+
+// ResourceObjects defines the resource objects in knative-serving
+type ResourceObjects struct {
+ Route *v1alpha1.Route
+ Configuration *v1alpha1.Configuration
+ Service *v1alpha1.Service
+}
+
+// OverallAPICoverage defines the overall api coverage for knative serving
+type OverallAPICoverage struct {
+ RouteAPICovered map[string]int
+ RouteAPINotCovered map[string]int
+ ConfigurationAPICovered map[string]int
+ ConfigurationAPINotCovered map[string]int
+ ServiceAPICovered map[string]int
+ ServiceAPINotCovered map[string]int
+}
+
+type apiObjectName string
+
+const (
+ apiObjectRoute apiObjectName = "route"
+ apiObjectConfiguration = "configuration"
+ apiObjectService = "service"
+)
+
+// check if the object value is nil or empty.
+// Uses https://golang.org/pkg/reflect/#Kind to get the variable type
+func isNil(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ }
+ return false
+}
+
+func isStruct(v reflect.Value) bool {
+ return v.Kind() == reflect.Struct
+}
+
+// Parse the struct and returns a map of
+func parseStruct(v reflect.Value) map[string]reflect.Value {
+ f := make(map[string]reflect.Value)
+
+ for i := 0; i < v.NumField(); i++ {
+ // Include only public vars. https://golang.org/pkg/reflect/#StructField.
+ if len(v.Type().Field(i).PkgPath) == 0 {
+ f[v.Type().Field(i).Name] = v.Field(i)
+ }
+ }
+
+ return f
+}
+
+func incrementCoverageValues(name string, covered map[string]int) {
+ if i, ok := covered[name]; ok {
+ covered[name] = i + 1
+ } else {
+ covered[name] = 1
+ }
+}
+
+func handleCovered(name string, coverage *OverallAPICoverage) {
+ if strings.HasPrefix(name, "route") {
+ incrementCoverageValues(name, coverage.RouteAPICovered)
+ } else if strings.HasPrefix(name, "configuration") {
+ incrementCoverageValues(name, coverage.ConfigurationAPICovered)
+ } else if strings.HasPrefix(name, "service") {
+ incrementCoverageValues(name, coverage.ServiceAPICovered)
+ }
+}
+
+func handleNotCovered(name string, coverage *OverallAPICoverage) {
+ if strings.HasPrefix(name, "route") {
+ coverage.RouteAPINotCovered[name] = 0
+ } else if strings.HasPrefix(name, "configuration") {
+ coverage.ConfigurationAPINotCovered[name] = 0
+ } else if strings.HasPrefix(name, "service") {
+ coverage.ServiceAPINotCovered[name] = 0
+ }
+}
+
+func getCoverage(value reflect.Value, name string, coverage *OverallAPICoverage) {
+ // Parse all the fields in the struct
+ for key, v := range parseStruct(value) {
+ name := name + "." + key
+ if isStruct(v) {
+ getCoverage(v, name, coverage)
+ } else {
+ // check if it is empty/nil
+ if isNil(v) {
+ handleNotCovered(name, coverage)
+ } else {
+ handleCovered(name, coverage)
+ }
+ }
+ }
+}
+
+func calculateCoverage(covLogs []string, coverage *OverallAPICoverage) {
+ if len(covLogs) == 0 {
+ return
+ }
+
+ for _, f := range covLogs {
+ var obj ResourceObjects
+ if err := json.Unmarshal([]byte(f), &obj); err != nil {
+ log.Fatalf("Cannot read resource object: %v", err)
+ } else {
+ if obj.Route != nil {
+ getCoverage(reflect.ValueOf(obj.Route).Elem(), "route", coverage)
+ } else if obj.Configuration != nil {
+ getCoverage(reflect.ValueOf(obj.Configuration).Elem(), "configuration", coverage)
+ } else if obj.Service != nil {
+ getCoverage(reflect.ValueOf(obj.Service).Elem(), "service", coverage)
+ }
+ }
+ }
+}
+
+func initCoverage() *OverallAPICoverage {
+ coverage := OverallAPICoverage{}
+ coverage.RouteAPICovered = make(map[string]int)
+ coverage.RouteAPINotCovered = make(map[string]int)
+ coverage.ConfigurationAPICovered = make(map[string]int)
+ coverage.ConfigurationAPINotCovered = make(map[string]int)
+ coverage.ServiceAPICovered = make(map[string]int)
+ coverage.ServiceAPINotCovered = make(map[string]int)
+
+ return &coverage
+}
+
+func main() {
+
+ artifactsDir := flag.String("artifacts-dir", "./artifacts", "Directory to store the generated XML file")
+ serviceAccount := flag.String("service-account", os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"), "JSON key file for service account to use")
+ flag.Parse()
+
+ // Read the latest-build.txt file to get the latest build number
+ ctx := context.Background()
+ contents, err := readGcsFile(ctx, logDir+sourceDir+"/latest-build.txt", *serviceAccount)
+ if err != nil {
+ log.Fatalf("Cannot get latest build number. %s: %v", contents, err)
+ }
+ latestBuild, err := strconv.Atoi(string(contents))
+ if err != nil {
+ log.Fatalf("Cannot convert %s to string to get latest build %v", string(contents), err)
+ }
+
+ // Calculate coverage
+ coverage := initCoverage()
+ calculateCoverage(parseLog(ctx, fmt.Sprintf("%s/%d", sourceDir, latestBuild), false, coverage), coverage)
+
+ // Write the testgrid xml to artifacts
+ createTestgridXML(coverage, *artifactsDir)
+}
diff --git a/vendor/github.com/knative/test-infra/tools/apicoverage/gcs.go b/vendor/github.com/knative/test-infra/tools/apicoverage/gcs.go
new file mode 100644
index 00000000..3a6b8a32
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/apicoverage/gcs.go
@@ -0,0 +1,101 @@
+/*
+Copyright 2018 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// gcs.go defines functions on gcs
+
+package main
+
+import (
+ "bufio"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "strings"
+
+ "cloud.google.com/go/storage"
+ "google.golang.org/api/option"
+)
+
+const (
+ logDir = "logs/"
+ sourceDir = "ci-knative-serving-continuous"
+ bucketName = "knative-prow"
+)
+
+var client *storage.Client
+
+func createStorageClient(ctx context.Context, sa string) error {
+ var err error
+ client, err = storage.NewClient(ctx, option.WithCredentialsFile(sa))
+ return err
+}
+
+func createStorageObject(filename string) *storage.ObjectHandle {
+ return client.Bucket(bucketName).Object(filename)
+}
+
+func readGcsFile(ctx context.Context, filename string, sa string) ([]byte, error) {
+ // Create a new GCS client
+ if err := createStorageClient(ctx, sa); err != nil {
+ log.Fatalf("Failed to create GCS client: %v", err)
+ }
+ o := createStorageObject(filename)
+ if _, err := o.Attrs(ctx); err != nil {
+ return []byte(fmt.Sprintf("Cannot get attributes of '%s'", filename)), err
+ }
+ f, err := o.NewReader(ctx)
+ if err != nil {
+ return []byte(fmt.Sprintf("Cannot open '%s'", filename)), err
+ }
+ defer f.Close()
+ contents, err := ioutil.ReadAll(f)
+ if err != nil {
+ return []byte(fmt.Sprintf("Cannot read '%s'", filename)), err
+ }
+ return contents, nil
+}
+
+func parseLog(ctx context.Context, dir string, isLocal bool, coverage *OverallAPICoverage) []string {
+ var covLogs []string
+
+ buildDir := logDir + dir
+ log.Printf("Parsing '%s'", buildDir)
+ logFile := buildDir + "/build-log.txt"
+ log.Printf("Parsing '%s'", logFile)
+ o := createStorageObject(logFile)
+ if _, err := o.Attrs(ctx); err != nil {
+ log.Printf("Cannot get attributes of '%s', assuming not ready yet: %v", logFile, err)
+ return nil
+ }
+ f, err := o.NewReader(ctx)
+ if err != nil {
+ log.Fatalf("Error opening '%s': %v", logFile, err)
+ }
+ defer f.Close()
+
+ scanner := bufio.NewScanner(f)
+
+ for scanner.Scan() {
+ fields := strings.Fields(scanner.Text())
+
+ // I0727 16:23:30.055] info TestRouteCreation test/configuration.go:34 resource {: }"}
+ if len(fields) == 7 && fields[2] == "info" && fields[5] == "resource" {
+ covLogs = append(covLogs, strings.Join(fields[6:], " "))
+ }
+ }
+ return covLogs
+}
diff --git a/vendor/github.com/knative/test-infra/tools/apicoverage/testgrid.go b/vendor/github.com/knative/test-infra/tools/apicoverage/testgrid.go
new file mode 100644
index 00000000..06901e6e
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/apicoverage/testgrid.go
@@ -0,0 +1,115 @@
+/*
+Copyright 2018 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// testgrid.go provides methods to perform action on testgrid.
+
+package main
+
+import (
+ "encoding/xml"
+ "log"
+ "os"
+)
+
+const (
+ apiCoverage = "api_coverage"
+ overallRoute = "OverallRoute"
+ overallConfig = "OverallConfiguration"
+ overallService = "OverallService"
+)
+
+// TestProperty defines a property of the test
+type TestProperty struct {
+ Name string `xml:"name,attr"`
+ Value float32 `xml:"value,attr"`
+}
+
+// TestProperties is an array of test properties
+type TestProperties struct {
+ Property []TestProperty `xml:"property"`
+}
+
+// TestCase defines a test case that was executed
+type TestCase struct {
+ ClassName string `xml:"class_name,attr"`
+ Name string `xml:"name,attr"`
+ Time int `xml:"time,attr"`
+ Properties TestProperties `xml:"properties"`
+ Fail bool `xml:"failure,omitempty"`
+}
+
+// TestSuite defines the set of relevant test cases
+type TestSuite struct {
+ XMLName xml.Name `xml:"testsuite"`
+ TestCases []TestCase `xml:"testcase"`
+}
+
+func createTestProperty(value float32) TestProperty {
+ return TestProperty{Name: apiCoverage, Value: value}
+}
+
+func createTestCase(name string, properties []TestProperty, fail bool) TestCase {
+ tc := TestCase{ClassName: apiCoverage, Name: name, Properties: TestProperties{Property: properties}, Time: 0}
+ if fail {
+ tc.Fail = true
+ }
+ return tc
+}
+
+func createTestSuite(cases []TestCase) TestSuite {
+ return TestSuite{TestCases: cases}
+}
+
+func createCases(tcName string, covered map[string]int, notCovered map[string]int) []TestCase {
+ var tc []TestCase
+
+ var percentCovered = float32(100 * len(covered) / (len(covered) + len(notCovered)))
+ tp := []TestProperty{createTestProperty(percentCovered)}
+ tc = append(tc, createTestCase(tcName, tp, false))
+
+ for key, value := range covered {
+ tp := []TestProperty{createTestProperty(float32(value))}
+ tc = append(tc, createTestCase(tcName+"/"+key, tp, false))
+ }
+
+ for key, value := range notCovered {
+ tp := []TestProperty{createTestProperty(float32(value))}
+ tc = append(tc, createTestCase(tcName+"/"+key, tp, true))
+ }
+ return tc
+}
+
+func createTestgridXML(coverage *OverallAPICoverage, artifactsDir string) {
+ tc := createCases(overallRoute, coverage.RouteAPICovered, coverage.RouteAPINotCovered)
+ tc = append(tc, createCases(overallConfig, coverage.ConfigurationAPICovered, coverage.ConfigurationAPINotCovered)...)
+ tc = append(tc, createCases(overallService, coverage.ServiceAPICovered, coverage.ServiceAPINotCovered)...)
+ ts := createTestSuite(tc)
+
+ op, err := xml.MarshalIndent(ts, "", " ")
+ if err != nil {
+ log.Fatalf("Error creating xml: %v", err)
+ }
+
+ outputFile := artifactsDir + "/junit_bazel.xml"
+ f, err := os.Create(outputFile)
+ if err != nil {
+ log.Fatalf("Cannot create '%s': %v", outputFile, err)
+ }
+ defer f.Close()
+ if _, err := f.WriteString(string(op) + "\n"); err != nil {
+ log.Fatalf("Cannot write to '%s': %v", f.Name(), err)
+ }
+}
diff --git a/vendor/github.com/knative/test-infra/tools/githubhelper/Makefile b/vendor/github.com/knative/test-infra/tools/githubhelper/Makefile
new file mode 100644
index 00000000..c8fef33a
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/githubhelper/Makefile
@@ -0,0 +1,17 @@
+# Copyright 2018 The Knative Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+all:
+ go get -u github.com/google/go-github/github
+ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
diff --git a/vendor/github.com/knative/test-infra/tools/githubhelper/README.md b/vendor/github.com/knative/test-infra/tools/githubhelper/README.md
new file mode 100644
index 00000000..5975a235
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/githubhelper/README.md
@@ -0,0 +1,10 @@
+# GitHub Helper Tool
+
+This tool is designed to interact with GitHub, providing useful data for a Prow job. Actions performed and the output are governed by the flags used.
+
+Currently the tool makes unauthenticated requests to GitHub API.
+
+## Flags
+
+* `-list-changed-files` will list the files that are touched by the current PR in a Prow job.
+* `-verbose` will dump extra info on output when executing the comments; it is intended for debugging.
diff --git a/vendor/github.com/knative/test-infra/tools/githubhelper/githubhelper.go b/vendor/github.com/knative/test-infra/tools/githubhelper/githubhelper.go
new file mode 100644
index 00000000..d45fad47
--- /dev/null
+++ b/vendor/github.com/knative/test-infra/tools/githubhelper/githubhelper.go
@@ -0,0 +1,85 @@
+/*
+Copyright 2018 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// githubhelper.go interacts with GitHub, providing useful data for a Prow job.
+
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "strconv"
+
+ "github.com/google/go-github/github"
+)
+
+var (
+ // Info about the current PR
+ repoOwner = os.Getenv("REPO_OWNER")
+ repoName = os.Getenv("REPO_NAME")
+ pullNumber = atoi(os.Getenv("PULL_NUMBER"), "pull number")
+
+ // Shared useful variables
+ ctx = context.Background()
+ onePageList = &github.ListOptions{Page: 1}
+ verbose = false
+ anonymousGitHubClient *github.Client
+)
+
+// atoi is a convenience function to convert a string to integer, failing in case of error.
+func atoi(str, valueName string) int {
+ value, err := strconv.Atoi(str)
+ if err != nil {
+ log.Fatalf("Unexpected non number '%s' for %s: %v", str, valueName, err)
+ }
+ return value
+}
+
+// infof if a convenience wrapper around log.Infof, and does nothing unless --verbose is passed.
+func infof(template string, args ...interface{}) {
+ if verbose {
+ log.Printf(template, args...)
+ }
+}
+
+// listChangedFiles simply lists the files changed by the current PR.
+func listChangedFiles() {
+ infof("Listing changed files for PR %d in repository %s/%s", pullNumber, repoOwner, repoName)
+ files, _, err := anonymousGitHubClient.PullRequests.ListFiles(ctx, repoOwner, repoName, pullNumber, onePageList)
+ if err != nil {
+ log.Fatalf("Error listing files: %v", err)
+ }
+ for _, file := range files {
+ fmt.Println(*file.Filename)
+ }
+}
+
+func main() {
+ listChangedFilesFlag := flag.Bool("list-changed-files", false, "List the files changed by the current pull request")
+ verboseFlag := flag.Bool("verbose", false, "Whether to dump extra info on output or not; intended for debugging")
+ flag.Parse()
+
+ verbose = *verboseFlag
+ anonymousGitHubClient = github.NewClient(nil)
+
+ if *listChangedFilesFlag {
+ listChangedFiles()
+ }
+}
+
diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE b/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE
new file mode 100644
index 00000000..8dada3ed
--- /dev/null
+++ b/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE b/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE
new file mode 100644
index 00000000..5d8cb5b7
--- /dev/null
+++ b/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE
@@ -0,0 +1 @@
+Copyright 2012 Matt T. Proud (matt.proud@gmail.com)
diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go
new file mode 100644
index 00000000..258c0636
--- /dev/null
+++ b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go
@@ -0,0 +1,75 @@
+// Copyright 2013 Matt T. Proud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pbutil
+
+import (
+ "encoding/binary"
+ "errors"
+ "io"
+
+ "github.com/golang/protobuf/proto"
+)
+
+var errInvalidVarint = errors.New("invalid varint32 encountered")
+
+// ReadDelimited decodes a message from the provided length-delimited stream,
+// where the length is encoded as 32-bit varint prefix to the message body.
+// It returns the total number of bytes read and any applicable error. This is
+// roughly equivalent to the companion Java API's
+// MessageLite#parseDelimitedFrom. As per the reader contract, this function
+// calls r.Read repeatedly as required until exactly one message including its
+// prefix is read and decoded (or an error has occurred). The function never
+// reads more bytes from the stream than required. The function never returns
+// an error if a message has been read and decoded correctly, even if the end
+// of the stream has been reached in doing so. In that case, any subsequent
+// calls return (0, io.EOF).
+func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) {
+ // Per AbstractParser#parsePartialDelimitedFrom with
+ // CodedInputStream#readRawVarint32.
+ var headerBuf [binary.MaxVarintLen32]byte
+ var bytesRead, varIntBytes int
+ var messageLength uint64
+ for varIntBytes == 0 { // i.e. no varint has been decoded yet.
+ if bytesRead >= len(headerBuf) {
+ return bytesRead, errInvalidVarint
+ }
+ // We have to read byte by byte here to avoid reading more bytes
+ // than required. Each read byte is appended to what we have
+ // read before.
+ newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1])
+ if newBytesRead == 0 {
+ if err != nil {
+ return bytesRead, err
+ }
+ // A Reader should not return (0, nil), but if it does,
+ // it should be treated as no-op (according to the
+ // Reader contract). So let's go on...
+ continue
+ }
+ bytesRead += newBytesRead
+ // Now present everything read so far to the varint decoder and
+ // see if a varint can be decoded already.
+ messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead])
+ }
+
+ messageBuf := make([]byte, messageLength)
+ newBytesRead, err := io.ReadFull(r, messageBuf)
+ bytesRead += newBytesRead
+ if err != nil {
+ return bytesRead, err
+ }
+
+ return bytesRead, proto.Unmarshal(messageBuf, m)
+}
diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go
new file mode 100644
index 00000000..c318385c
--- /dev/null
+++ b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2013 Matt T. Proud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package pbutil provides record length-delimited Protocol Buffer streaming.
+package pbutil
diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go
new file mode 100644
index 00000000..8fb59ad2
--- /dev/null
+++ b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go
@@ -0,0 +1,46 @@
+// Copyright 2013 Matt T. Proud
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package pbutil
+
+import (
+ "encoding/binary"
+ "io"
+
+ "github.com/golang/protobuf/proto"
+)
+
+// WriteDelimited encodes and dumps a message to the provided writer prefixed
+// with a 32-bit varint indicating the length of the encoded message, producing
+// a length-delimited record stream, which can be used to chain together
+// encoded messages of the same type together in a file. It returns the total
+// number of bytes written and any applicable error. This is roughly
+// equivalent to the companion Java API's MessageLite#writeDelimitedTo.
+func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) {
+ buffer, err := proto.Marshal(m)
+ if err != nil {
+ return 0, err
+ }
+
+ var buf [binary.MaxVarintLen32]byte
+ encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer)))
+
+ sync, err := w.Write(buf[:encodedLength])
+ if err != nil {
+ return sync, err
+ }
+
+ n, err = w.Write(buffer)
+ return n + sync, err
+}
diff --git a/vendor/github.com/prometheus/client_golang/AUTHORS.md b/vendor/github.com/prometheus/client_golang/AUTHORS.md
new file mode 100644
index 00000000..c5275d5a
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/AUTHORS.md
@@ -0,0 +1,18 @@
+The Prometheus project was started by Matt T. Proud (emeritus) and
+Julius Volz in 2012.
+
+Maintainers of this repository:
+
+* Björn Rabenstein
+
+The following individuals have contributed code to this repository
+(listed in alphabetical order):
+
+* Bernerd Schaefer
+* Björn Rabenstein
+* Daniel Bornkessel
+* Jeff Younker
+* Julius Volz
+* Matt T. Proud
+* Tobias Schmidt
+
diff --git a/vendor/github.com/prometheus/client_golang/LICENSE b/vendor/github.com/prometheus/client_golang/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/prometheus/client_golang/NOTICE b/vendor/github.com/prometheus/client_golang/NOTICE
new file mode 100644
index 00000000..dd878a30
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/NOTICE
@@ -0,0 +1,23 @@
+Prometheus instrumentation library for Go applications
+Copyright 2012-2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
+
+
+The following components are included in this product:
+
+perks - a fork of https://github.com/bmizerany/perks
+https://github.com/beorn7/perks
+Copyright 2013-2015 Blake Mizerany, Björn Rabenstein
+See https://github.com/beorn7/perks/blob/master/README.md for license details.
+
+Go support for Protocol Buffers - Google's data interchange format
+http://github.com/golang/protobuf/
+Copyright 2010 The Go Authors
+See source code for license details.
+
+Support for streaming Protocol Buffer messages for the Go language (golang).
+https://github.com/matttproud/golang_protobuf_extensions
+Copyright 2013 Matt T. Proud
+Licensed under the Apache License, Version 2.0
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collector.go b/vendor/github.com/prometheus/client_golang/prometheus/collector.go
new file mode 100644
index 00000000..623d3d83
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/collector.go
@@ -0,0 +1,75 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+// Collector is the interface implemented by anything that can be used by
+// Prometheus to collect metrics. A Collector has to be registered for
+// collection. See Registerer.Register.
+//
+// The stock metrics provided by this package (Gauge, Counter, Summary,
+// Histogram, Untyped) are also Collectors (which only ever collect one metric,
+// namely itself). An implementer of Collector may, however, collect multiple
+// metrics in a coordinated fashion and/or create metrics on the fly. Examples
+// for collectors already implemented in this library are the metric vectors
+// (i.e. collection of multiple instances of the same Metric but with different
+// label values) like GaugeVec or SummaryVec, and the ExpvarCollector.
+type Collector interface {
+ // Describe sends the super-set of all possible descriptors of metrics
+ // collected by this Collector to the provided channel and returns once
+ // the last descriptor has been sent. The sent descriptors fulfill the
+ // consistency and uniqueness requirements described in the Desc
+ // documentation. (It is valid if one and the same Collector sends
+ // duplicate descriptors. Those duplicates are simply ignored. However,
+ // two different Collectors must not send duplicate descriptors.) This
+ // method idempotently sends the same descriptors throughout the
+ // lifetime of the Collector. If a Collector encounters an error while
+ // executing this method, it must send an invalid descriptor (created
+ // with NewInvalidDesc) to signal the error to the registry.
+ Describe(chan<- *Desc)
+ // Collect is called by the Prometheus registry when collecting
+ // metrics. The implementation sends each collected metric via the
+ // provided channel and returns once the last metric has been sent. The
+ // descriptor of each sent metric is one of those returned by
+ // Describe. Returned metrics that share the same descriptor must differ
+ // in their variable label values. This method may be called
+ // concurrently and must therefore be implemented in a concurrency safe
+ // way. Blocking occurs at the expense of total performance of rendering
+ // all registered metrics. Ideally, Collector implementations support
+ // concurrent readers.
+ Collect(chan<- Metric)
+}
+
+// selfCollector implements Collector for a single Metric so that the Metric
+// collects itself. Add it as an anonymous field to a struct that implements
+// Metric, and call init with the Metric itself as an argument.
+type selfCollector struct {
+ self Metric
+}
+
+// init provides the selfCollector with a reference to the metric it is supposed
+// to collect. It is usually called within the factory function to create a
+// metric. See example.
+func (c *selfCollector) init(self Metric) {
+ c.self = self
+}
+
+// Describe implements Collector.
+func (c *selfCollector) Describe(ch chan<- *Desc) {
+ ch <- c.self.Desc()
+}
+
+// Collect implements Collector.
+func (c *selfCollector) Collect(ch chan<- Metric) {
+ ch <- c.self
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go
new file mode 100644
index 00000000..ee37949a
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/counter.go
@@ -0,0 +1,172 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "errors"
+)
+
+// Counter is a Metric that represents a single numerical value that only ever
+// goes up. That implies that it cannot be used to count items whose number can
+// also go down, e.g. the number of currently running goroutines. Those
+// "counters" are represented by Gauges.
+//
+// A Counter is typically used to count requests served, tasks completed, errors
+// occurred, etc.
+//
+// To create Counter instances, use NewCounter.
+type Counter interface {
+ Metric
+ Collector
+
+ // Set is used to set the Counter to an arbitrary value. It is only used
+ // if you have to transfer a value from an external counter into this
+ // Prometheus metric. Do not use it for regular handling of a
+ // Prometheus counter (as it can be used to break the contract of
+ // monotonically increasing values).
+ //
+ // Deprecated: Use NewConstMetric to create a counter for an external
+ // value. A Counter should never be set.
+ Set(float64)
+ // Inc increments the counter by 1.
+ Inc()
+ // Add adds the given value to the counter. It panics if the value is <
+ // 0.
+ Add(float64)
+}
+
+// CounterOpts is an alias for Opts. See there for doc comments.
+type CounterOpts Opts
+
+// NewCounter creates a new Counter based on the provided CounterOpts.
+func NewCounter(opts CounterOpts) Counter {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ )
+ result := &counter{value: value{desc: desc, valType: CounterValue, labelPairs: desc.constLabelPairs}}
+ result.init(result) // Init self-collection.
+ return result
+}
+
+type counter struct {
+ value
+}
+
+func (c *counter) Add(v float64) {
+ if v < 0 {
+ panic(errors.New("counter cannot decrease in value"))
+ }
+ c.value.Add(v)
+}
+
+// CounterVec is a Collector that bundles a set of Counters that all share the
+// same Desc, but have different values for their variable labels. This is used
+// if you want to count the same thing partitioned by various dimensions
+// (e.g. number of HTTP requests, partitioned by response code and
+// method). Create instances with NewCounterVec.
+//
+// CounterVec embeds MetricVec. See there for a full list of methods with
+// detailed documentation.
+type CounterVec struct {
+ *MetricVec
+}
+
+// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
+// partitioned by the given label names. At least one label name must be
+// provided.
+func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &CounterVec{
+ MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ result := &counter{value: value{
+ desc: desc,
+ valType: CounterValue,
+ labelPairs: makeLabelPairs(desc, lvs),
+ }}
+ result.init(result) // Init self-collection.
+ return result
+ }),
+ }
+}
+
+// GetMetricWithLabelValues replaces the method of the same name in
+// MetricVec. The difference is that this method returns a Counter and not a
+// Metric so that no type conversion is required.
+func (m *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
+ metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Counter), err
+ }
+ return nil, err
+}
+
+// GetMetricWith replaces the method of the same name in MetricVec. The
+// difference is that this method returns a Counter and not a Metric so that no
+// type conversion is required.
+func (m *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
+ metric, err := m.MetricVec.GetMetricWith(labels)
+ if metric != nil {
+ return metric.(Counter), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. By not returning an
+// error, WithLabelValues allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Add(42)
+func (m *CounterVec) WithLabelValues(lvs ...string) Counter {
+ return m.MetricVec.WithLabelValues(lvs...).(Counter)
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. By not returning an error, With allows shortcuts like
+// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
+func (m *CounterVec) With(labels Labels) Counter {
+ return m.MetricVec.With(labels).(Counter)
+}
+
+// CounterFunc is a Counter whose value is determined at collect time by calling a
+// provided function.
+//
+// To create CounterFunc instances, use NewCounterFunc.
+type CounterFunc interface {
+ Metric
+ Collector
+}
+
+// NewCounterFunc creates a new CounterFunc based on the provided
+// CounterOpts. The value reported is determined by calling the given function
+// from within the Write method. Take into account that metric collection may
+// happen concurrently. If that results in concurrent calls to Write, like in
+// the case where a CounterFunc is directly registered with Prometheus, the
+// provided function must be concurrency-safe. The function should also honor
+// the contract for a Counter (values only go up, not down), but compliance will
+// not be checked.
+func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc {
+ return newValueFunc(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), CounterValue, function)
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go
new file mode 100644
index 00000000..77f4b30e
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/desc.go
@@ -0,0 +1,205 @@
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "sort"
+ "strings"
+
+ "github.com/golang/protobuf/proto"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+var (
+ metricNameRE = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_:]*$`)
+ labelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
+)
+
+// reservedLabelPrefix is a prefix which is not legal in user-supplied
+// label names.
+const reservedLabelPrefix = "__"
+
+// Labels represents a collection of label name -> value mappings. This type is
+// commonly used with the With(Labels) and GetMetricWith(Labels) methods of
+// metric vector Collectors, e.g.:
+// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
+//
+// The other use-case is the specification of constant label pairs in Opts or to
+// create a Desc.
+type Labels map[string]string
+
+// Desc is the descriptor used by every Prometheus Metric. It is essentially
+// the immutable meta-data of a Metric. The normal Metric implementations
+// included in this package manage their Desc under the hood. Users only have to
+// deal with Desc if they use advanced features like the ExpvarCollector or
+// custom Collectors and Metrics.
+//
+// Descriptors registered with the same registry have to fulfill certain
+// consistency and uniqueness criteria if they share the same fully-qualified
+// name: They must have the same help string and the same label names (aka label
+// dimensions) in each, constLabels and variableLabels, but they must differ in
+// the values of the constLabels.
+//
+// Descriptors that share the same fully-qualified names and the same label
+// values of their constLabels are considered equal.
+//
+// Use NewDesc to create new Desc instances.
+type Desc struct {
+ // fqName has been built from Namespace, Subsystem, and Name.
+ fqName string
+ // help provides some helpful information about this metric.
+ help string
+ // constLabelPairs contains precalculated DTO label pairs based on
+ // the constant labels.
+ constLabelPairs []*dto.LabelPair
+ // VariableLabels contains names of labels for which the metric
+ // maintains variable values.
+ variableLabels []string
+ // id is a hash of the values of the ConstLabels and fqName. This
+ // must be unique among all registered descriptors and can therefore be
+ // used as an identifier of the descriptor.
+ id uint64
+ // dimHash is a hash of the label names (preset and variable) and the
+ // Help string. Each Desc with the same fqName must have the same
+ // dimHash.
+ dimHash uint64
+ // err is an error that occured during construction. It is reported on
+ // registration time.
+ err error
+}
+
+// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
+// and will be reported on registration time. variableLabels and constLabels can
+// be nil if no such labels should be set. fqName and help must not be empty.
+//
+// variableLabels only contain the label names. Their label values are variable
+// and therefore not part of the Desc. (They are managed within the Metric.)
+//
+// For constLabels, the label values are constant. Therefore, they are fully
+// specified in the Desc. See the Opts documentation for the implications of
+// constant labels.
+func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc {
+ d := &Desc{
+ fqName: fqName,
+ help: help,
+ variableLabels: variableLabels,
+ }
+ if help == "" {
+ d.err = errors.New("empty help string")
+ return d
+ }
+ if !metricNameRE.MatchString(fqName) {
+ d.err = fmt.Errorf("%q is not a valid metric name", fqName)
+ return d
+ }
+ // labelValues contains the label values of const labels (in order of
+ // their sorted label names) plus the fqName (at position 0).
+ labelValues := make([]string, 1, len(constLabels)+1)
+ labelValues[0] = fqName
+ labelNames := make([]string, 0, len(constLabels)+len(variableLabels))
+ labelNameSet := map[string]struct{}{}
+ // First add only the const label names and sort them...
+ for labelName := range constLabels {
+ if !checkLabelName(labelName) {
+ d.err = fmt.Errorf("%q is not a valid label name", labelName)
+ return d
+ }
+ labelNames = append(labelNames, labelName)
+ labelNameSet[labelName] = struct{}{}
+ }
+ sort.Strings(labelNames)
+ // ... so that we can now add const label values in the order of their names.
+ for _, labelName := range labelNames {
+ labelValues = append(labelValues, constLabels[labelName])
+ }
+ // Now add the variable label names, but prefix them with something that
+ // cannot be in a regular label name. That prevents matching the label
+ // dimension with a different mix between preset and variable labels.
+ for _, labelName := range variableLabels {
+ if !checkLabelName(labelName) {
+ d.err = fmt.Errorf("%q is not a valid label name", labelName)
+ return d
+ }
+ labelNames = append(labelNames, "$"+labelName)
+ labelNameSet[labelName] = struct{}{}
+ }
+ if len(labelNames) != len(labelNameSet) {
+ d.err = errors.New("duplicate label names")
+ return d
+ }
+ vh := hashNew()
+ for _, val := range labelValues {
+ vh = hashAdd(vh, val)
+ vh = hashAddByte(vh, separatorByte)
+ }
+ d.id = vh
+ // Sort labelNames so that order doesn't matter for the hash.
+ sort.Strings(labelNames)
+ // Now hash together (in this order) the help string and the sorted
+ // label names.
+ lh := hashNew()
+ lh = hashAdd(lh, help)
+ lh = hashAddByte(lh, separatorByte)
+ for _, labelName := range labelNames {
+ lh = hashAdd(lh, labelName)
+ lh = hashAddByte(lh, separatorByte)
+ }
+ d.dimHash = lh
+
+ d.constLabelPairs = make([]*dto.LabelPair, 0, len(constLabels))
+ for n, v := range constLabels {
+ d.constLabelPairs = append(d.constLabelPairs, &dto.LabelPair{
+ Name: proto.String(n),
+ Value: proto.String(v),
+ })
+ }
+ sort.Sort(LabelPairSorter(d.constLabelPairs))
+ return d
+}
+
+// NewInvalidDesc returns an invalid descriptor, i.e. a descriptor with the
+// provided error set. If a collector returning such a descriptor is registered,
+// registration will fail with the provided error. NewInvalidDesc can be used by
+// a Collector to signal inability to describe itself.
+func NewInvalidDesc(err error) *Desc {
+ return &Desc{
+ err: err,
+ }
+}
+
+func (d *Desc) String() string {
+ lpStrings := make([]string, 0, len(d.constLabelPairs))
+ for _, lp := range d.constLabelPairs {
+ lpStrings = append(
+ lpStrings,
+ fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()),
+ )
+ }
+ return fmt.Sprintf(
+ "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: %v}",
+ d.fqName,
+ d.help,
+ strings.Join(lpStrings, ","),
+ d.variableLabels,
+ )
+}
+
+func checkLabelName(l string) bool {
+ return labelNameRE.MatchString(l) &&
+ !strings.HasPrefix(l, reservedLabelPrefix)
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/doc.go b/vendor/github.com/prometheus/client_golang/prometheus/doc.go
new file mode 100644
index 00000000..b15a2d3b
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/doc.go
@@ -0,0 +1,181 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package prometheus provides metrics primitives to instrument code for
+// monitoring. It also offers a registry for metrics. Sub-packages allow to
+// expose the registered metrics via HTTP (package promhttp) or push them to a
+// Pushgateway (package push).
+//
+// All exported functions and methods are safe to be used concurrently unless
+//specified otherwise.
+//
+// A Basic Example
+//
+// As a starting point, a very basic usage example:
+//
+// package main
+//
+// import (
+// "net/http"
+//
+// "github.com/prometheus/client_golang/prometheus"
+// "github.com/prometheus/client_golang/prometheus/promhttp"
+// )
+//
+// var (
+// cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{
+// Name: "cpu_temperature_celsius",
+// Help: "Current temperature of the CPU.",
+// })
+// hdFailures = prometheus.NewCounterVec(
+// prometheus.CounterOpts{
+// Name: "hd_errors_total",
+// Help: "Number of hard-disk errors.",
+// },
+// []string{"device"},
+// )
+// )
+//
+// func init() {
+// // Metrics have to be registered to be exposed:
+// prometheus.MustRegister(cpuTemp)
+// prometheus.MustRegister(hdFailures)
+// }
+//
+// func main() {
+// cpuTemp.Set(65.3)
+// hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc()
+//
+// // The Handler function provides a default handler to expose metrics
+// // via an HTTP server. "/metrics" is the usual endpoint for that.
+// http.Handle("/metrics", promhttp.Handler())
+// http.ListenAndServe(":8080", nil)
+// }
+//
+//
+// This is a complete program that exports two metrics, a Gauge and a Counter,
+// the latter with a label attached to turn it into a (one-dimensional) vector.
+//
+// Metrics
+//
+// The number of exported identifiers in this package might appear a bit
+// overwhelming. Hovever, in addition to the basic plumbing shown in the example
+// above, you only need to understand the different metric types and their
+// vector versions for basic usage.
+//
+// Above, you have already touched the Counter and the Gauge. There are two more
+// advanced metric types: the Summary and Histogram. A more thorough description
+// of those four metric types can be found in the Prometheus docs:
+// https://prometheus.io/docs/concepts/metric_types/
+//
+// A fifth "type" of metric is Untyped. It behaves like a Gauge, but signals the
+// Prometheus server not to assume anything about its type.
+//
+// In addition to the fundamental metric types Gauge, Counter, Summary,
+// Histogram, and Untyped, a very important part of the Prometheus data model is
+// the partitioning of samples along dimensions called labels, which results in
+// metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec,
+// HistogramVec, and UntypedVec.
+//
+// While only the fundamental metric types implement the Metric interface, both
+// the metrics and their vector versions implement the Collector interface. A
+// Collector manages the collection of a number of Metrics, but for convenience,
+// a Metric can also “collect itself”. Note that Gauge, Counter, Summary,
+// Histogram, and Untyped are interfaces themselves while GaugeVec, CounterVec,
+// SummaryVec, HistogramVec, and UntypedVec are not.
+//
+// To create instances of Metrics and their vector versions, you need a suitable
+// …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts,
+// HistogramOpts, or UntypedOpts.
+//
+// Custom Collectors and constant Metrics
+//
+// While you could create your own implementations of Metric, most likely you
+// will only ever implement the Collector interface on your own. At a first
+// glance, a custom Collector seems handy to bundle Metrics for common
+// registration (with the prime example of the different metric vectors above,
+// which bundle all the metrics of the same name but with different labels).
+//
+// There is a more involved use case, too: If you already have metrics
+// available, created outside of the Prometheus context, you don't need the
+// interface of the various Metric types. You essentially want to mirror the
+// existing numbers into Prometheus Metrics during collection. An own
+// implementation of the Collector interface is perfect for that. You can create
+// Metric instances “on the fly” using NewConstMetric, NewConstHistogram, and
+// NewConstSummary (and their respective Must… versions). That will happen in
+// the Collect method. The Describe method has to return separate Desc
+// instances, representative of the “throw-away” metrics to be created
+// later. NewDesc comes in handy to create those Desc instances.
+//
+// The Collector example illustrates the use case. You can also look at the
+// source code of the processCollector (mirroring process metrics), the
+// goCollector (mirroring Go metrics), or the expvarCollector (mirroring expvar
+// metrics) as examples that are used in this package itself.
+//
+// If you just need to call a function to get a single float value to collect as
+// a metric, GaugeFunc, CounterFunc, or UntypedFunc might be interesting
+// shortcuts.
+//
+// Advanced Uses of the Registry
+//
+// While MustRegister is the by far most common way of registering a Collector,
+// sometimes you might want to handle the errors the registration might
+// cause. As suggested by the name, MustRegister panics if an error occurs. With
+// the Register function, the error is returned and can be handled.
+//
+// An error is returned if the registered Collector is incompatible or
+// inconsistent with already registered metrics. The registry aims for
+// consistency of the collected metrics according to the Prometheus data
+// model. Inconsistencies are ideally detected at registration time, not at
+// collect time. The former will usually be detected at start-up time of a
+// program, while the latter will only happen at scrape time, possibly not even
+// on the first scrape if the inconsistency only becomes relevant later. That is
+// the main reason why a Collector and a Metric have to describe themselves to
+// the registry.
+//
+// So far, everything we did operated on the so-called default registry, as it
+// can be found in the global DefaultRegistry variable. With NewRegistry, you
+// can create a custom registry, or you can even implement the Registerer or
+// Gatherer interfaces yourself. The methods Register and Unregister work in
+// the same way on a custom registry as the global functions Register and
+// Unregister on the default registry.
+//
+// There are a number of uses for custom registries: You can use registries
+// with special properties, see NewPedanticRegistry. You can avoid global state,
+// as it is imposed by the DefaultRegistry. You can use multiple registries at
+// the same time to expose different metrics in different ways. You can use
+// separate registries for testing purposes.
+//
+// Also note that the DefaultRegistry comes registered with a Collector for Go
+// runtime metrics (via NewGoCollector) and a Collector for process metrics (via
+// NewProcessCollector). With a custom registry, you are in control and decide
+// yourself about the Collectors to register.
+//
+// HTTP Exposition
+//
+// The Registry implements the Gatherer interface. The caller of the Gather
+// method can then expose the gathered metrics in some way. Usually, the metrics
+// are served via HTTP on the /metrics endpoint. That's happening in the example
+// above. The tools to expose metrics via HTTP are in the promhttp
+// sub-package. (The top-level functions in the prometheus package are
+// deprecated.)
+//
+// Pushing to the Pushgateway
+//
+// Function for pushing to the Pushgateway can be found in the push sub-package.
+//
+// Other Means of Exposition
+//
+// More ways of exposing metrics can easily be added. Sending metrics to
+// Graphite would be an example that will soon be implemented.
+package prometheus
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go
new file mode 100644
index 00000000..18a99d5f
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go
@@ -0,0 +1,119 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "encoding/json"
+ "expvar"
+)
+
+type expvarCollector struct {
+ exports map[string]*Desc
+}
+
+// NewExpvarCollector returns a newly allocated expvar Collector that still has
+// to be registered with a Prometheus registry.
+//
+// An expvar Collector collects metrics from the expvar interface. It provides a
+// quick way to expose numeric values that are already exported via expvar as
+// Prometheus metrics. Note that the data models of expvar and Prometheus are
+// fundamentally different, and that the expvar Collector is inherently slower
+// than native Prometheus metrics. Thus, the expvar Collector is probably great
+// for experiments and prototying, but you should seriously consider a more
+// direct implementation of Prometheus metrics for monitoring production
+// systems.
+//
+// The exports map has the following meaning:
+//
+// The keys in the map correspond to expvar keys, i.e. for every expvar key you
+// want to export as Prometheus metric, you need an entry in the exports
+// map. The descriptor mapped to each key describes how to export the expvar
+// value. It defines the name and the help string of the Prometheus metric
+// proxying the expvar value. The type will always be Untyped.
+//
+// For descriptors without variable labels, the expvar value must be a number or
+// a bool. The number is then directly exported as the Prometheus sample
+// value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values
+// that are not numbers or bools are silently ignored.
+//
+// If the descriptor has one variable label, the expvar value must be an expvar
+// map. The keys in the expvar map become the various values of the one
+// Prometheus label. The values in the expvar map must be numbers or bools again
+// as above.
+//
+// For descriptors with more than one variable label, the expvar must be a
+// nested expvar map, i.e. where the values of the topmost map are maps again
+// etc. until a depth is reached that corresponds to the number of labels. The
+// leaves of that structure must be numbers or bools as above to serve as the
+// sample values.
+//
+// Anything that does not fit into the scheme above is silently ignored.
+func NewExpvarCollector(exports map[string]*Desc) Collector {
+ return &expvarCollector{
+ exports: exports,
+ }
+}
+
+// Describe implements Collector.
+func (e *expvarCollector) Describe(ch chan<- *Desc) {
+ for _, desc := range e.exports {
+ ch <- desc
+ }
+}
+
+// Collect implements Collector.
+func (e *expvarCollector) Collect(ch chan<- Metric) {
+ for name, desc := range e.exports {
+ var m Metric
+ expVar := expvar.Get(name)
+ if expVar == nil {
+ continue
+ }
+ var v interface{}
+ labels := make([]string, len(desc.variableLabels))
+ if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil {
+ ch <- NewInvalidMetric(desc, err)
+ continue
+ }
+ var processValue func(v interface{}, i int)
+ processValue = func(v interface{}, i int) {
+ if i >= len(labels) {
+ copiedLabels := append(make([]string, 0, len(labels)), labels...)
+ switch v := v.(type) {
+ case float64:
+ m = MustNewConstMetric(desc, UntypedValue, v, copiedLabels...)
+ case bool:
+ if v {
+ m = MustNewConstMetric(desc, UntypedValue, 1, copiedLabels...)
+ } else {
+ m = MustNewConstMetric(desc, UntypedValue, 0, copiedLabels...)
+ }
+ default:
+ return
+ }
+ ch <- m
+ return
+ }
+ vm, ok := v.(map[string]interface{})
+ if !ok {
+ return
+ }
+ for lv, val := range vm {
+ labels[i] = lv
+ processValue(val, i+1)
+ }
+ }
+ processValue(v, 0)
+ }
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/fnv.go b/vendor/github.com/prometheus/client_golang/prometheus/fnv.go
new file mode 100644
index 00000000..e3b67df8
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/fnv.go
@@ -0,0 +1,29 @@
+package prometheus
+
+// Inline and byte-free variant of hash/fnv's fnv64a.
+
+const (
+ offset64 = 14695981039346656037
+ prime64 = 1099511628211
+)
+
+// hashNew initializies a new fnv64a hash value.
+func hashNew() uint64 {
+ return offset64
+}
+
+// hashAdd adds a string to a fnv64a hash value, returning the updated hash.
+func hashAdd(h uint64, s string) uint64 {
+ for i := 0; i < len(s); i++ {
+ h ^= uint64(s[i])
+ h *= prime64
+ }
+ return h
+}
+
+// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash.
+func hashAddByte(h uint64, b byte) uint64 {
+ h ^= uint64(b)
+ h *= prime64
+ return h
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go
new file mode 100644
index 00000000..8b70e514
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go
@@ -0,0 +1,140 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+// Gauge is a Metric that represents a single numerical value that can
+// arbitrarily go up and down.
+//
+// A Gauge is typically used for measured values like temperatures or current
+// memory usage, but also "counts" that can go up and down, like the number of
+// running goroutines.
+//
+// To create Gauge instances, use NewGauge.
+type Gauge interface {
+ Metric
+ Collector
+
+ // Set sets the Gauge to an arbitrary value.
+ Set(float64)
+ // Inc increments the Gauge by 1.
+ Inc()
+ // Dec decrements the Gauge by 1.
+ Dec()
+ // Add adds the given value to the Gauge. (The value can be
+ // negative, resulting in a decrease of the Gauge.)
+ Add(float64)
+ // Sub subtracts the given value from the Gauge. (The value can be
+ // negative, resulting in an increase of the Gauge.)
+ Sub(float64)
+}
+
+// GaugeOpts is an alias for Opts. See there for doc comments.
+type GaugeOpts Opts
+
+// NewGauge creates a new Gauge based on the provided GaugeOpts.
+func NewGauge(opts GaugeOpts) Gauge {
+ return newValue(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), GaugeValue, 0)
+}
+
+// GaugeVec is a Collector that bundles a set of Gauges that all share the same
+// Desc, but have different values for their variable labels. This is used if
+// you want to count the same thing partitioned by various dimensions
+// (e.g. number of operations queued, partitioned by user and operation
+// type). Create instances with NewGaugeVec.
+type GaugeVec struct {
+ *MetricVec
+}
+
+// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
+// partitioned by the given label names. At least one label name must be
+// provided.
+func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &GaugeVec{
+ MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ return newValue(desc, GaugeValue, 0, lvs...)
+ }),
+ }
+}
+
+// GetMetricWithLabelValues replaces the method of the same name in
+// MetricVec. The difference is that this method returns a Gauge and not a
+// Metric so that no type conversion is required.
+func (m *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
+ metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Gauge), err
+ }
+ return nil, err
+}
+
+// GetMetricWith replaces the method of the same name in MetricVec. The
+// difference is that this method returns a Gauge and not a Metric so that no
+// type conversion is required.
+func (m *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
+ metric, err := m.MetricVec.GetMetricWith(labels)
+ if metric != nil {
+ return metric.(Gauge), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. By not returning an
+// error, WithLabelValues allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Add(42)
+func (m *GaugeVec) WithLabelValues(lvs ...string) Gauge {
+ return m.MetricVec.WithLabelValues(lvs...).(Gauge)
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. By not returning an error, With allows shortcuts like
+// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
+func (m *GaugeVec) With(labels Labels) Gauge {
+ return m.MetricVec.With(labels).(Gauge)
+}
+
+// GaugeFunc is a Gauge whose value is determined at collect time by calling a
+// provided function.
+//
+// To create GaugeFunc instances, use NewGaugeFunc.
+type GaugeFunc interface {
+ Metric
+ Collector
+}
+
+// NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The
+// value reported is determined by calling the given function from within the
+// Write method. Take into account that metric collection may happen
+// concurrently. If that results in concurrent calls to Write, like in the case
+// where a GaugeFunc is directly registered with Prometheus, the provided
+// function must be concurrency-safe.
+func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
+ return newValueFunc(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), GaugeValue, function)
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
new file mode 100644
index 00000000..abc9d4ec
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
@@ -0,0 +1,263 @@
+package prometheus
+
+import (
+ "fmt"
+ "runtime"
+ "runtime/debug"
+ "time"
+)
+
+type goCollector struct {
+ goroutines Gauge
+ gcDesc *Desc
+
+ // metrics to describe and collect
+ metrics memStatsMetrics
+}
+
+// NewGoCollector returns a collector which exports metrics about the current
+// go process.
+func NewGoCollector() Collector {
+ return &goCollector{
+ goroutines: NewGauge(GaugeOpts{
+ Namespace: "go",
+ Name: "goroutines",
+ Help: "Number of goroutines that currently exist.",
+ }),
+ gcDesc: NewDesc(
+ "go_gc_duration_seconds",
+ "A summary of the GC invocation durations.",
+ nil, nil),
+ metrics: memStatsMetrics{
+ {
+ desc: NewDesc(
+ memstatNamespace("alloc_bytes"),
+ "Number of bytes allocated and still in use.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("alloc_bytes_total"),
+ "Total number of bytes allocated, even if freed.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("sys_bytes"),
+ "Number of bytes obtained by system. Sum of all system allocations.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("lookups_total"),
+ "Total number of pointer lookups.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mallocs_total"),
+ "Total number of mallocs.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("frees_total"),
+ "Total number of frees.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_alloc_bytes"),
+ "Number of heap bytes allocated and still in use.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_sys_bytes"),
+ "Number of heap bytes obtained from system.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_idle_bytes"),
+ "Number of heap bytes waiting to be used.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_inuse_bytes"),
+ "Number of heap bytes that are in use.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_released_bytes_total"),
+ "Total number of heap bytes released to OS.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },
+ valType: CounterValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("heap_objects"),
+ "Number of allocated objects.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("stack_inuse_bytes"),
+ "Number of bytes in use by the stack allocator.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("stack_sys_bytes"),
+ "Number of bytes obtained from system for stack allocator.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mspan_inuse_bytes"),
+ "Number of bytes in use by mspan structures.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mspan_sys_bytes"),
+ "Number of bytes used for mspan structures obtained from system.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mcache_inuse_bytes"),
+ "Number of bytes in use by mcache structures.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("mcache_sys_bytes"),
+ "Number of bytes used for mcache structures obtained from system.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("buck_hash_sys_bytes"),
+ "Number of bytes used by the profiling bucket hash table.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("gc_sys_bytes"),
+ "Number of bytes used for garbage collection system metadata.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("other_sys_bytes"),
+ "Number of bytes used for other system allocations.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("next_gc_bytes"),
+ "Number of heap bytes when next garbage collection will take place.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
+ valType: GaugeValue,
+ }, {
+ desc: NewDesc(
+ memstatNamespace("last_gc_time_seconds"),
+ "Number of seconds since 1970 of last garbage collection.",
+ nil, nil,
+ ),
+ eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 },
+ valType: GaugeValue,
+ },
+ },
+ }
+}
+
+func memstatNamespace(s string) string {
+ return fmt.Sprintf("go_memstats_%s", s)
+}
+
+// Describe returns all descriptions of the collector.
+func (c *goCollector) Describe(ch chan<- *Desc) {
+ ch <- c.goroutines.Desc()
+ ch <- c.gcDesc
+
+ for _, i := range c.metrics {
+ ch <- i.desc
+ }
+}
+
+// Collect returns the current state of all metrics of the collector.
+func (c *goCollector) Collect(ch chan<- Metric) {
+ c.goroutines.Set(float64(runtime.NumGoroutine()))
+ ch <- c.goroutines
+
+ var stats debug.GCStats
+ stats.PauseQuantiles = make([]time.Duration, 5)
+ debug.ReadGCStats(&stats)
+
+ quantiles := make(map[float64]float64)
+ for idx, pq := range stats.PauseQuantiles[1:] {
+ quantiles[float64(idx+1)/float64(len(stats.PauseQuantiles)-1)] = pq.Seconds()
+ }
+ quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
+ ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles)
+
+ ms := &runtime.MemStats{}
+ runtime.ReadMemStats(ms)
+ for _, i := range c.metrics {
+ ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
+ }
+}
+
+// memStatsMetrics provide description, value, and value type for memstat metrics.
+type memStatsMetrics []struct {
+ desc *Desc
+ eval func(*runtime.MemStats) float64
+ valType ValueType
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
new file mode 100644
index 00000000..9719e8fa
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go
@@ -0,0 +1,444 @@
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "fmt"
+ "math"
+ "sort"
+ "sync/atomic"
+
+ "github.com/golang/protobuf/proto"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// A Histogram counts individual observations from an event or sample stream in
+// configurable buckets. Similar to a summary, it also provides a sum of
+// observations and an observation count.
+//
+// On the Prometheus server, quantiles can be calculated from a Histogram using
+// the histogram_quantile function in the query language.
+//
+// Note that Histograms, in contrast to Summaries, can be aggregated with the
+// Prometheus query language (see the documentation for detailed
+// procedures). However, Histograms require the user to pre-define suitable
+// buckets, and they are in general less accurate. The Observe method of a
+// Histogram has a very low performance overhead in comparison with the Observe
+// method of a Summary.
+//
+// To create Histogram instances, use NewHistogram.
+type Histogram interface {
+ Metric
+ Collector
+
+ // Observe adds a single observation to the histogram.
+ Observe(float64)
+}
+
+// bucketLabel is used for the label that defines the upper bound of a
+// bucket of a histogram ("le" -> "less or equal").
+const bucketLabel = "le"
+
+// DefBuckets are the default Histogram buckets. The default buckets are
+// tailored to broadly measure the response time (in seconds) of a network
+// service. Most likely, however, you will be required to define buckets
+// customized to your use case.
+var (
+ DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
+
+ errBucketLabelNotAllowed = fmt.Errorf(
+ "%q is not allowed as label name in histograms", bucketLabel,
+ )
+)
+
+// LinearBuckets creates 'count' buckets, each 'width' wide, where the lowest
+// bucket has an upper bound of 'start'. The final +Inf bucket is not counted
+// and not included in the returned slice. The returned slice is meant to be
+// used for the Buckets field of HistogramOpts.
+//
+// The function panics if 'count' is zero or negative.
+func LinearBuckets(start, width float64, count int) []float64 {
+ if count < 1 {
+ panic("LinearBuckets needs a positive count")
+ }
+ buckets := make([]float64, count)
+ for i := range buckets {
+ buckets[i] = start
+ start += width
+ }
+ return buckets
+}
+
+// ExponentialBuckets creates 'count' buckets, where the lowest bucket has an
+// upper bound of 'start' and each following bucket's upper bound is 'factor'
+// times the previous bucket's upper bound. The final +Inf bucket is not counted
+// and not included in the returned slice. The returned slice is meant to be
+// used for the Buckets field of HistogramOpts.
+//
+// The function panics if 'count' is 0 or negative, if 'start' is 0 or negative,
+// or if 'factor' is less than or equal 1.
+func ExponentialBuckets(start, factor float64, count int) []float64 {
+ if count < 1 {
+ panic("ExponentialBuckets needs a positive count")
+ }
+ if start <= 0 {
+ panic("ExponentialBuckets needs a positive start value")
+ }
+ if factor <= 1 {
+ panic("ExponentialBuckets needs a factor greater than 1")
+ }
+ buckets := make([]float64, count)
+ for i := range buckets {
+ buckets[i] = start
+ start *= factor
+ }
+ return buckets
+}
+
+// HistogramOpts bundles the options for creating a Histogram metric. It is
+// mandatory to set Name and Help to a non-empty string. All other fields are
+// optional and can safely be left at their zero value.
+type HistogramOpts struct {
+ // Namespace, Subsystem, and Name are components of the fully-qualified
+ // name of the Histogram (created by joining these components with
+ // "_"). Only Name is mandatory, the others merely help structuring the
+ // name. Note that the fully-qualified name of the Histogram must be a
+ // valid Prometheus metric name.
+ Namespace string
+ Subsystem string
+ Name string
+
+ // Help provides information about this Histogram. Mandatory!
+ //
+ // Metrics with the same fully-qualified name must have the same Help
+ // string.
+ Help string
+
+ // ConstLabels are used to attach fixed labels to this
+ // Histogram. Histograms with the same fully-qualified name must have the
+ // same label names in their ConstLabels.
+ //
+ // Note that in most cases, labels have a value that varies during the
+ // lifetime of a process. Those labels are usually managed with a
+ // HistogramVec. ConstLabels serve only special purposes. One is for the
+ // special case where the value of a label does not change during the
+ // lifetime of a process, e.g. if the revision of the running binary is
+ // put into a label. Another, more advanced purpose is if more than one
+ // Collector needs to collect Histograms with the same fully-qualified
+ // name. In that case, those Summaries must differ in the values of
+ // their ConstLabels. See the Collector examples.
+ //
+ // If the value of a label never changes (not even between binaries),
+ // that label most likely should not be a label at all (but part of the
+ // metric name).
+ ConstLabels Labels
+
+ // Buckets defines the buckets into which observations are counted. Each
+ // element in the slice is the upper inclusive bound of a bucket. The
+ // values must be sorted in strictly increasing order. There is no need
+ // to add a highest bucket with +Inf bound, it will be added
+ // implicitly. The default value is DefBuckets.
+ Buckets []float64
+}
+
+// NewHistogram creates a new Histogram based on the provided HistogramOpts. It
+// panics if the buckets in HistogramOpts are not in strictly increasing order.
+func NewHistogram(opts HistogramOpts) Histogram {
+ return newHistogram(
+ NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ),
+ opts,
+ )
+}
+
+func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram {
+ if len(desc.variableLabels) != len(labelValues) {
+ panic(errInconsistentCardinality)
+ }
+
+ for _, n := range desc.variableLabels {
+ if n == bucketLabel {
+ panic(errBucketLabelNotAllowed)
+ }
+ }
+ for _, lp := range desc.constLabelPairs {
+ if lp.GetName() == bucketLabel {
+ panic(errBucketLabelNotAllowed)
+ }
+ }
+
+ if len(opts.Buckets) == 0 {
+ opts.Buckets = DefBuckets
+ }
+
+ h := &histogram{
+ desc: desc,
+ upperBounds: opts.Buckets,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }
+ for i, upperBound := range h.upperBounds {
+ if i < len(h.upperBounds)-1 {
+ if upperBound >= h.upperBounds[i+1] {
+ panic(fmt.Errorf(
+ "histogram buckets must be in increasing order: %f >= %f",
+ upperBound, h.upperBounds[i+1],
+ ))
+ }
+ } else {
+ if math.IsInf(upperBound, +1) {
+ // The +Inf bucket is implicit. Remove it here.
+ h.upperBounds = h.upperBounds[:i]
+ }
+ }
+ }
+ // Finally we know the final length of h.upperBounds and can make counts.
+ h.counts = make([]uint64, len(h.upperBounds))
+
+ h.init(h) // Init self-collection.
+ return h
+}
+
+type histogram struct {
+ // sumBits contains the bits of the float64 representing the sum of all
+ // observations. sumBits and count have to go first in the struct to
+ // guarantee alignment for atomic operations.
+ // http://golang.org/pkg/sync/atomic/#pkg-note-BUG
+ sumBits uint64
+ count uint64
+
+ selfCollector
+ // Note that there is no mutex required.
+
+ desc *Desc
+
+ upperBounds []float64
+ counts []uint64
+
+ labelPairs []*dto.LabelPair
+}
+
+func (h *histogram) Desc() *Desc {
+ return h.desc
+}
+
+func (h *histogram) Observe(v float64) {
+ // TODO(beorn7): For small numbers of buckets (<30), a linear search is
+ // slightly faster than the binary search. If we really care, we could
+ // switch from one search strategy to the other depending on the number
+ // of buckets.
+ //
+ // Microbenchmarks (BenchmarkHistogramNoLabels):
+ // 11 buckets: 38.3 ns/op linear - binary 48.7 ns/op
+ // 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op
+ // 300 buckets: 154 ns/op linear - binary 61.6 ns/op
+ i := sort.SearchFloat64s(h.upperBounds, v)
+ if i < len(h.counts) {
+ atomic.AddUint64(&h.counts[i], 1)
+ }
+ atomic.AddUint64(&h.count, 1)
+ for {
+ oldBits := atomic.LoadUint64(&h.sumBits)
+ newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
+ if atomic.CompareAndSwapUint64(&h.sumBits, oldBits, newBits) {
+ break
+ }
+ }
+}
+
+func (h *histogram) Write(out *dto.Metric) error {
+ his := &dto.Histogram{}
+ buckets := make([]*dto.Bucket, len(h.upperBounds))
+
+ his.SampleSum = proto.Float64(math.Float64frombits(atomic.LoadUint64(&h.sumBits)))
+ his.SampleCount = proto.Uint64(atomic.LoadUint64(&h.count))
+ var count uint64
+ for i, upperBound := range h.upperBounds {
+ count += atomic.LoadUint64(&h.counts[i])
+ buckets[i] = &dto.Bucket{
+ CumulativeCount: proto.Uint64(count),
+ UpperBound: proto.Float64(upperBound),
+ }
+ }
+ his.Bucket = buckets
+ out.Histogram = his
+ out.Label = h.labelPairs
+ return nil
+}
+
+// HistogramVec is a Collector that bundles a set of Histograms that all share the
+// same Desc, but have different values for their variable labels. This is used
+// if you want to count the same thing partitioned by various dimensions
+// (e.g. HTTP request latencies, partitioned by status code and method). Create
+// instances with NewHistogramVec.
+type HistogramVec struct {
+ *MetricVec
+}
+
+// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
+// partitioned by the given label names. At least one label name must be
+// provided.
+func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &HistogramVec{
+ MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ return newHistogram(desc, opts, lvs...)
+ }),
+ }
+}
+
+// GetMetricWithLabelValues replaces the method of the same name in
+// MetricVec. The difference is that this method returns a Histogram and not a
+// Metric so that no type conversion is required.
+func (m *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Histogram, error) {
+ metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Histogram), err
+ }
+ return nil, err
+}
+
+// GetMetricWith replaces the method of the same name in MetricVec. The
+// difference is that this method returns a Histogram and not a Metric so that no
+// type conversion is required.
+func (m *HistogramVec) GetMetricWith(labels Labels) (Histogram, error) {
+ metric, err := m.MetricVec.GetMetricWith(labels)
+ if metric != nil {
+ return metric.(Histogram), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. By not returning an
+// error, WithLabelValues allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Observe(42.21)
+func (m *HistogramVec) WithLabelValues(lvs ...string) Histogram {
+ return m.MetricVec.WithLabelValues(lvs...).(Histogram)
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. By not returning an error, With allows shortcuts like
+// myVec.With(Labels{"code": "404", "method": "GET"}).Observe(42.21)
+func (m *HistogramVec) With(labels Labels) Histogram {
+ return m.MetricVec.With(labels).(Histogram)
+}
+
+type constHistogram struct {
+ desc *Desc
+ count uint64
+ sum float64
+ buckets map[float64]uint64
+ labelPairs []*dto.LabelPair
+}
+
+func (h *constHistogram) Desc() *Desc {
+ return h.desc
+}
+
+func (h *constHistogram) Write(out *dto.Metric) error {
+ his := &dto.Histogram{}
+ buckets := make([]*dto.Bucket, 0, len(h.buckets))
+
+ his.SampleCount = proto.Uint64(h.count)
+ his.SampleSum = proto.Float64(h.sum)
+
+ for upperBound, count := range h.buckets {
+ buckets = append(buckets, &dto.Bucket{
+ CumulativeCount: proto.Uint64(count),
+ UpperBound: proto.Float64(upperBound),
+ })
+ }
+
+ if len(buckets) > 0 {
+ sort.Sort(buckSort(buckets))
+ }
+ his.Bucket = buckets
+
+ out.Histogram = his
+ out.Label = h.labelPairs
+
+ return nil
+}
+
+// NewConstHistogram returns a metric representing a Prometheus histogram with
+// fixed values for the count, sum, and bucket counts. As those parameters
+// cannot be changed, the returned value does not implement the Histogram
+// interface (but only the Metric interface). Users of this package will not
+// have much use for it in regular operations. However, when implementing custom
+// Collectors, it is useful as a throw-away metric that is generated on the fly
+// to send it to Prometheus in the Collect method.
+//
+// buckets is a map of upper bounds to cumulative counts, excluding the +Inf
+// bucket.
+//
+// NewConstHistogram returns an error if the length of labelValues is not
+// consistent with the variable labels in Desc.
+func NewConstHistogram(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ buckets map[float64]uint64,
+ labelValues ...string,
+) (Metric, error) {
+ if len(desc.variableLabels) != len(labelValues) {
+ return nil, errInconsistentCardinality
+ }
+ return &constHistogram{
+ desc: desc,
+ count: count,
+ sum: sum,
+ buckets: buckets,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }, nil
+}
+
+// MustNewConstHistogram is a version of NewConstHistogram that panics where
+// NewConstMetric would have returned an error.
+func MustNewConstHistogram(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ buckets map[float64]uint64,
+ labelValues ...string,
+) Metric {
+ m, err := NewConstHistogram(desc, count, sum, buckets, labelValues...)
+ if err != nil {
+ panic(err)
+ }
+ return m
+}
+
+type buckSort []*dto.Bucket
+
+func (s buckSort) Len() int {
+ return len(s)
+}
+
+func (s buckSort) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s buckSort) Less(i, j int) bool {
+ return s[i].GetUpperBound() < s[j].GetUpperBound()
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/http.go b/vendor/github.com/prometheus/client_golang/prometheus/http.go
new file mode 100644
index 00000000..67ee5ac7
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/http.go
@@ -0,0 +1,490 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/prometheus/common/expfmt"
+)
+
+// TODO(beorn7): Remove this whole file. It is a partial mirror of
+// promhttp/http.go (to avoid circular import chains) where everything HTTP
+// related should live. The functions here are just for avoiding
+// breakage. Everything is deprecated.
+
+const (
+ contentTypeHeader = "Content-Type"
+ contentLengthHeader = "Content-Length"
+ contentEncodingHeader = "Content-Encoding"
+ acceptEncodingHeader = "Accept-Encoding"
+)
+
+var bufPool sync.Pool
+
+func getBuf() *bytes.Buffer {
+ buf := bufPool.Get()
+ if buf == nil {
+ return &bytes.Buffer{}
+ }
+ return buf.(*bytes.Buffer)
+}
+
+func giveBuf(buf *bytes.Buffer) {
+ buf.Reset()
+ bufPool.Put(buf)
+}
+
+// Handler returns an HTTP handler for the DefaultGatherer. It is
+// already instrumented with InstrumentHandler (using "prometheus" as handler
+// name).
+//
+// Deprecated: Please note the issues described in the doc comment of
+// InstrumentHandler. You might want to consider using promhttp.Handler instead
+// (which is non instrumented).
+func Handler() http.Handler {
+ return InstrumentHandler("prometheus", UninstrumentedHandler())
+}
+
+// UninstrumentedHandler returns an HTTP handler for the DefaultGatherer.
+//
+// Deprecated: Use promhttp.Handler instead. See there for further documentation.
+func UninstrumentedHandler() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ mfs, err := DefaultGatherer.Gather()
+ if err != nil {
+ http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ contentType := expfmt.Negotiate(req.Header)
+ buf := getBuf()
+ defer giveBuf(buf)
+ writer, encoding := decorateWriter(req, buf)
+ enc := expfmt.NewEncoder(writer, contentType)
+ var lastErr error
+ for _, mf := range mfs {
+ if err := enc.Encode(mf); err != nil {
+ lastErr = err
+ http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+ if closer, ok := writer.(io.Closer); ok {
+ closer.Close()
+ }
+ if lastErr != nil && buf.Len() == 0 {
+ http.Error(w, "No metrics encoded, last error:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ header := w.Header()
+ header.Set(contentTypeHeader, string(contentType))
+ header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
+ if encoding != "" {
+ header.Set(contentEncodingHeader, encoding)
+ }
+ w.Write(buf.Bytes())
+ })
+}
+
+// decorateWriter wraps a writer to handle gzip compression if requested. It
+// returns the decorated writer and the appropriate "Content-Encoding" header
+// (which is empty if no compression is enabled).
+func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) {
+ header := request.Header.Get(acceptEncodingHeader)
+ parts := strings.Split(header, ",")
+ for _, part := range parts {
+ part := strings.TrimSpace(part)
+ if part == "gzip" || strings.HasPrefix(part, "gzip;") {
+ return gzip.NewWriter(writer), "gzip"
+ }
+ }
+ return writer, ""
+}
+
+var instLabels = []string{"method", "code"}
+
+type nower interface {
+ Now() time.Time
+}
+
+type nowFunc func() time.Time
+
+func (n nowFunc) Now() time.Time {
+ return n()
+}
+
+var now nower = nowFunc(func() time.Time {
+ return time.Now()
+})
+
+func nowSeries(t ...time.Time) nower {
+ return nowFunc(func() time.Time {
+ defer func() {
+ t = t[1:]
+ }()
+
+ return t[0]
+ })
+}
+
+// InstrumentHandler wraps the given HTTP handler for instrumentation. It
+// registers four metric collectors (if not already done) and reports HTTP
+// metrics to the (newly or already) registered collectors: http_requests_total
+// (CounterVec), http_request_duration_microseconds (Summary),
+// http_request_size_bytes (Summary), http_response_size_bytes (Summary). Each
+// has a constant label named "handler" with the provided handlerName as
+// value. http_requests_total is a metric vector partitioned by HTTP method
+// (label name "method") and HTTP status code (label name "code").
+//
+// Deprecated: InstrumentHandler has several issues:
+//
+// - It uses Summaries rather than Histograms. Summaries are not useful if
+// aggregation across multiple instances is required.
+//
+// - It uses microseconds as unit, which is deprecated and should be replaced by
+// seconds.
+//
+// - The size of the request is calculated in a separate goroutine. Since this
+// calculator requires access to the request header, it creates a race with
+// any writes to the header performed during request handling.
+// httputil.ReverseProxy is a prominent example for a handler
+// performing such writes.
+//
+// Upcoming versions of this package will provide ways of instrumenting HTTP
+// handlers that are more flexible and have fewer issues. Please prefer direct
+// instrumentation in the meantime.
+func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc {
+ return InstrumentHandlerFunc(handlerName, handler.ServeHTTP)
+}
+
+// InstrumentHandlerFunc wraps the given function for instrumentation. It
+// otherwise works in the same way as InstrumentHandler (and shares the same
+// issues).
+//
+// Deprecated: InstrumentHandlerFunc is deprecated for the same reasons as
+// InstrumentHandler is.
+func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
+ return InstrumentHandlerFuncWithOpts(
+ SummaryOpts{
+ Subsystem: "http",
+ ConstLabels: Labels{"handler": handlerName},
+ },
+ handlerFunc,
+ )
+}
+
+// InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same
+// issues) but provides more flexibility (at the cost of a more complex call
+// syntax). As InstrumentHandler, this function registers four metric
+// collectors, but it uses the provided SummaryOpts to create them. However, the
+// fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced
+// by "requests_total", "request_duration_microseconds", "request_size_bytes",
+// and "response_size_bytes", respectively. "Help" is replaced by an appropriate
+// help string. The names of the variable labels of the http_requests_total
+// CounterVec are "method" (get, post, etc.), and "code" (HTTP status code).
+//
+// If InstrumentHandlerWithOpts is called as follows, it mimics exactly the
+// behavior of InstrumentHandler:
+//
+// prometheus.InstrumentHandlerWithOpts(
+// prometheus.SummaryOpts{
+// Subsystem: "http",
+// ConstLabels: prometheus.Labels{"handler": handlerName},
+// },
+// handler,
+// )
+//
+// Technical detail: "requests_total" is a CounterVec, not a SummaryVec, so it
+// cannot use SummaryOpts. Instead, a CounterOpts struct is created internally,
+// and all its fields are set to the equally named fields in the provided
+// SummaryOpts.
+//
+// Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as
+// InstrumentHandler is.
+func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc {
+ return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP)
+}
+
+// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares
+// the same issues) but provides more flexibility (at the cost of a more complex
+// call syntax). See InstrumentHandlerWithOpts for details how the provided
+// SummaryOpts are used.
+//
+// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons
+// as InstrumentHandler is.
+func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
+ reqCnt := NewCounterVec(
+ CounterOpts{
+ Namespace: opts.Namespace,
+ Subsystem: opts.Subsystem,
+ Name: "requests_total",
+ Help: "Total number of HTTP requests made.",
+ ConstLabels: opts.ConstLabels,
+ },
+ instLabels,
+ )
+
+ opts.Name = "request_duration_microseconds"
+ opts.Help = "The HTTP request latencies in microseconds."
+ reqDur := NewSummary(opts)
+
+ opts.Name = "request_size_bytes"
+ opts.Help = "The HTTP request sizes in bytes."
+ reqSz := NewSummary(opts)
+
+ opts.Name = "response_size_bytes"
+ opts.Help = "The HTTP response sizes in bytes."
+ resSz := NewSummary(opts)
+
+ regReqCnt := MustRegisterOrGet(reqCnt).(*CounterVec)
+ regReqDur := MustRegisterOrGet(reqDur).(Summary)
+ regReqSz := MustRegisterOrGet(reqSz).(Summary)
+ regResSz := MustRegisterOrGet(resSz).(Summary)
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ now := time.Now()
+
+ delegate := &responseWriterDelegator{ResponseWriter: w}
+ out := make(chan int)
+ urlLen := 0
+ if r.URL != nil {
+ urlLen = len(r.URL.String())
+ }
+ go computeApproximateRequestSize(r, out, urlLen)
+
+ _, cn := w.(http.CloseNotifier)
+ _, fl := w.(http.Flusher)
+ _, hj := w.(http.Hijacker)
+ _, rf := w.(io.ReaderFrom)
+ var rw http.ResponseWriter
+ if cn && fl && hj && rf {
+ rw = &fancyResponseWriterDelegator{delegate}
+ } else {
+ rw = delegate
+ }
+ handlerFunc(rw, r)
+
+ elapsed := float64(time.Since(now)) / float64(time.Microsecond)
+
+ method := sanitizeMethod(r.Method)
+ code := sanitizeCode(delegate.status)
+ regReqCnt.WithLabelValues(method, code).Inc()
+ regReqDur.Observe(elapsed)
+ regResSz.Observe(float64(delegate.written))
+ regReqSz.Observe(float64(<-out))
+ })
+}
+
+func computeApproximateRequestSize(r *http.Request, out chan int, s int) {
+ s += len(r.Method)
+ s += len(r.Proto)
+ for name, values := range r.Header {
+ s += len(name)
+ for _, value := range values {
+ s += len(value)
+ }
+ }
+ s += len(r.Host)
+
+ // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
+
+ if r.ContentLength != -1 {
+ s += int(r.ContentLength)
+ }
+ out <- s
+}
+
+type responseWriterDelegator struct {
+ http.ResponseWriter
+
+ handler, method string
+ status int
+ written int64
+ wroteHeader bool
+}
+
+func (r *responseWriterDelegator) WriteHeader(code int) {
+ r.status = code
+ r.wroteHeader = true
+ r.ResponseWriter.WriteHeader(code)
+}
+
+func (r *responseWriterDelegator) Write(b []byte) (int, error) {
+ if !r.wroteHeader {
+ r.WriteHeader(http.StatusOK)
+ }
+ n, err := r.ResponseWriter.Write(b)
+ r.written += int64(n)
+ return n, err
+}
+
+type fancyResponseWriterDelegator struct {
+ *responseWriterDelegator
+}
+
+func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool {
+ return f.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
+
+func (f *fancyResponseWriterDelegator) Flush() {
+ f.ResponseWriter.(http.Flusher).Flush()
+}
+
+func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ return f.ResponseWriter.(http.Hijacker).Hijack()
+}
+
+func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) {
+ if !f.wroteHeader {
+ f.WriteHeader(http.StatusOK)
+ }
+ n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r)
+ f.written += n
+ return n, err
+}
+
+func sanitizeMethod(m string) string {
+ switch m {
+ case "GET", "get":
+ return "get"
+ case "PUT", "put":
+ return "put"
+ case "HEAD", "head":
+ return "head"
+ case "POST", "post":
+ return "post"
+ case "DELETE", "delete":
+ return "delete"
+ case "CONNECT", "connect":
+ return "connect"
+ case "OPTIONS", "options":
+ return "options"
+ case "NOTIFY", "notify":
+ return "notify"
+ default:
+ return strings.ToLower(m)
+ }
+}
+
+func sanitizeCode(s int) string {
+ switch s {
+ case 100:
+ return "100"
+ case 101:
+ return "101"
+
+ case 200:
+ return "200"
+ case 201:
+ return "201"
+ case 202:
+ return "202"
+ case 203:
+ return "203"
+ case 204:
+ return "204"
+ case 205:
+ return "205"
+ case 206:
+ return "206"
+
+ case 300:
+ return "300"
+ case 301:
+ return "301"
+ case 302:
+ return "302"
+ case 304:
+ return "304"
+ case 305:
+ return "305"
+ case 307:
+ return "307"
+
+ case 400:
+ return "400"
+ case 401:
+ return "401"
+ case 402:
+ return "402"
+ case 403:
+ return "403"
+ case 404:
+ return "404"
+ case 405:
+ return "405"
+ case 406:
+ return "406"
+ case 407:
+ return "407"
+ case 408:
+ return "408"
+ case 409:
+ return "409"
+ case 410:
+ return "410"
+ case 411:
+ return "411"
+ case 412:
+ return "412"
+ case 413:
+ return "413"
+ case 414:
+ return "414"
+ case 415:
+ return "415"
+ case 416:
+ return "416"
+ case 417:
+ return "417"
+ case 418:
+ return "418"
+
+ case 500:
+ return "500"
+ case 501:
+ return "501"
+ case 502:
+ return "502"
+ case 503:
+ return "503"
+ case 504:
+ return "504"
+ case 505:
+ return "505"
+
+ case 428:
+ return "428"
+ case 429:
+ return "429"
+ case 431:
+ return "431"
+ case 511:
+ return "511"
+
+ default:
+ return strconv.Itoa(s)
+ }
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go
new file mode 100644
index 00000000..d4063d98
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go
@@ -0,0 +1,166 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "strings"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+const separatorByte byte = 255
+
+// A Metric models a single sample value with its meta data being exported to
+// Prometheus. Implementations of Metric in this package are Gauge, Counter,
+// Histogram, Summary, and Untyped.
+type Metric interface {
+ // Desc returns the descriptor for the Metric. This method idempotently
+ // returns the same descriptor throughout the lifetime of the
+ // Metric. The returned descriptor is immutable by contract. A Metric
+ // unable to describe itself must return an invalid descriptor (created
+ // with NewInvalidDesc).
+ Desc() *Desc
+ // Write encodes the Metric into a "Metric" Protocol Buffer data
+ // transmission object.
+ //
+ // Metric implementations must observe concurrency safety as reads of
+ // this metric may occur at any time, and any blocking occurs at the
+ // expense of total performance of rendering all registered
+ // metrics. Ideally, Metric implementations should support concurrent
+ // readers.
+ //
+ // While populating dto.Metric, it is the responsibility of the
+ // implementation to ensure validity of the Metric protobuf (like valid
+ // UTF-8 strings or syntactically valid metric and label names). It is
+ // recommended to sort labels lexicographically. (Implementers may find
+ // LabelPairSorter useful for that.) Callers of Write should still make
+ // sure of sorting if they depend on it.
+ Write(*dto.Metric) error
+ // TODO(beorn7): The original rationale of passing in a pre-allocated
+ // dto.Metric protobuf to save allocations has disappeared. The
+ // signature of this method should be changed to "Write() (*dto.Metric,
+ // error)".
+}
+
+// Opts bundles the options for creating most Metric types. Each metric
+// implementation XXX has its own XXXOpts type, but in most cases, it is just be
+// an alias of this type (which might change when the requirement arises.)
+//
+// It is mandatory to set Name and Help to a non-empty string. All other fields
+// are optional and can safely be left at their zero value.
+type Opts struct {
+ // Namespace, Subsystem, and Name are components of the fully-qualified
+ // name of the Metric (created by joining these components with
+ // "_"). Only Name is mandatory, the others merely help structuring the
+ // name. Note that the fully-qualified name of the metric must be a
+ // valid Prometheus metric name.
+ Namespace string
+ Subsystem string
+ Name string
+
+ // Help provides information about this metric. Mandatory!
+ //
+ // Metrics with the same fully-qualified name must have the same Help
+ // string.
+ Help string
+
+ // ConstLabels are used to attach fixed labels to this metric. Metrics
+ // with the same fully-qualified name must have the same label names in
+ // their ConstLabels.
+ //
+ // Note that in most cases, labels have a value that varies during the
+ // lifetime of a process. Those labels are usually managed with a metric
+ // vector collector (like CounterVec, GaugeVec, UntypedVec). ConstLabels
+ // serve only special purposes. One is for the special case where the
+ // value of a label does not change during the lifetime of a process,
+ // e.g. if the revision of the running binary is put into a
+ // label. Another, more advanced purpose is if more than one Collector
+ // needs to collect Metrics with the same fully-qualified name. In that
+ // case, those Metrics must differ in the values of their
+ // ConstLabels. See the Collector examples.
+ //
+ // If the value of a label never changes (not even between binaries),
+ // that label most likely should not be a label at all (but part of the
+ // metric name).
+ ConstLabels Labels
+}
+
+// BuildFQName joins the given three name components by "_". Empty name
+// components are ignored. If the name parameter itself is empty, an empty
+// string is returned, no matter what. Metric implementations included in this
+// library use this function internally to generate the fully-qualified metric
+// name from the name component in their Opts. Users of the library will only
+// need this function if they implement their own Metric or instantiate a Desc
+// (with NewDesc) directly.
+func BuildFQName(namespace, subsystem, name string) string {
+ if name == "" {
+ return ""
+ }
+ switch {
+ case namespace != "" && subsystem != "":
+ return strings.Join([]string{namespace, subsystem, name}, "_")
+ case namespace != "":
+ return strings.Join([]string{namespace, name}, "_")
+ case subsystem != "":
+ return strings.Join([]string{subsystem, name}, "_")
+ }
+ return name
+}
+
+// LabelPairSorter implements sort.Interface. It is used to sort a slice of
+// dto.LabelPair pointers. This is useful for implementing the Write method of
+// custom metrics.
+type LabelPairSorter []*dto.LabelPair
+
+func (s LabelPairSorter) Len() int {
+ return len(s)
+}
+
+func (s LabelPairSorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s LabelPairSorter) Less(i, j int) bool {
+ return s[i].GetName() < s[j].GetName()
+}
+
+type hashSorter []uint64
+
+func (s hashSorter) Len() int {
+ return len(s)
+}
+
+func (s hashSorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s hashSorter) Less(i, j int) bool {
+ return s[i] < s[j]
+}
+
+type invalidMetric struct {
+ desc *Desc
+ err error
+}
+
+// NewInvalidMetric returns a metric whose Write method always returns the
+// provided error. It is useful if a Collector finds itself unable to collect
+// a metric and wishes to report an error to the registry.
+func NewInvalidMetric(desc *Desc, err error) Metric {
+ return &invalidMetric{desc, err}
+}
+
+func (m *invalidMetric) Desc() *Desc { return m.desc }
+
+func (m *invalidMetric) Write(*dto.Metric) error { return m.err }
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
new file mode 100644
index 00000000..e31e62e7
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
@@ -0,0 +1,142 @@
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import "github.com/prometheus/procfs"
+
+type processCollector struct {
+ pid int
+ collectFn func(chan<- Metric)
+ pidFn func() (int, error)
+ cpuTotal Counter
+ openFDs, maxFDs Gauge
+ vsize, rss Gauge
+ startTime Gauge
+}
+
+// NewProcessCollector returns a collector which exports the current state of
+// process metrics including cpu, memory and file descriptor usage as well as
+// the process start time for the given process id under the given namespace.
+func NewProcessCollector(pid int, namespace string) Collector {
+ return NewProcessCollectorPIDFn(
+ func() (int, error) { return pid, nil },
+ namespace,
+ )
+}
+
+// NewProcessCollectorPIDFn returns a collector which exports the current state
+// of process metrics including cpu, memory and file descriptor usage as well
+// as the process start time under the given namespace. The given pidFn is
+// called on each collect and is used to determine the process to export
+// metrics for.
+func NewProcessCollectorPIDFn(
+ pidFn func() (int, error),
+ namespace string,
+) Collector {
+ c := processCollector{
+ pidFn: pidFn,
+ collectFn: func(chan<- Metric) {},
+
+ cpuTotal: NewCounter(CounterOpts{
+ Namespace: namespace,
+ Name: "process_cpu_seconds_total",
+ Help: "Total user and system CPU time spent in seconds.",
+ }),
+ openFDs: NewGauge(GaugeOpts{
+ Namespace: namespace,
+ Name: "process_open_fds",
+ Help: "Number of open file descriptors.",
+ }),
+ maxFDs: NewGauge(GaugeOpts{
+ Namespace: namespace,
+ Name: "process_max_fds",
+ Help: "Maximum number of open file descriptors.",
+ }),
+ vsize: NewGauge(GaugeOpts{
+ Namespace: namespace,
+ Name: "process_virtual_memory_bytes",
+ Help: "Virtual memory size in bytes.",
+ }),
+ rss: NewGauge(GaugeOpts{
+ Namespace: namespace,
+ Name: "process_resident_memory_bytes",
+ Help: "Resident memory size in bytes.",
+ }),
+ startTime: NewGauge(GaugeOpts{
+ Namespace: namespace,
+ Name: "process_start_time_seconds",
+ Help: "Start time of the process since unix epoch in seconds.",
+ }),
+ }
+
+ // Set up process metric collection if supported by the runtime.
+ if _, err := procfs.NewStat(); err == nil {
+ c.collectFn = c.processCollect
+ }
+
+ return &c
+}
+
+// Describe returns all descriptions of the collector.
+func (c *processCollector) Describe(ch chan<- *Desc) {
+ ch <- c.cpuTotal.Desc()
+ ch <- c.openFDs.Desc()
+ ch <- c.maxFDs.Desc()
+ ch <- c.vsize.Desc()
+ ch <- c.rss.Desc()
+ ch <- c.startTime.Desc()
+}
+
+// Collect returns the current state of all metrics of the collector.
+func (c *processCollector) Collect(ch chan<- Metric) {
+ c.collectFn(ch)
+}
+
+// TODO(ts): Bring back error reporting by reverting 7faf9e7 as soon as the
+// client allows users to configure the error behavior.
+func (c *processCollector) processCollect(ch chan<- Metric) {
+ pid, err := c.pidFn()
+ if err != nil {
+ return
+ }
+
+ p, err := procfs.NewProc(pid)
+ if err != nil {
+ return
+ }
+
+ if stat, err := p.NewStat(); err == nil {
+ c.cpuTotal.Set(stat.CPUTime())
+ ch <- c.cpuTotal
+ c.vsize.Set(float64(stat.VirtualMemory()))
+ ch <- c.vsize
+ c.rss.Set(float64(stat.ResidentMemory()))
+ ch <- c.rss
+
+ if startTime, err := stat.StartTime(); err == nil {
+ c.startTime.Set(startTime)
+ ch <- c.startTime
+ }
+ }
+
+ if fds, err := p.FileDescriptorsLen(); err == nil {
+ c.openFDs.Set(float64(fds))
+ ch <- c.openFDs
+ }
+
+ if limits, err := p.NewLimits(); err == nil {
+ c.maxFDs.Set(float64(limits.OpenFiles))
+ ch <- c.maxFDs
+ }
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
new file mode 100644
index 00000000..b6dd5a26
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
@@ -0,0 +1,201 @@
+// Copyright 2016 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright (c) 2013, The Prometheus Authors
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be found
+// in the LICENSE file.
+
+// Package promhttp contains functions to create http.Handler instances to
+// expose Prometheus metrics via HTTP. In later versions of this package, it
+// will also contain tooling to instrument instances of http.Handler and
+// http.RoundTripper.
+//
+// promhttp.Handler acts on the prometheus.DefaultGatherer. With HandlerFor,
+// you can create a handler for a custom registry or anything that implements
+// the Gatherer interface. It also allows to create handlers that act
+// differently on errors or allow to log errors.
+package promhttp
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "net/http"
+ "strings"
+ "sync"
+
+ "github.com/prometheus/common/expfmt"
+
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+const (
+ contentTypeHeader = "Content-Type"
+ contentLengthHeader = "Content-Length"
+ contentEncodingHeader = "Content-Encoding"
+ acceptEncodingHeader = "Accept-Encoding"
+)
+
+var bufPool sync.Pool
+
+func getBuf() *bytes.Buffer {
+ buf := bufPool.Get()
+ if buf == nil {
+ return &bytes.Buffer{}
+ }
+ return buf.(*bytes.Buffer)
+}
+
+func giveBuf(buf *bytes.Buffer) {
+ buf.Reset()
+ bufPool.Put(buf)
+}
+
+// Handler returns an HTTP handler for the prometheus.DefaultGatherer. The
+// Handler uses the default HandlerOpts, i.e. report the first error as an HTTP
+// error, no error logging, and compression if requested by the client.
+//
+// If you want to create a Handler for the DefaultGatherer with different
+// HandlerOpts, create it with HandlerFor with prometheus.DefaultGatherer and
+// your desired HandlerOpts.
+func Handler() http.Handler {
+ return HandlerFor(prometheus.DefaultGatherer, HandlerOpts{})
+}
+
+// HandlerFor returns an http.Handler for the provided Gatherer. The behavior
+// of the Handler is defined by the provided HandlerOpts.
+func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ mfs, err := reg.Gather()
+ if err != nil {
+ if opts.ErrorLog != nil {
+ opts.ErrorLog.Println("error gathering metrics:", err)
+ }
+ switch opts.ErrorHandling {
+ case PanicOnError:
+ panic(err)
+ case ContinueOnError:
+ if len(mfs) == 0 {
+ http.Error(w, "No metrics gathered, last error:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ case HTTPErrorOnError:
+ http.Error(w, "An error has occurred during metrics gathering:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+
+ contentType := expfmt.Negotiate(req.Header)
+ buf := getBuf()
+ defer giveBuf(buf)
+ writer, encoding := decorateWriter(req, buf, opts.DisableCompression)
+ enc := expfmt.NewEncoder(writer, contentType)
+ var lastErr error
+ for _, mf := range mfs {
+ if err := enc.Encode(mf); err != nil {
+ lastErr = err
+ if opts.ErrorLog != nil {
+ opts.ErrorLog.Println("error encoding metric family:", err)
+ }
+ switch opts.ErrorHandling {
+ case PanicOnError:
+ panic(err)
+ case ContinueOnError:
+ // Handled later.
+ case HTTPErrorOnError:
+ http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+ }
+ if closer, ok := writer.(io.Closer); ok {
+ closer.Close()
+ }
+ if lastErr != nil && buf.Len() == 0 {
+ http.Error(w, "No metrics encoded, last error:\n\n"+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ header := w.Header()
+ header.Set(contentTypeHeader, string(contentType))
+ header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
+ if encoding != "" {
+ header.Set(contentEncodingHeader, encoding)
+ }
+ w.Write(buf.Bytes())
+ // TODO(beorn7): Consider streaming serving of metrics.
+ })
+}
+
+// HandlerErrorHandling defines how a Handler serving metrics will handle
+// errors.
+type HandlerErrorHandling int
+
+// These constants cause handlers serving metrics to behave as described if
+// errors are encountered.
+const (
+ // Serve an HTTP status code 500 upon the first error
+ // encountered. Report the error message in the body.
+ HTTPErrorOnError HandlerErrorHandling = iota
+ // Ignore errors and try to serve as many metrics as possible. However,
+ // if no metrics can be served, serve an HTTP status code 500 and the
+ // last error message in the body. Only use this in deliberate "best
+ // effort" metrics collection scenarios. It is recommended to at least
+ // log errors (by providing an ErrorLog in HandlerOpts) to not mask
+ // errors completely.
+ ContinueOnError
+ // Panic upon the first error encountered (useful for "crash only" apps).
+ PanicOnError
+)
+
+// Logger is the minimal interface HandlerOpts needs for logging. Note that
+// log.Logger from the standard library implements this interface, and it is
+// easy to implement by custom loggers, if they don't do so already anyway.
+type Logger interface {
+ Println(v ...interface{})
+}
+
+// HandlerOpts specifies options how to serve metrics via an http.Handler. The
+// zero value of HandlerOpts is a reasonable default.
+type HandlerOpts struct {
+ // ErrorLog specifies an optional logger for errors collecting and
+ // serving metrics. If nil, errors are not logged at all.
+ ErrorLog Logger
+ // ErrorHandling defines how errors are handled. Note that errors are
+ // logged regardless of the configured ErrorHandling provided ErrorLog
+ // is not nil.
+ ErrorHandling HandlerErrorHandling
+ // If DisableCompression is true, the handler will never compress the
+ // response, even if requested by the client.
+ DisableCompression bool
+}
+
+// decorateWriter wraps a writer to handle gzip compression if requested. It
+// returns the decorated writer and the appropriate "Content-Encoding" header
+// (which is empty if no compression is enabled).
+func decorateWriter(request *http.Request, writer io.Writer, compressionDisabled bool) (io.Writer, string) {
+ if compressionDisabled {
+ return writer, ""
+ }
+ header := request.Header.Get(acceptEncodingHeader)
+ parts := strings.Split(header, ",")
+ for _, part := range parts {
+ part := strings.TrimSpace(part)
+ if part == "gzip" || strings.HasPrefix(part, "gzip;") {
+ return gzip.NewWriter(writer), "gzip"
+ }
+ }
+ return writer, ""
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go
new file mode 100644
index 00000000..32a3986b
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go
@@ -0,0 +1,806 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "os"
+ "sort"
+ "sync"
+
+ "github.com/golang/protobuf/proto"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+const (
+ // Capacity for the channel to collect metrics and descriptors.
+ capMetricChan = 1000
+ capDescChan = 10
+)
+
+// DefaultRegisterer and DefaultGatherer are the implementations of the
+// Registerer and Gatherer interface a number of convenience functions in this
+// package act on. Initially, both variables point to the same Registry, which
+// has a process collector (see NewProcessCollector) and a Go collector (see
+// NewGoCollector) already registered. This approach to keep default instances
+// as global state mirrors the approach of other packages in the Go standard
+// library. Note that there are caveats. Change the variables with caution and
+// only if you understand the consequences. Users who want to avoid global state
+// altogether should not use the convenience function and act on custom
+// instances instead.
+var (
+ defaultRegistry = NewRegistry()
+ DefaultRegisterer Registerer = defaultRegistry
+ DefaultGatherer Gatherer = defaultRegistry
+)
+
+func init() {
+ MustRegister(NewProcessCollector(os.Getpid(), ""))
+ MustRegister(NewGoCollector())
+}
+
+// NewRegistry creates a new vanilla Registry without any Collectors
+// pre-registered.
+func NewRegistry() *Registry {
+ return &Registry{
+ collectorsByID: map[uint64]Collector{},
+ descIDs: map[uint64]struct{}{},
+ dimHashesByName: map[string]uint64{},
+ }
+}
+
+// NewPedanticRegistry returns a registry that checks during collection if each
+// collected Metric is consistent with its reported Desc, and if the Desc has
+// actually been registered with the registry.
+//
+// Usually, a Registry will be happy as long as the union of all collected
+// Metrics is consistent and valid even if some metrics are not consistent with
+// their own Desc or a Desc provided by their registered Collector. Well-behaved
+// Collectors and Metrics will only provide consistent Descs. This Registry is
+// useful to test the implementation of Collectors and Metrics.
+func NewPedanticRegistry() *Registry {
+ r := NewRegistry()
+ r.pedanticChecksEnabled = true
+ return r
+}
+
+// Registerer is the interface for the part of a registry in charge of
+// registering and unregistering. Users of custom registries should use
+// Registerer as type for registration purposes (rather then the Registry type
+// directly). In that way, they are free to use custom Registerer implementation
+// (e.g. for testing purposes).
+type Registerer interface {
+ // Register registers a new Collector to be included in metrics
+ // collection. It returns an error if the descriptors provided by the
+ // Collector are invalid or if they — in combination with descriptors of
+ // already registered Collectors — do not fulfill the consistency and
+ // uniqueness criteria described in the documentation of metric.Desc.
+ //
+ // If the provided Collector is equal to a Collector already registered
+ // (which includes the case of re-registering the same Collector), the
+ // returned error is an instance of AlreadyRegisteredError, which
+ // contains the previously registered Collector.
+ //
+ // It is in general not safe to register the same Collector multiple
+ // times concurrently.
+ Register(Collector) error
+ // MustRegister works like Register but registers any number of
+ // Collectors and panics upon the first registration that causes an
+ // error.
+ MustRegister(...Collector)
+ // Unregister unregisters the Collector that equals the Collector passed
+ // in as an argument. (Two Collectors are considered equal if their
+ // Describe method yields the same set of descriptors.) The function
+ // returns whether a Collector was unregistered.
+ //
+ // Note that even after unregistering, it will not be possible to
+ // register a new Collector that is inconsistent with the unregistered
+ // Collector, e.g. a Collector collecting metrics with the same name but
+ // a different help string. The rationale here is that the same registry
+ // instance must only collect consistent metrics throughout its
+ // lifetime.
+ Unregister(Collector) bool
+}
+
+// Gatherer is the interface for the part of a registry in charge of gathering
+// the collected metrics into a number of MetricFamilies. The Gatherer interface
+// comes with the same general implication as described for the Registerer
+// interface.
+type Gatherer interface {
+ // Gather calls the Collect method of the registered Collectors and then
+ // gathers the collected metrics into a lexicographically sorted slice
+ // of MetricFamily protobufs. Even if an error occurs, Gather attempts
+ // to gather as many metrics as possible. Hence, if a non-nil error is
+ // returned, the returned MetricFamily slice could be nil (in case of a
+ // fatal error that prevented any meaningful metric collection) or
+ // contain a number of MetricFamily protobufs, some of which might be
+ // incomplete, and some might be missing altogether. The returned error
+ // (which might be a MultiError) explains the details. In scenarios
+ // where complete collection is critical, the returned MetricFamily
+ // protobufs should be disregarded if the returned error is non-nil.
+ Gather() ([]*dto.MetricFamily, error)
+}
+
+// Register registers the provided Collector with the DefaultRegisterer.
+//
+// Register is a shortcut for DefaultRegisterer.Register(c). See there for more
+// details.
+func Register(c Collector) error {
+ return DefaultRegisterer.Register(c)
+}
+
+// MustRegister registers the provided Collectors with the DefaultRegisterer and
+// panics if any error occurs.
+//
+// MustRegister is a shortcut for DefaultRegisterer.MustRegister(cs...). See
+// there for more details.
+func MustRegister(cs ...Collector) {
+ DefaultRegisterer.MustRegister(cs...)
+}
+
+// RegisterOrGet registers the provided Collector with the DefaultRegisterer and
+// returns the Collector, unless an equal Collector was registered before, in
+// which case that Collector is returned.
+//
+// Deprecated: RegisterOrGet is merely a convenience function for the
+// implementation as described in the documentation for
+// AlreadyRegisteredError. As the use case is relatively rare, this function
+// will be removed in a future version of this package to clean up the
+// namespace.
+func RegisterOrGet(c Collector) (Collector, error) {
+ if err := Register(c); err != nil {
+ if are, ok := err.(AlreadyRegisteredError); ok {
+ return are.ExistingCollector, nil
+ }
+ return nil, err
+ }
+ return c, nil
+}
+
+// MustRegisterOrGet behaves like RegisterOrGet but panics instead of returning
+// an error.
+//
+// Deprecated: This is deprecated for the same reason RegisterOrGet is. See
+// there for details.
+func MustRegisterOrGet(c Collector) Collector {
+ c, err := RegisterOrGet(c)
+ if err != nil {
+ panic(err)
+ }
+ return c
+}
+
+// Unregister removes the registration of the provided Collector from the
+// DefaultRegisterer.
+//
+// Unregister is a shortcut for DefaultRegisterer.Unregister(c). See there for
+// more details.
+func Unregister(c Collector) bool {
+ return DefaultRegisterer.Unregister(c)
+}
+
+// GathererFunc turns a function into a Gatherer.
+type GathererFunc func() ([]*dto.MetricFamily, error)
+
+// Gather implements Gatherer.
+func (gf GathererFunc) Gather() ([]*dto.MetricFamily, error) {
+ return gf()
+}
+
+// SetMetricFamilyInjectionHook replaces the DefaultGatherer with one that
+// gathers from the previous DefaultGatherers but then merges the MetricFamily
+// protobufs returned from the provided hook function with the MetricFamily
+// protobufs returned from the original DefaultGatherer.
+//
+// Deprecated: This function manipulates the DefaultGatherer variable. Consider
+// the implications, i.e. don't do this concurrently with any uses of the
+// DefaultGatherer. In the rare cases where you need to inject MetricFamily
+// protobufs directly, it is recommended to use a custom Registry and combine it
+// with a custom Gatherer using the Gatherers type (see
+// there). SetMetricFamilyInjectionHook only exists for compatibility reasons
+// with previous versions of this package.
+func SetMetricFamilyInjectionHook(hook func() []*dto.MetricFamily) {
+ DefaultGatherer = Gatherers{
+ DefaultGatherer,
+ GathererFunc(func() ([]*dto.MetricFamily, error) { return hook(), nil }),
+ }
+}
+
+// AlreadyRegisteredError is returned by the Register method if the Collector to
+// be registered has already been registered before, or a different Collector
+// that collects the same metrics has been registered before. Registration fails
+// in that case, but you can detect from the kind of error what has
+// happened. The error contains fields for the existing Collector and the
+// (rejected) new Collector that equals the existing one. This can be used to
+// find out if an equal Collector has been registered before and switch over to
+// using the old one, as demonstrated in the example.
+type AlreadyRegisteredError struct {
+ ExistingCollector, NewCollector Collector
+}
+
+func (err AlreadyRegisteredError) Error() string {
+ return "duplicate metrics collector registration attempted"
+}
+
+// MultiError is a slice of errors implementing the error interface. It is used
+// by a Gatherer to report multiple errors during MetricFamily gathering.
+type MultiError []error
+
+func (errs MultiError) Error() string {
+ if len(errs) == 0 {
+ return ""
+ }
+ buf := &bytes.Buffer{}
+ fmt.Fprintf(buf, "%d error(s) occurred:", len(errs))
+ for _, err := range errs {
+ fmt.Fprintf(buf, "\n* %s", err)
+ }
+ return buf.String()
+}
+
+// MaybeUnwrap returns nil if len(errs) is 0. It returns the first and only
+// contained error as error if len(errs is 1). In all other cases, it returns
+// the MultiError directly. This is helpful for returning a MultiError in a way
+// that only uses the MultiError if needed.
+func (errs MultiError) MaybeUnwrap() error {
+ switch len(errs) {
+ case 0:
+ return nil
+ case 1:
+ return errs[0]
+ default:
+ return errs
+ }
+}
+
+// Registry registers Prometheus collectors, collects their metrics, and gathers
+// them into MetricFamilies for exposition. It implements both Registerer and
+// Gatherer. The zero value is not usable. Create instances with NewRegistry or
+// NewPedanticRegistry.
+type Registry struct {
+ mtx sync.RWMutex
+ collectorsByID map[uint64]Collector // ID is a hash of the descIDs.
+ descIDs map[uint64]struct{}
+ dimHashesByName map[string]uint64
+ pedanticChecksEnabled bool
+}
+
+// Register implements Registerer.
+func (r *Registry) Register(c Collector) error {
+ var (
+ descChan = make(chan *Desc, capDescChan)
+ newDescIDs = map[uint64]struct{}{}
+ newDimHashesByName = map[string]uint64{}
+ collectorID uint64 // Just a sum of all desc IDs.
+ duplicateDescErr error
+ )
+ go func() {
+ c.Describe(descChan)
+ close(descChan)
+ }()
+ r.mtx.Lock()
+ defer r.mtx.Unlock()
+ // Coduct various tests...
+ for desc := range descChan {
+
+ // Is the descriptor valid at all?
+ if desc.err != nil {
+ return fmt.Errorf("descriptor %s is invalid: %s", desc, desc.err)
+ }
+
+ // Is the descID unique?
+ // (In other words: Is the fqName + constLabel combination unique?)
+ if _, exists := r.descIDs[desc.id]; exists {
+ duplicateDescErr = fmt.Errorf("descriptor %s already exists with the same fully-qualified name and const label values", desc)
+ }
+ // If it is not a duplicate desc in this collector, add it to
+ // the collectorID. (We allow duplicate descs within the same
+ // collector, but their existence must be a no-op.)
+ if _, exists := newDescIDs[desc.id]; !exists {
+ newDescIDs[desc.id] = struct{}{}
+ collectorID += desc.id
+ }
+
+ // Are all the label names and the help string consistent with
+ // previous descriptors of the same name?
+ // First check existing descriptors...
+ if dimHash, exists := r.dimHashesByName[desc.fqName]; exists {
+ if dimHash != desc.dimHash {
+ return fmt.Errorf("a previously registered descriptor with the same fully-qualified name as %s has different label names or a different help string", desc)
+ }
+ } else {
+ // ...then check the new descriptors already seen.
+ if dimHash, exists := newDimHashesByName[desc.fqName]; exists {
+ if dimHash != desc.dimHash {
+ return fmt.Errorf("descriptors reported by collector have inconsistent label names or help strings for the same fully-qualified name, offender is %s", desc)
+ }
+ } else {
+ newDimHashesByName[desc.fqName] = desc.dimHash
+ }
+ }
+ }
+ // Did anything happen at all?
+ if len(newDescIDs) == 0 {
+ return errors.New("collector has no descriptors")
+ }
+ if existing, exists := r.collectorsByID[collectorID]; exists {
+ return AlreadyRegisteredError{
+ ExistingCollector: existing,
+ NewCollector: c,
+ }
+ }
+ // If the collectorID is new, but at least one of the descs existed
+ // before, we are in trouble.
+ if duplicateDescErr != nil {
+ return duplicateDescErr
+ }
+
+ // Only after all tests have passed, actually register.
+ r.collectorsByID[collectorID] = c
+ for hash := range newDescIDs {
+ r.descIDs[hash] = struct{}{}
+ }
+ for name, dimHash := range newDimHashesByName {
+ r.dimHashesByName[name] = dimHash
+ }
+ return nil
+}
+
+// Unregister implements Registerer.
+func (r *Registry) Unregister(c Collector) bool {
+ var (
+ descChan = make(chan *Desc, capDescChan)
+ descIDs = map[uint64]struct{}{}
+ collectorID uint64 // Just a sum of the desc IDs.
+ )
+ go func() {
+ c.Describe(descChan)
+ close(descChan)
+ }()
+ for desc := range descChan {
+ if _, exists := descIDs[desc.id]; !exists {
+ collectorID += desc.id
+ descIDs[desc.id] = struct{}{}
+ }
+ }
+
+ r.mtx.RLock()
+ if _, exists := r.collectorsByID[collectorID]; !exists {
+ r.mtx.RUnlock()
+ return false
+ }
+ r.mtx.RUnlock()
+
+ r.mtx.Lock()
+ defer r.mtx.Unlock()
+
+ delete(r.collectorsByID, collectorID)
+ for id := range descIDs {
+ delete(r.descIDs, id)
+ }
+ // dimHashesByName is left untouched as those must be consistent
+ // throughout the lifetime of a program.
+ return true
+}
+
+// MustRegister implements Registerer.
+func (r *Registry) MustRegister(cs ...Collector) {
+ for _, c := range cs {
+ if err := r.Register(c); err != nil {
+ panic(err)
+ }
+ }
+}
+
+// Gather implements Gatherer.
+func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
+ var (
+ metricChan = make(chan Metric, capMetricChan)
+ metricHashes = map[uint64]struct{}{}
+ dimHashes = map[string]uint64{}
+ wg sync.WaitGroup
+ errs MultiError // The collected errors to return in the end.
+ registeredDescIDs map[uint64]struct{} // Only used for pedantic checks
+ )
+
+ r.mtx.RLock()
+ metricFamiliesByName := make(map[string]*dto.MetricFamily, len(r.dimHashesByName))
+
+ // Scatter.
+ // (Collectors could be complex and slow, so we call them all at once.)
+ wg.Add(len(r.collectorsByID))
+ go func() {
+ wg.Wait()
+ close(metricChan)
+ }()
+ for _, collector := range r.collectorsByID {
+ go func(collector Collector) {
+ defer wg.Done()
+ collector.Collect(metricChan)
+ }(collector)
+ }
+
+ // In case pedantic checks are enabled, we have to copy the map before
+ // giving up the RLock.
+ if r.pedanticChecksEnabled {
+ registeredDescIDs = make(map[uint64]struct{}, len(r.descIDs))
+ for id := range r.descIDs {
+ registeredDescIDs[id] = struct{}{}
+ }
+ }
+
+ r.mtx.RUnlock()
+
+ // Drain metricChan in case of premature return.
+ defer func() {
+ for _ = range metricChan {
+ }
+ }()
+
+ // Gather.
+ for metric := range metricChan {
+ // This could be done concurrently, too, but it required locking
+ // of metricFamiliesByName (and of metricHashes if checks are
+ // enabled). Most likely not worth it.
+ desc := metric.Desc()
+ dtoMetric := &dto.Metric{}
+ if err := metric.Write(dtoMetric); err != nil {
+ errs = append(errs, fmt.Errorf(
+ "error collecting metric %v: %s", desc, err,
+ ))
+ continue
+ }
+ metricFamily, ok := metricFamiliesByName[desc.fqName]
+ if ok {
+ if metricFamily.GetHelp() != desc.help {
+ errs = append(errs, fmt.Errorf(
+ "collected metric %s %s has help %q but should have %q",
+ desc.fqName, dtoMetric, desc.help, metricFamily.GetHelp(),
+ ))
+ continue
+ }
+ // TODO(beorn7): Simplify switch once Desc has type.
+ switch metricFamily.GetType() {
+ case dto.MetricType_COUNTER:
+ if dtoMetric.Counter == nil {
+ errs = append(errs, fmt.Errorf(
+ "collected metric %s %s should be a Counter",
+ desc.fqName, dtoMetric,
+ ))
+ continue
+ }
+ case dto.MetricType_GAUGE:
+ if dtoMetric.Gauge == nil {
+ errs = append(errs, fmt.Errorf(
+ "collected metric %s %s should be a Gauge",
+ desc.fqName, dtoMetric,
+ ))
+ continue
+ }
+ case dto.MetricType_SUMMARY:
+ if dtoMetric.Summary == nil {
+ errs = append(errs, fmt.Errorf(
+ "collected metric %s %s should be a Summary",
+ desc.fqName, dtoMetric,
+ ))
+ continue
+ }
+ case dto.MetricType_UNTYPED:
+ if dtoMetric.Untyped == nil {
+ errs = append(errs, fmt.Errorf(
+ "collected metric %s %s should be Untyped",
+ desc.fqName, dtoMetric,
+ ))
+ continue
+ }
+ case dto.MetricType_HISTOGRAM:
+ if dtoMetric.Histogram == nil {
+ errs = append(errs, fmt.Errorf(
+ "collected metric %s %s should be a Histogram",
+ desc.fqName, dtoMetric,
+ ))
+ continue
+ }
+ default:
+ panic("encountered MetricFamily with invalid type")
+ }
+ } else {
+ metricFamily = &dto.MetricFamily{}
+ metricFamily.Name = proto.String(desc.fqName)
+ metricFamily.Help = proto.String(desc.help)
+ // TODO(beorn7): Simplify switch once Desc has type.
+ switch {
+ case dtoMetric.Gauge != nil:
+ metricFamily.Type = dto.MetricType_GAUGE.Enum()
+ case dtoMetric.Counter != nil:
+ metricFamily.Type = dto.MetricType_COUNTER.Enum()
+ case dtoMetric.Summary != nil:
+ metricFamily.Type = dto.MetricType_SUMMARY.Enum()
+ case dtoMetric.Untyped != nil:
+ metricFamily.Type = dto.MetricType_UNTYPED.Enum()
+ case dtoMetric.Histogram != nil:
+ metricFamily.Type = dto.MetricType_HISTOGRAM.Enum()
+ default:
+ errs = append(errs, fmt.Errorf(
+ "empty metric collected: %s", dtoMetric,
+ ))
+ continue
+ }
+ metricFamiliesByName[desc.fqName] = metricFamily
+ }
+ if err := checkMetricConsistency(metricFamily, dtoMetric, metricHashes, dimHashes); err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ if r.pedanticChecksEnabled {
+ // Is the desc registered at all?
+ if _, exist := registeredDescIDs[desc.id]; !exist {
+ errs = append(errs, fmt.Errorf(
+ "collected metric %s %s with unregistered descriptor %s",
+ metricFamily.GetName(), dtoMetric, desc,
+ ))
+ continue
+ }
+ if err := checkDescConsistency(metricFamily, dtoMetric, desc); err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ }
+ metricFamily.Metric = append(metricFamily.Metric, dtoMetric)
+ }
+ return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
+}
+
+// Gatherers is a slice of Gatherer instances that implements the Gatherer
+// interface itself. Its Gather method calls Gather on all Gatherers in the
+// slice in order and returns the merged results. Errors returned from the
+// Gather calles are all returned in a flattened MultiError. Duplicate and
+// inconsistent Metrics are skipped (first occurrence in slice order wins) and
+// reported in the returned error.
+//
+// Gatherers can be used to merge the Gather results from multiple
+// Registries. It also provides a way to directly inject existing MetricFamily
+// protobufs into the gathering by creating a custom Gatherer with a Gather
+// method that simply returns the existing MetricFamily protobufs. Note that no
+// registration is involved (in contrast to Collector registration), so
+// obviously registration-time checks cannot happen. Any inconsistencies between
+// the gathered MetricFamilies are reported as errors by the Gather method, and
+// inconsistent Metrics are dropped. Invalid parts of the MetricFamilies
+// (e.g. syntactically invalid metric or label names) will go undetected.
+type Gatherers []Gatherer
+
+// Gather implements Gatherer.
+func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) {
+ var (
+ metricFamiliesByName = map[string]*dto.MetricFamily{}
+ metricHashes = map[uint64]struct{}{}
+ dimHashes = map[string]uint64{}
+ errs MultiError // The collected errors to return in the end.
+ )
+
+ for i, g := range gs {
+ mfs, err := g.Gather()
+ if err != nil {
+ if multiErr, ok := err.(MultiError); ok {
+ for _, err := range multiErr {
+ errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err))
+ }
+ } else {
+ errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err))
+ }
+ }
+ for _, mf := range mfs {
+ existingMF, exists := metricFamiliesByName[mf.GetName()]
+ if exists {
+ if existingMF.GetHelp() != mf.GetHelp() {
+ errs = append(errs, fmt.Errorf(
+ "gathered metric family %s has help %q but should have %q",
+ mf.GetName(), mf.GetHelp(), existingMF.GetHelp(),
+ ))
+ continue
+ }
+ if existingMF.GetType() != mf.GetType() {
+ errs = append(errs, fmt.Errorf(
+ "gathered metric family %s has type %s but should have %s",
+ mf.GetName(), mf.GetType(), existingMF.GetType(),
+ ))
+ continue
+ }
+ } else {
+ existingMF = &dto.MetricFamily{}
+ existingMF.Name = mf.Name
+ existingMF.Help = mf.Help
+ existingMF.Type = mf.Type
+ metricFamiliesByName[mf.GetName()] = existingMF
+ }
+ for _, m := range mf.Metric {
+ if err := checkMetricConsistency(existingMF, m, metricHashes, dimHashes); err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ existingMF.Metric = append(existingMF.Metric, m)
+ }
+ }
+ }
+ return normalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
+}
+
+// metricSorter is a sortable slice of *dto.Metric.
+type metricSorter []*dto.Metric
+
+func (s metricSorter) Len() int {
+ return len(s)
+}
+
+func (s metricSorter) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s metricSorter) Less(i, j int) bool {
+ if len(s[i].Label) != len(s[j].Label) {
+ // This should not happen. The metrics are
+ // inconsistent. However, we have to deal with the fact, as
+ // people might use custom collectors or metric family injection
+ // to create inconsistent metrics. So let's simply compare the
+ // number of labels in this case. That will still yield
+ // reproducible sorting.
+ return len(s[i].Label) < len(s[j].Label)
+ }
+ for n, lp := range s[i].Label {
+ vi := lp.GetValue()
+ vj := s[j].Label[n].GetValue()
+ if vi != vj {
+ return vi < vj
+ }
+ }
+
+ // We should never arrive here. Multiple metrics with the same
+ // label set in the same scrape will lead to undefined ingestion
+ // behavior. However, as above, we have to provide stable sorting
+ // here, even for inconsistent metrics. So sort equal metrics
+ // by their timestamp, with missing timestamps (implying "now")
+ // coming last.
+ if s[i].TimestampMs == nil {
+ return false
+ }
+ if s[j].TimestampMs == nil {
+ return true
+ }
+ return s[i].GetTimestampMs() < s[j].GetTimestampMs()
+}
+
+// normalizeMetricFamilies returns a MetricFamily slice whith empty
+// MetricFamilies pruned and the remaining MetricFamilies sorted by name within
+// the slice, with the contained Metrics sorted within each MetricFamily.
+func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily {
+ for _, mf := range metricFamiliesByName {
+ sort.Sort(metricSorter(mf.Metric))
+ }
+ names := make([]string, 0, len(metricFamiliesByName))
+ for name, mf := range metricFamiliesByName {
+ if len(mf.Metric) > 0 {
+ names = append(names, name)
+ }
+ }
+ sort.Strings(names)
+ result := make([]*dto.MetricFamily, 0, len(names))
+ for _, name := range names {
+ result = append(result, metricFamiliesByName[name])
+ }
+ return result
+}
+
+// checkMetricConsistency checks if the provided Metric is consistent with the
+// provided MetricFamily. It also hashed the Metric labels and the MetricFamily
+// name. If the resulting hash is alread in the provided metricHashes, an error
+// is returned. If not, it is added to metricHashes. The provided dimHashes maps
+// MetricFamily names to their dimHash (hashed sorted label names). If dimHashes
+// doesn't yet contain a hash for the provided MetricFamily, it is
+// added. Otherwise, an error is returned if the existing dimHashes in not equal
+// the calculated dimHash.
+func checkMetricConsistency(
+ metricFamily *dto.MetricFamily,
+ dtoMetric *dto.Metric,
+ metricHashes map[uint64]struct{},
+ dimHashes map[string]uint64,
+) error {
+ // Type consistency with metric family.
+ if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil ||
+ metricFamily.GetType() == dto.MetricType_COUNTER && dtoMetric.Counter == nil ||
+ metricFamily.GetType() == dto.MetricType_SUMMARY && dtoMetric.Summary == nil ||
+ metricFamily.GetType() == dto.MetricType_HISTOGRAM && dtoMetric.Histogram == nil ||
+ metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil {
+ return fmt.Errorf(
+ "collected metric %s %s is not a %s",
+ metricFamily.GetName(), dtoMetric, metricFamily.GetType(),
+ )
+ }
+
+ // Is the metric unique (i.e. no other metric with the same name and the same label values)?
+ h := hashNew()
+ h = hashAdd(h, metricFamily.GetName())
+ h = hashAddByte(h, separatorByte)
+ dh := hashNew()
+ // Make sure label pairs are sorted. We depend on it for the consistency
+ // check.
+ sort.Sort(LabelPairSorter(dtoMetric.Label))
+ for _, lp := range dtoMetric.Label {
+ h = hashAdd(h, lp.GetValue())
+ h = hashAddByte(h, separatorByte)
+ dh = hashAdd(dh, lp.GetName())
+ dh = hashAddByte(dh, separatorByte)
+ }
+ if _, exists := metricHashes[h]; exists {
+ return fmt.Errorf(
+ "collected metric %s %s was collected before with the same name and label values",
+ metricFamily.GetName(), dtoMetric,
+ )
+ }
+ if dimHash, ok := dimHashes[metricFamily.GetName()]; ok {
+ if dimHash != dh {
+ return fmt.Errorf(
+ "collected metric %s %s has label dimensions inconsistent with previously collected metrics in the same metric family",
+ metricFamily.GetName(), dtoMetric,
+ )
+ }
+ } else {
+ dimHashes[metricFamily.GetName()] = dh
+ }
+ metricHashes[h] = struct{}{}
+ return nil
+}
+
+func checkDescConsistency(
+ metricFamily *dto.MetricFamily,
+ dtoMetric *dto.Metric,
+ desc *Desc,
+) error {
+ // Desc help consistency with metric family help.
+ if metricFamily.GetHelp() != desc.help {
+ return fmt.Errorf(
+ "collected metric %s %s has help %q but should have %q",
+ metricFamily.GetName(), dtoMetric, metricFamily.GetHelp(), desc.help,
+ )
+ }
+
+ // Is the desc consistent with the content of the metric?
+ lpsFromDesc := make([]*dto.LabelPair, 0, len(dtoMetric.Label))
+ lpsFromDesc = append(lpsFromDesc, desc.constLabelPairs...)
+ for _, l := range desc.variableLabels {
+ lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{
+ Name: proto.String(l),
+ })
+ }
+ if len(lpsFromDesc) != len(dtoMetric.Label) {
+ return fmt.Errorf(
+ "labels in collected metric %s %s are inconsistent with descriptor %s",
+ metricFamily.GetName(), dtoMetric, desc,
+ )
+ }
+ sort.Sort(LabelPairSorter(lpsFromDesc))
+ for i, lpFromDesc := range lpsFromDesc {
+ lpFromMetric := dtoMetric.Label[i]
+ if lpFromDesc.GetName() != lpFromMetric.GetName() ||
+ lpFromDesc.Value != nil && lpFromDesc.GetValue() != lpFromMetric.GetValue() {
+ return fmt.Errorf(
+ "labels in collected metric %s %s are inconsistent with descriptor %s",
+ metricFamily.GetName(), dtoMetric, desc,
+ )
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go
new file mode 100644
index 00000000..bce05bf9
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go
@@ -0,0 +1,534 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "fmt"
+ "math"
+ "sort"
+ "sync"
+ "time"
+
+ "github.com/beorn7/perks/quantile"
+ "github.com/golang/protobuf/proto"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// quantileLabel is used for the label that defines the quantile in a
+// summary.
+const quantileLabel = "quantile"
+
+// A Summary captures individual observations from an event or sample stream and
+// summarizes them in a manner similar to traditional summary statistics: 1. sum
+// of observations, 2. observation count, 3. rank estimations.
+//
+// A typical use-case is the observation of request latencies. By default, a
+// Summary provides the median, the 90th and the 99th percentile of the latency
+// as rank estimations.
+//
+// Note that the rank estimations cannot be aggregated in a meaningful way with
+// the Prometheus query language (i.e. you cannot average or add them). If you
+// need aggregatable quantiles (e.g. you want the 99th percentile latency of all
+// queries served across all instances of a service), consider the Histogram
+// metric type. See the Prometheus documentation for more details.
+//
+// To create Summary instances, use NewSummary.
+type Summary interface {
+ Metric
+ Collector
+
+ // Observe adds a single observation to the summary.
+ Observe(float64)
+}
+
+// DefObjectives are the default Summary quantile values.
+var (
+ DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
+
+ errQuantileLabelNotAllowed = fmt.Errorf(
+ "%q is not allowed as label name in summaries", quantileLabel,
+ )
+)
+
+// Default values for SummaryOpts.
+const (
+ // DefMaxAge is the default duration for which observations stay
+ // relevant.
+ DefMaxAge time.Duration = 10 * time.Minute
+ // DefAgeBuckets is the default number of buckets used to calculate the
+ // age of observations.
+ DefAgeBuckets = 5
+ // DefBufCap is the standard buffer size for collecting Summary observations.
+ DefBufCap = 500
+)
+
+// SummaryOpts bundles the options for creating a Summary metric. It is
+// mandatory to set Name and Help to a non-empty string. All other fields are
+// optional and can safely be left at their zero value.
+type SummaryOpts struct {
+ // Namespace, Subsystem, and Name are components of the fully-qualified
+ // name of the Summary (created by joining these components with
+ // "_"). Only Name is mandatory, the others merely help structuring the
+ // name. Note that the fully-qualified name of the Summary must be a
+ // valid Prometheus metric name.
+ Namespace string
+ Subsystem string
+ Name string
+
+ // Help provides information about this Summary. Mandatory!
+ //
+ // Metrics with the same fully-qualified name must have the same Help
+ // string.
+ Help string
+
+ // ConstLabels are used to attach fixed labels to this
+ // Summary. Summaries with the same fully-qualified name must have the
+ // same label names in their ConstLabels.
+ //
+ // Note that in most cases, labels have a value that varies during the
+ // lifetime of a process. Those labels are usually managed with a
+ // SummaryVec. ConstLabels serve only special purposes. One is for the
+ // special case where the value of a label does not change during the
+ // lifetime of a process, e.g. if the revision of the running binary is
+ // put into a label. Another, more advanced purpose is if more than one
+ // Collector needs to collect Summaries with the same fully-qualified
+ // name. In that case, those Summaries must differ in the values of
+ // their ConstLabels. See the Collector examples.
+ //
+ // If the value of a label never changes (not even between binaries),
+ // that label most likely should not be a label at all (but part of the
+ // metric name).
+ ConstLabels Labels
+
+ // Objectives defines the quantile rank estimates with their respective
+ // absolute error. If Objectives[q] = e, then the value reported
+ // for q will be the φ-quantile value for some φ between q-e and q+e.
+ // The default value is DefObjectives.
+ Objectives map[float64]float64
+
+ // MaxAge defines the duration for which an observation stays relevant
+ // for the summary. Must be positive. The default value is DefMaxAge.
+ MaxAge time.Duration
+
+ // AgeBuckets is the number of buckets used to exclude observations that
+ // are older than MaxAge from the summary. A higher number has a
+ // resource penalty, so only increase it if the higher resolution is
+ // really required. For very high observation rates, you might want to
+ // reduce the number of age buckets. With only one age bucket, you will
+ // effectively see a complete reset of the summary each time MaxAge has
+ // passed. The default value is DefAgeBuckets.
+ AgeBuckets uint32
+
+ // BufCap defines the default sample stream buffer size. The default
+ // value of DefBufCap should suffice for most uses. If there is a need
+ // to increase the value, a multiple of 500 is recommended (because that
+ // is the internal buffer size of the underlying package
+ // "github.com/bmizerany/perks/quantile").
+ BufCap uint32
+}
+
+// Great fuck-up with the sliding-window decay algorithm... The Merge method of
+// perk/quantile is actually not working as advertised - and it might be
+// unfixable, as the underlying algorithm is apparently not capable of merging
+// summaries in the first place. To avoid using Merge, we are currently adding
+// observations to _each_ age bucket, i.e. the effort to add a sample is
+// essentially multiplied by the number of age buckets. When rotating age
+// buckets, we empty the previous head stream. On scrape time, we simply take
+// the quantiles from the head stream (no merging required). Result: More effort
+// on observation time, less effort on scrape time, which is exactly the
+// opposite of what we try to accomplish, but at least the results are correct.
+//
+// The quite elegant previous contraption to merge the age buckets efficiently
+// on scrape time (see code up commit 6b9530d72ea715f0ba612c0120e6e09fbf1d49d0)
+// can't be used anymore.
+
+// NewSummary creates a new Summary based on the provided SummaryOpts.
+func NewSummary(opts SummaryOpts) Summary {
+ return newSummary(
+ NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ),
+ opts,
+ )
+}
+
+func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
+ if len(desc.variableLabels) != len(labelValues) {
+ panic(errInconsistentCardinality)
+ }
+
+ for _, n := range desc.variableLabels {
+ if n == quantileLabel {
+ panic(errQuantileLabelNotAllowed)
+ }
+ }
+ for _, lp := range desc.constLabelPairs {
+ if lp.GetName() == quantileLabel {
+ panic(errQuantileLabelNotAllowed)
+ }
+ }
+
+ if len(opts.Objectives) == 0 {
+ opts.Objectives = DefObjectives
+ }
+
+ if opts.MaxAge < 0 {
+ panic(fmt.Errorf("illegal max age MaxAge=%v", opts.MaxAge))
+ }
+ if opts.MaxAge == 0 {
+ opts.MaxAge = DefMaxAge
+ }
+
+ if opts.AgeBuckets == 0 {
+ opts.AgeBuckets = DefAgeBuckets
+ }
+
+ if opts.BufCap == 0 {
+ opts.BufCap = DefBufCap
+ }
+
+ s := &summary{
+ desc: desc,
+
+ objectives: opts.Objectives,
+ sortedObjectives: make([]float64, 0, len(opts.Objectives)),
+
+ labelPairs: makeLabelPairs(desc, labelValues),
+
+ hotBuf: make([]float64, 0, opts.BufCap),
+ coldBuf: make([]float64, 0, opts.BufCap),
+ streamDuration: opts.MaxAge / time.Duration(opts.AgeBuckets),
+ }
+ s.headStreamExpTime = time.Now().Add(s.streamDuration)
+ s.hotBufExpTime = s.headStreamExpTime
+
+ for i := uint32(0); i < opts.AgeBuckets; i++ {
+ s.streams = append(s.streams, s.newStream())
+ }
+ s.headStream = s.streams[0]
+
+ for qu := range s.objectives {
+ s.sortedObjectives = append(s.sortedObjectives, qu)
+ }
+ sort.Float64s(s.sortedObjectives)
+
+ s.init(s) // Init self-collection.
+ return s
+}
+
+type summary struct {
+ selfCollector
+
+ bufMtx sync.Mutex // Protects hotBuf and hotBufExpTime.
+ mtx sync.Mutex // Protects every other moving part.
+ // Lock bufMtx before mtx if both are needed.
+
+ desc *Desc
+
+ objectives map[float64]float64
+ sortedObjectives []float64
+
+ labelPairs []*dto.LabelPair
+
+ sum float64
+ cnt uint64
+
+ hotBuf, coldBuf []float64
+
+ streams []*quantile.Stream
+ streamDuration time.Duration
+ headStream *quantile.Stream
+ headStreamIdx int
+ headStreamExpTime, hotBufExpTime time.Time
+}
+
+func (s *summary) Desc() *Desc {
+ return s.desc
+}
+
+func (s *summary) Observe(v float64) {
+ s.bufMtx.Lock()
+ defer s.bufMtx.Unlock()
+
+ now := time.Now()
+ if now.After(s.hotBufExpTime) {
+ s.asyncFlush(now)
+ }
+ s.hotBuf = append(s.hotBuf, v)
+ if len(s.hotBuf) == cap(s.hotBuf) {
+ s.asyncFlush(now)
+ }
+}
+
+func (s *summary) Write(out *dto.Metric) error {
+ sum := &dto.Summary{}
+ qs := make([]*dto.Quantile, 0, len(s.objectives))
+
+ s.bufMtx.Lock()
+ s.mtx.Lock()
+ // Swap bufs even if hotBuf is empty to set new hotBufExpTime.
+ s.swapBufs(time.Now())
+ s.bufMtx.Unlock()
+
+ s.flushColdBuf()
+ sum.SampleCount = proto.Uint64(s.cnt)
+ sum.SampleSum = proto.Float64(s.sum)
+
+ for _, rank := range s.sortedObjectives {
+ var q float64
+ if s.headStream.Count() == 0 {
+ q = math.NaN()
+ } else {
+ q = s.headStream.Query(rank)
+ }
+ qs = append(qs, &dto.Quantile{
+ Quantile: proto.Float64(rank),
+ Value: proto.Float64(q),
+ })
+ }
+
+ s.mtx.Unlock()
+
+ if len(qs) > 0 {
+ sort.Sort(quantSort(qs))
+ }
+ sum.Quantile = qs
+
+ out.Summary = sum
+ out.Label = s.labelPairs
+ return nil
+}
+
+func (s *summary) newStream() *quantile.Stream {
+ return quantile.NewTargeted(s.objectives)
+}
+
+// asyncFlush needs bufMtx locked.
+func (s *summary) asyncFlush(now time.Time) {
+ s.mtx.Lock()
+ s.swapBufs(now)
+
+ // Unblock the original goroutine that was responsible for the mutation
+ // that triggered the compaction. But hold onto the global non-buffer
+ // state mutex until the operation finishes.
+ go func() {
+ s.flushColdBuf()
+ s.mtx.Unlock()
+ }()
+}
+
+// rotateStreams needs mtx AND bufMtx locked.
+func (s *summary) maybeRotateStreams() {
+ for !s.hotBufExpTime.Equal(s.headStreamExpTime) {
+ s.headStream.Reset()
+ s.headStreamIdx++
+ if s.headStreamIdx >= len(s.streams) {
+ s.headStreamIdx = 0
+ }
+ s.headStream = s.streams[s.headStreamIdx]
+ s.headStreamExpTime = s.headStreamExpTime.Add(s.streamDuration)
+ }
+}
+
+// flushColdBuf needs mtx locked.
+func (s *summary) flushColdBuf() {
+ for _, v := range s.coldBuf {
+ for _, stream := range s.streams {
+ stream.Insert(v)
+ }
+ s.cnt++
+ s.sum += v
+ }
+ s.coldBuf = s.coldBuf[0:0]
+ s.maybeRotateStreams()
+}
+
+// swapBufs needs mtx AND bufMtx locked, coldBuf must be empty.
+func (s *summary) swapBufs(now time.Time) {
+ if len(s.coldBuf) != 0 {
+ panic("coldBuf is not empty")
+ }
+ s.hotBuf, s.coldBuf = s.coldBuf, s.hotBuf
+ // hotBuf is now empty and gets new expiration set.
+ for now.After(s.hotBufExpTime) {
+ s.hotBufExpTime = s.hotBufExpTime.Add(s.streamDuration)
+ }
+}
+
+type quantSort []*dto.Quantile
+
+func (s quantSort) Len() int {
+ return len(s)
+}
+
+func (s quantSort) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s quantSort) Less(i, j int) bool {
+ return s[i].GetQuantile() < s[j].GetQuantile()
+}
+
+// SummaryVec is a Collector that bundles a set of Summaries that all share the
+// same Desc, but have different values for their variable labels. This is used
+// if you want to count the same thing partitioned by various dimensions
+// (e.g. HTTP request latencies, partitioned by status code and method). Create
+// instances with NewSummaryVec.
+type SummaryVec struct {
+ *MetricVec
+}
+
+// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
+// partitioned by the given label names. At least one label name must be
+// provided.
+func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &SummaryVec{
+ MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ return newSummary(desc, opts, lvs...)
+ }),
+ }
+}
+
+// GetMetricWithLabelValues replaces the method of the same name in
+// MetricVec. The difference is that this method returns a Summary and not a
+// Metric so that no type conversion is required.
+func (m *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Summary, error) {
+ metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Summary), err
+ }
+ return nil, err
+}
+
+// GetMetricWith replaces the method of the same name in MetricVec. The
+// difference is that this method returns a Summary and not a Metric so that no
+// type conversion is required.
+func (m *SummaryVec) GetMetricWith(labels Labels) (Summary, error) {
+ metric, err := m.MetricVec.GetMetricWith(labels)
+ if metric != nil {
+ return metric.(Summary), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. By not returning an
+// error, WithLabelValues allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Observe(42.21)
+func (m *SummaryVec) WithLabelValues(lvs ...string) Summary {
+ return m.MetricVec.WithLabelValues(lvs...).(Summary)
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. By not returning an error, With allows shortcuts like
+// myVec.With(Labels{"code": "404", "method": "GET"}).Observe(42.21)
+func (m *SummaryVec) With(labels Labels) Summary {
+ return m.MetricVec.With(labels).(Summary)
+}
+
+type constSummary struct {
+ desc *Desc
+ count uint64
+ sum float64
+ quantiles map[float64]float64
+ labelPairs []*dto.LabelPair
+}
+
+func (s *constSummary) Desc() *Desc {
+ return s.desc
+}
+
+func (s *constSummary) Write(out *dto.Metric) error {
+ sum := &dto.Summary{}
+ qs := make([]*dto.Quantile, 0, len(s.quantiles))
+
+ sum.SampleCount = proto.Uint64(s.count)
+ sum.SampleSum = proto.Float64(s.sum)
+
+ for rank, q := range s.quantiles {
+ qs = append(qs, &dto.Quantile{
+ Quantile: proto.Float64(rank),
+ Value: proto.Float64(q),
+ })
+ }
+
+ if len(qs) > 0 {
+ sort.Sort(quantSort(qs))
+ }
+ sum.Quantile = qs
+
+ out.Summary = sum
+ out.Label = s.labelPairs
+
+ return nil
+}
+
+// NewConstSummary returns a metric representing a Prometheus summary with fixed
+// values for the count, sum, and quantiles. As those parameters cannot be
+// changed, the returned value does not implement the Summary interface (but
+// only the Metric interface). Users of this package will not have much use for
+// it in regular operations. However, when implementing custom Collectors, it is
+// useful as a throw-away metric that is generated on the fly to send it to
+// Prometheus in the Collect method.
+//
+// quantiles maps ranks to quantile values. For example, a median latency of
+// 0.23s and a 99th percentile latency of 0.56s would be expressed as:
+// map[float64]float64{0.5: 0.23, 0.99: 0.56}
+//
+// NewConstSummary returns an error if the length of labelValues is not
+// consistent with the variable labels in Desc.
+func NewConstSummary(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ quantiles map[float64]float64,
+ labelValues ...string,
+) (Metric, error) {
+ if len(desc.variableLabels) != len(labelValues) {
+ return nil, errInconsistentCardinality
+ }
+ return &constSummary{
+ desc: desc,
+ count: count,
+ sum: sum,
+ quantiles: quantiles,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }, nil
+}
+
+// MustNewConstSummary is a version of NewConstSummary that panics where
+// NewConstMetric would have returned an error.
+func MustNewConstSummary(
+ desc *Desc,
+ count uint64,
+ sum float64,
+ quantiles map[float64]float64,
+ labelValues ...string,
+) Metric {
+ m, err := NewConstSummary(desc, count, sum, quantiles, labelValues...)
+ if err != nil {
+ panic(err)
+ }
+ return m
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/untyped.go b/vendor/github.com/prometheus/client_golang/prometheus/untyped.go
new file mode 100644
index 00000000..5faf7e6e
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/untyped.go
@@ -0,0 +1,138 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+// Untyped is a Metric that represents a single numerical value that can
+// arbitrarily go up and down.
+//
+// An Untyped metric works the same as a Gauge. The only difference is that to
+// no type information is implied.
+//
+// To create Untyped instances, use NewUntyped.
+type Untyped interface {
+ Metric
+ Collector
+
+ // Set sets the Untyped metric to an arbitrary value.
+ Set(float64)
+ // Inc increments the Untyped metric by 1.
+ Inc()
+ // Dec decrements the Untyped metric by 1.
+ Dec()
+ // Add adds the given value to the Untyped metric. (The value can be
+ // negative, resulting in a decrease.)
+ Add(float64)
+ // Sub subtracts the given value from the Untyped metric. (The value can
+ // be negative, resulting in an increase.)
+ Sub(float64)
+}
+
+// UntypedOpts is an alias for Opts. See there for doc comments.
+type UntypedOpts Opts
+
+// NewUntyped creates a new Untyped metric from the provided UntypedOpts.
+func NewUntyped(opts UntypedOpts) Untyped {
+ return newValue(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), UntypedValue, 0)
+}
+
+// UntypedVec is a Collector that bundles a set of Untyped metrics that all
+// share the same Desc, but have different values for their variable
+// labels. This is used if you want to count the same thing partitioned by
+// various dimensions. Create instances with NewUntypedVec.
+type UntypedVec struct {
+ *MetricVec
+}
+
+// NewUntypedVec creates a new UntypedVec based on the provided UntypedOpts and
+// partitioned by the given label names. At least one label name must be
+// provided.
+func NewUntypedVec(opts UntypedOpts, labelNames []string) *UntypedVec {
+ desc := NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ labelNames,
+ opts.ConstLabels,
+ )
+ return &UntypedVec{
+ MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
+ return newValue(desc, UntypedValue, 0, lvs...)
+ }),
+ }
+}
+
+// GetMetricWithLabelValues replaces the method of the same name in
+// MetricVec. The difference is that this method returns an Untyped and not a
+// Metric so that no type conversion is required.
+func (m *UntypedVec) GetMetricWithLabelValues(lvs ...string) (Untyped, error) {
+ metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...)
+ if metric != nil {
+ return metric.(Untyped), err
+ }
+ return nil, err
+}
+
+// GetMetricWith replaces the method of the same name in MetricVec. The
+// difference is that this method returns an Untyped and not a Metric so that no
+// type conversion is required.
+func (m *UntypedVec) GetMetricWith(labels Labels) (Untyped, error) {
+ metric, err := m.MetricVec.GetMetricWith(labels)
+ if metric != nil {
+ return metric.(Untyped), err
+ }
+ return nil, err
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics where
+// GetMetricWithLabelValues would have returned an error. By not returning an
+// error, WithLabelValues allows shortcuts like
+// myVec.WithLabelValues("404", "GET").Add(42)
+func (m *UntypedVec) WithLabelValues(lvs ...string) Untyped {
+ return m.MetricVec.WithLabelValues(lvs...).(Untyped)
+}
+
+// With works as GetMetricWith, but panics where GetMetricWithLabels would have
+// returned an error. By not returning an error, With allows shortcuts like
+// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
+func (m *UntypedVec) With(labels Labels) Untyped {
+ return m.MetricVec.With(labels).(Untyped)
+}
+
+// UntypedFunc is an Untyped whose value is determined at collect time by
+// calling a provided function.
+//
+// To create UntypedFunc instances, use NewUntypedFunc.
+type UntypedFunc interface {
+ Metric
+ Collector
+}
+
+// NewUntypedFunc creates a new UntypedFunc based on the provided
+// UntypedOpts. The value reported is determined by calling the given function
+// from within the Write method. Take into account that metric collection may
+// happen concurrently. If that results in concurrent calls to Write, like in
+// the case where an UntypedFunc is directly registered with Prometheus, the
+// provided function must be concurrency-safe.
+func NewUntypedFunc(opts UntypedOpts, function func() float64) UntypedFunc {
+ return newValueFunc(NewDesc(
+ BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
+ opts.Help,
+ nil,
+ opts.ConstLabels,
+ ), UntypedValue, function)
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/value.go b/vendor/github.com/prometheus/client_golang/prometheus/value.go
new file mode 100644
index 00000000..a944c377
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/value.go
@@ -0,0 +1,234 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "errors"
+ "fmt"
+ "math"
+ "sort"
+ "sync/atomic"
+
+ dto "github.com/prometheus/client_model/go"
+
+ "github.com/golang/protobuf/proto"
+)
+
+// ValueType is an enumeration of metric types that represent a simple value.
+type ValueType int
+
+// Possible values for the ValueType enum.
+const (
+ _ ValueType = iota
+ CounterValue
+ GaugeValue
+ UntypedValue
+)
+
+var errInconsistentCardinality = errors.New("inconsistent label cardinality")
+
+// value is a generic metric for simple values. It implements Metric, Collector,
+// Counter, Gauge, and Untyped. Its effective type is determined by
+// ValueType. This is a low-level building block used by the library to back the
+// implementations of Counter, Gauge, and Untyped.
+type value struct {
+ // valBits containst the bits of the represented float64 value. It has
+ // to go first in the struct to guarantee alignment for atomic
+ // operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
+ valBits uint64
+
+ selfCollector
+
+ desc *Desc
+ valType ValueType
+ labelPairs []*dto.LabelPair
+}
+
+// newValue returns a newly allocated value with the given Desc, ValueType,
+// sample value and label values. It panics if the number of label
+// values is different from the number of variable labels in Desc.
+func newValue(desc *Desc, valueType ValueType, val float64, labelValues ...string) *value {
+ if len(labelValues) != len(desc.variableLabels) {
+ panic(errInconsistentCardinality)
+ }
+ result := &value{
+ desc: desc,
+ valType: valueType,
+ valBits: math.Float64bits(val),
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }
+ result.init(result)
+ return result
+}
+
+func (v *value) Desc() *Desc {
+ return v.desc
+}
+
+func (v *value) Set(val float64) {
+ atomic.StoreUint64(&v.valBits, math.Float64bits(val))
+}
+
+func (v *value) Inc() {
+ v.Add(1)
+}
+
+func (v *value) Dec() {
+ v.Add(-1)
+}
+
+func (v *value) Add(val float64) {
+ for {
+ oldBits := atomic.LoadUint64(&v.valBits)
+ newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
+ if atomic.CompareAndSwapUint64(&v.valBits, oldBits, newBits) {
+ return
+ }
+ }
+}
+
+func (v *value) Sub(val float64) {
+ v.Add(val * -1)
+}
+
+func (v *value) Write(out *dto.Metric) error {
+ val := math.Float64frombits(atomic.LoadUint64(&v.valBits))
+ return populateMetric(v.valType, val, v.labelPairs, out)
+}
+
+// valueFunc is a generic metric for simple values retrieved on collect time
+// from a function. It implements Metric and Collector. Its effective type is
+// determined by ValueType. This is a low-level building block used by the
+// library to back the implementations of CounterFunc, GaugeFunc, and
+// UntypedFunc.
+type valueFunc struct {
+ selfCollector
+
+ desc *Desc
+ valType ValueType
+ function func() float64
+ labelPairs []*dto.LabelPair
+}
+
+// newValueFunc returns a newly allocated valueFunc with the given Desc and
+// ValueType. The value reported is determined by calling the given function
+// from within the Write method. Take into account that metric collection may
+// happen concurrently. If that results in concurrent calls to Write, like in
+// the case where a valueFunc is directly registered with Prometheus, the
+// provided function must be concurrency-safe.
+func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *valueFunc {
+ result := &valueFunc{
+ desc: desc,
+ valType: valueType,
+ function: function,
+ labelPairs: makeLabelPairs(desc, nil),
+ }
+ result.init(result)
+ return result
+}
+
+func (v *valueFunc) Desc() *Desc {
+ return v.desc
+}
+
+func (v *valueFunc) Write(out *dto.Metric) error {
+ return populateMetric(v.valType, v.function(), v.labelPairs, out)
+}
+
+// NewConstMetric returns a metric with one fixed value that cannot be
+// changed. Users of this package will not have much use for it in regular
+// operations. However, when implementing custom Collectors, it is useful as a
+// throw-away metric that is generated on the fly to send it to Prometheus in
+// the Collect method. NewConstMetric returns an error if the length of
+// labelValues is not consistent with the variable labels in Desc.
+func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) {
+ if len(desc.variableLabels) != len(labelValues) {
+ return nil, errInconsistentCardinality
+ }
+ return &constMetric{
+ desc: desc,
+ valType: valueType,
+ val: value,
+ labelPairs: makeLabelPairs(desc, labelValues),
+ }, nil
+}
+
+// MustNewConstMetric is a version of NewConstMetric that panics where
+// NewConstMetric would have returned an error.
+func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric {
+ m, err := NewConstMetric(desc, valueType, value, labelValues...)
+ if err != nil {
+ panic(err)
+ }
+ return m
+}
+
+type constMetric struct {
+ desc *Desc
+ valType ValueType
+ val float64
+ labelPairs []*dto.LabelPair
+}
+
+func (m *constMetric) Desc() *Desc {
+ return m.desc
+}
+
+func (m *constMetric) Write(out *dto.Metric) error {
+ return populateMetric(m.valType, m.val, m.labelPairs, out)
+}
+
+func populateMetric(
+ t ValueType,
+ v float64,
+ labelPairs []*dto.LabelPair,
+ m *dto.Metric,
+) error {
+ m.Label = labelPairs
+ switch t {
+ case CounterValue:
+ m.Counter = &dto.Counter{Value: proto.Float64(v)}
+ case GaugeValue:
+ m.Gauge = &dto.Gauge{Value: proto.Float64(v)}
+ case UntypedValue:
+ m.Untyped = &dto.Untyped{Value: proto.Float64(v)}
+ default:
+ return fmt.Errorf("encountered unknown type %v", t)
+ }
+ return nil
+}
+
+func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
+ totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
+ if totalLen == 0 {
+ // Super fast path.
+ return nil
+ }
+ if len(desc.variableLabels) == 0 {
+ // Moderately fast path.
+ return desc.constLabelPairs
+ }
+ labelPairs := make([]*dto.LabelPair, 0, totalLen)
+ for i, n := range desc.variableLabels {
+ labelPairs = append(labelPairs, &dto.LabelPair{
+ Name: proto.String(n),
+ Value: proto.String(labelValues[i]),
+ })
+ }
+ for _, lp := range desc.constLabelPairs {
+ labelPairs = append(labelPairs, lp)
+ }
+ sort.Sort(LabelPairSorter(labelPairs))
+ return labelPairs
+}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go
new file mode 100644
index 00000000..7f3eef9a
--- /dev/null
+++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go
@@ -0,0 +1,404 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package prometheus
+
+import (
+ "fmt"
+ "sync"
+
+ "github.com/prometheus/common/model"
+)
+
+// MetricVec is a Collector to bundle metrics of the same name that
+// differ in their label values. MetricVec is usually not used directly but as a
+// building block for implementations of vectors of a given metric
+// type. GaugeVec, CounterVec, SummaryVec, and UntypedVec are examples already
+// provided in this package.
+type MetricVec struct {
+ mtx sync.RWMutex // Protects the children.
+ children map[uint64][]metricWithLabelValues
+ desc *Desc
+
+ newMetric func(labelValues ...string) Metric
+ hashAdd func(h uint64, s string) uint64 // replace hash function for testing collision handling
+ hashAddByte func(h uint64, b byte) uint64
+}
+
+// newMetricVec returns an initialized MetricVec. The concrete value is
+// returned for embedding into another struct.
+func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
+ return &MetricVec{
+ children: map[uint64][]metricWithLabelValues{},
+ desc: desc,
+ newMetric: newMetric,
+ hashAdd: hashAdd,
+ hashAddByte: hashAddByte,
+ }
+}
+
+// metricWithLabelValues provides the metric and its label values for
+// disambiguation on hash collision.
+type metricWithLabelValues struct {
+ values []string
+ metric Metric
+}
+
+// Describe implements Collector. The length of the returned slice
+// is always one.
+func (m *MetricVec) Describe(ch chan<- *Desc) {
+ ch <- m.desc
+}
+
+// Collect implements Collector.
+func (m *MetricVec) Collect(ch chan<- Metric) {
+ m.mtx.RLock()
+ defer m.mtx.RUnlock()
+
+ for _, metrics := range m.children {
+ for _, metric := range metrics {
+ ch <- metric.metric
+ }
+ }
+}
+
+// GetMetricWithLabelValues returns the Metric for the given slice of label
+// values (same order as the VariableLabels in Desc). If that combination of
+// label values is accessed for the first time, a new Metric is created.
+//
+// It is possible to call this method without using the returned Metric to only
+// create the new Metric but leave it at its start value (e.g. a Summary or
+// Histogram without any observations). See also the SummaryVec example.
+//
+// Keeping the Metric for later use is possible (and should be considered if
+// performance is critical), but keep in mind that Reset, DeleteLabelValues and
+// Delete can be used to delete the Metric from the MetricVec. In that case, the
+// Metric will still exist, but it will not be exported anymore, even if a
+// Metric with the same label values is created later. See also the CounterVec
+// example.
+//
+// An error is returned if the number of label values is not the same as the
+// number of VariableLabels in Desc.
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
+// an alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+// See also the GaugeVec example.
+func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
+ h, err := m.hashLabelValues(lvs)
+ if err != nil {
+ return nil, err
+ }
+
+ return m.getOrCreateMetricWithLabelValues(h, lvs), nil
+}
+
+// GetMetricWith returns the Metric for the given Labels map (the label names
+// must match those of the VariableLabels in Desc). If that label map is
+// accessed for the first time, a new Metric is created. Implications of
+// creating a Metric without using it and keeping the Metric for later use are
+// the same as for GetMetricWithLabelValues.
+//
+// An error is returned if the number and names of the Labels are inconsistent
+// with those of the VariableLabels in Desc.
+//
+// This method is used for the same purpose as
+// GetMetricWithLabelValues(...string). See there for pros and cons of the two
+// methods.
+func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
+ h, err := m.hashLabels(labels)
+ if err != nil {
+ return nil, err
+ }
+
+ return m.getOrCreateMetricWithLabels(h, labels), nil
+}
+
+// WithLabelValues works as GetMetricWithLabelValues, but panics if an error
+// occurs. The method allows neat syntax like:
+// httpReqs.WithLabelValues("404", "POST").Inc()
+func (m *MetricVec) WithLabelValues(lvs ...string) Metric {
+ metric, err := m.GetMetricWithLabelValues(lvs...)
+ if err != nil {
+ panic(err)
+ }
+ return metric
+}
+
+// With works as GetMetricWith, but panics if an error occurs. The method allows
+// neat syntax like:
+// httpReqs.With(Labels{"status":"404", "method":"POST"}).Inc()
+func (m *MetricVec) With(labels Labels) Metric {
+ metric, err := m.GetMetricWith(labels)
+ if err != nil {
+ panic(err)
+ }
+ return metric
+}
+
+// DeleteLabelValues removes the metric where the variable labels are the same
+// as those passed in as labels (same order as the VariableLabels in Desc). It
+// returns true if a metric was deleted.
+//
+// It is not an error if the number of label values is not the same as the
+// number of VariableLabels in Desc. However, such inconsistent label count can
+// never match an actual Metric, so the method will always return false in that
+// case.
+//
+// Note that for more than one label value, this method is prone to mistakes
+// caused by an incorrect order of arguments. Consider Delete(Labels) as an
+// alternative to avoid that type of mistake. For higher label numbers, the
+// latter has a much more readable (albeit more verbose) syntax, but it comes
+// with a performance overhead (for creating and processing the Labels map).
+// See also the CounterVec example.
+func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+
+ h, err := m.hashLabelValues(lvs)
+ if err != nil {
+ return false
+ }
+ return m.deleteByHashWithLabelValues(h, lvs)
+}
+
+// Delete deletes the metric where the variable labels are the same as those
+// passed in as labels. It returns true if a metric was deleted.
+//
+// It is not an error if the number and names of the Labels are inconsistent
+// with those of the VariableLabels in the Desc of the MetricVec. However, such
+// inconsistent Labels can never match an actual Metric, so the method will
+// always return false in that case.
+//
+// This method is used for the same purpose as DeleteLabelValues(...string). See
+// there for pros and cons of the two methods.
+func (m *MetricVec) Delete(labels Labels) bool {
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+
+ h, err := m.hashLabels(labels)
+ if err != nil {
+ return false
+ }
+
+ return m.deleteByHashWithLabels(h, labels)
+}
+
+// deleteByHashWithLabelValues removes the metric from the hash bucket h. If
+// there are multiple matches in the bucket, use lvs to select a metric and
+// remove only that metric.
+func (m *MetricVec) deleteByHashWithLabelValues(h uint64, lvs []string) bool {
+ metrics, ok := m.children[h]
+ if !ok {
+ return false
+ }
+
+ i := m.findMetricWithLabelValues(metrics, lvs)
+ if i >= len(metrics) {
+ return false
+ }
+
+ if len(metrics) > 1 {
+ m.children[h] = append(metrics[:i], metrics[i+1:]...)
+ } else {
+ delete(m.children, h)
+ }
+ return true
+}
+
+// deleteByHashWithLabels removes the metric from the hash bucket h. If there
+// are multiple matches in the bucket, use lvs to select a metric and remove
+// only that metric.
+func (m *MetricVec) deleteByHashWithLabels(h uint64, labels Labels) bool {
+ metrics, ok := m.children[h]
+ if !ok {
+ return false
+ }
+ i := m.findMetricWithLabels(metrics, labels)
+ if i >= len(metrics) {
+ return false
+ }
+
+ if len(metrics) > 1 {
+ m.children[h] = append(metrics[:i], metrics[i+1:]...)
+ } else {
+ delete(m.children, h)
+ }
+ return true
+}
+
+// Reset deletes all metrics in this vector.
+func (m *MetricVec) Reset() {
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+
+ for h := range m.children {
+ delete(m.children, h)
+ }
+}
+
+func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
+ if len(vals) != len(m.desc.variableLabels) {
+ return 0, errInconsistentCardinality
+ }
+ h := hashNew()
+ for _, val := range vals {
+ h = m.hashAdd(h, val)
+ h = m.hashAddByte(h, model.SeparatorByte)
+ }
+ return h, nil
+}
+
+func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
+ if len(labels) != len(m.desc.variableLabels) {
+ return 0, errInconsistentCardinality
+ }
+ h := hashNew()
+ for _, label := range m.desc.variableLabels {
+ val, ok := labels[label]
+ if !ok {
+ return 0, fmt.Errorf("label name %q missing in label map", label)
+ }
+ h = m.hashAdd(h, val)
+ h = m.hashAddByte(h, model.SeparatorByte)
+ }
+ return h, nil
+}
+
+// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
+// or creates it and returns the new one.
+//
+// This function holds the mutex.
+func (m *MetricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string) Metric {
+ m.mtx.RLock()
+ metric, ok := m.getMetricWithLabelValues(hash, lvs)
+ m.mtx.RUnlock()
+ if ok {
+ return metric
+ }
+
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+ metric, ok = m.getMetricWithLabelValues(hash, lvs)
+ if !ok {
+ // Copy to avoid allocation in case wo don't go down this code path.
+ copiedLVs := make([]string, len(lvs))
+ copy(copiedLVs, lvs)
+ metric = m.newMetric(copiedLVs...)
+ m.children[hash] = append(m.children[hash], metricWithLabelValues{values: copiedLVs, metric: metric})
+ }
+ return metric
+}
+
+// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
+// or creates it and returns the new one.
+//
+// This function holds the mutex.
+func (m *MetricVec) getOrCreateMetricWithLabels(hash uint64, labels Labels) Metric {
+ m.mtx.RLock()
+ metric, ok := m.getMetricWithLabels(hash, labels)
+ m.mtx.RUnlock()
+ if ok {
+ return metric
+ }
+
+ m.mtx.Lock()
+ defer m.mtx.Unlock()
+ metric, ok = m.getMetricWithLabels(hash, labels)
+ if !ok {
+ lvs := m.extractLabelValues(labels)
+ metric = m.newMetric(lvs...)
+ m.children[hash] = append(m.children[hash], metricWithLabelValues{values: lvs, metric: metric})
+ }
+ return metric
+}
+
+// getMetricWithLabelValues gets a metric while handling possible collisions in
+// the hash space. Must be called while holding read mutex.
+func (m *MetricVec) getMetricWithLabelValues(h uint64, lvs []string) (Metric, bool) {
+ metrics, ok := m.children[h]
+ if ok {
+ if i := m.findMetricWithLabelValues(metrics, lvs); i < len(metrics) {
+ return metrics[i].metric, true
+ }
+ }
+ return nil, false
+}
+
+// getMetricWithLabels gets a metric while handling possible collisions in
+// the hash space. Must be called while holding read mutex.
+func (m *MetricVec) getMetricWithLabels(h uint64, labels Labels) (Metric, bool) {
+ metrics, ok := m.children[h]
+ if ok {
+ if i := m.findMetricWithLabels(metrics, labels); i < len(metrics) {
+ return metrics[i].metric, true
+ }
+ }
+ return nil, false
+}
+
+// findMetricWithLabelValues returns the index of the matching metric or
+// len(metrics) if not found.
+func (m *MetricVec) findMetricWithLabelValues(metrics []metricWithLabelValues, lvs []string) int {
+ for i, metric := range metrics {
+ if m.matchLabelValues(metric.values, lvs) {
+ return i
+ }
+ }
+ return len(metrics)
+}
+
+// findMetricWithLabels returns the index of the matching metric or len(metrics)
+// if not found.
+func (m *MetricVec) findMetricWithLabels(metrics []metricWithLabelValues, labels Labels) int {
+ for i, metric := range metrics {
+ if m.matchLabels(metric.values, labels) {
+ return i
+ }
+ }
+ return len(metrics)
+}
+
+func (m *MetricVec) matchLabelValues(values []string, lvs []string) bool {
+ if len(values) != len(lvs) {
+ return false
+ }
+ for i, v := range values {
+ if v != lvs[i] {
+ return false
+ }
+ }
+ return true
+}
+
+func (m *MetricVec) matchLabels(values []string, labels Labels) bool {
+ if len(labels) != len(values) {
+ return false
+ }
+ for i, k := range m.desc.variableLabels {
+ if values[i] != labels[k] {
+ return false
+ }
+ }
+ return true
+}
+
+func (m *MetricVec) extractLabelValues(labels Labels) []string {
+ labelValues := make([]string, len(labels))
+ for i, k := range m.desc.variableLabels {
+ labelValues[i] = labels[k]
+ }
+ return labelValues
+}
diff --git a/vendor/github.com/prometheus/client_model/LICENSE b/vendor/github.com/prometheus/client_model/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/vendor/github.com/prometheus/client_model/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/prometheus/client_model/NOTICE b/vendor/github.com/prometheus/client_model/NOTICE
new file mode 100644
index 00000000..20110e41
--- /dev/null
+++ b/vendor/github.com/prometheus/client_model/NOTICE
@@ -0,0 +1,5 @@
+Data model artifacts for Prometheus.
+Copyright 2012-2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
diff --git a/vendor/github.com/prometheus/client_model/go/metrics.pb.go b/vendor/github.com/prometheus/client_model/go/metrics.pb.go
new file mode 100644
index 00000000..9805432c
--- /dev/null
+++ b/vendor/github.com/prometheus/client_model/go/metrics.pb.go
@@ -0,0 +1,629 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: metrics.proto
+
+package io_prometheus_client // import "github.com/prometheus/client_model/go"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type MetricType int32
+
+const (
+ MetricType_COUNTER MetricType = 0
+ MetricType_GAUGE MetricType = 1
+ MetricType_SUMMARY MetricType = 2
+ MetricType_UNTYPED MetricType = 3
+ MetricType_HISTOGRAM MetricType = 4
+)
+
+var MetricType_name = map[int32]string{
+ 0: "COUNTER",
+ 1: "GAUGE",
+ 2: "SUMMARY",
+ 3: "UNTYPED",
+ 4: "HISTOGRAM",
+}
+var MetricType_value = map[string]int32{
+ "COUNTER": 0,
+ "GAUGE": 1,
+ "SUMMARY": 2,
+ "UNTYPED": 3,
+ "HISTOGRAM": 4,
+}
+
+func (x MetricType) Enum() *MetricType {
+ p := new(MetricType)
+ *p = x
+ return p
+}
+func (x MetricType) String() string {
+ return proto.EnumName(MetricType_name, int32(x))
+}
+func (x *MetricType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MetricType_value, data, "MetricType")
+ if err != nil {
+ return err
+ }
+ *x = MetricType(value)
+ return nil
+}
+func (MetricType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{0}
+}
+
+type LabelPair struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *LabelPair) Reset() { *m = LabelPair{} }
+func (m *LabelPair) String() string { return proto.CompactTextString(m) }
+func (*LabelPair) ProtoMessage() {}
+func (*LabelPair) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{0}
+}
+func (m *LabelPair) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_LabelPair.Unmarshal(m, b)
+}
+func (m *LabelPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_LabelPair.Marshal(b, m, deterministic)
+}
+func (dst *LabelPair) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_LabelPair.Merge(dst, src)
+}
+func (m *LabelPair) XXX_Size() int {
+ return xxx_messageInfo_LabelPair.Size(m)
+}
+func (m *LabelPair) XXX_DiscardUnknown() {
+ xxx_messageInfo_LabelPair.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LabelPair proto.InternalMessageInfo
+
+func (m *LabelPair) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *LabelPair) GetValue() string {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return ""
+}
+
+type Gauge struct {
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Gauge) Reset() { *m = Gauge{} }
+func (m *Gauge) String() string { return proto.CompactTextString(m) }
+func (*Gauge) ProtoMessage() {}
+func (*Gauge) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{1}
+}
+func (m *Gauge) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Gauge.Unmarshal(m, b)
+}
+func (m *Gauge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Gauge.Marshal(b, m, deterministic)
+}
+func (dst *Gauge) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Gauge.Merge(dst, src)
+}
+func (m *Gauge) XXX_Size() int {
+ return xxx_messageInfo_Gauge.Size(m)
+}
+func (m *Gauge) XXX_DiscardUnknown() {
+ xxx_messageInfo_Gauge.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Gauge proto.InternalMessageInfo
+
+func (m *Gauge) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Counter struct {
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Counter) Reset() { *m = Counter{} }
+func (m *Counter) String() string { return proto.CompactTextString(m) }
+func (*Counter) ProtoMessage() {}
+func (*Counter) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{2}
+}
+func (m *Counter) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Counter.Unmarshal(m, b)
+}
+func (m *Counter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Counter.Marshal(b, m, deterministic)
+}
+func (dst *Counter) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Counter.Merge(dst, src)
+}
+func (m *Counter) XXX_Size() int {
+ return xxx_messageInfo_Counter.Size(m)
+}
+func (m *Counter) XXX_DiscardUnknown() {
+ xxx_messageInfo_Counter.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Counter proto.InternalMessageInfo
+
+func (m *Counter) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Quantile struct {
+ Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"`
+ Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Quantile) Reset() { *m = Quantile{} }
+func (m *Quantile) String() string { return proto.CompactTextString(m) }
+func (*Quantile) ProtoMessage() {}
+func (*Quantile) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{3}
+}
+func (m *Quantile) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Quantile.Unmarshal(m, b)
+}
+func (m *Quantile) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Quantile.Marshal(b, m, deterministic)
+}
+func (dst *Quantile) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Quantile.Merge(dst, src)
+}
+func (m *Quantile) XXX_Size() int {
+ return xxx_messageInfo_Quantile.Size(m)
+}
+func (m *Quantile) XXX_DiscardUnknown() {
+ xxx_messageInfo_Quantile.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Quantile proto.InternalMessageInfo
+
+func (m *Quantile) GetQuantile() float64 {
+ if m != nil && m.Quantile != nil {
+ return *m.Quantile
+ }
+ return 0
+}
+
+func (m *Quantile) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Summary struct {
+ SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"`
+ SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"`
+ Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Summary) Reset() { *m = Summary{} }
+func (m *Summary) String() string { return proto.CompactTextString(m) }
+func (*Summary) ProtoMessage() {}
+func (*Summary) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{4}
+}
+func (m *Summary) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Summary.Unmarshal(m, b)
+}
+func (m *Summary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Summary.Marshal(b, m, deterministic)
+}
+func (dst *Summary) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Summary.Merge(dst, src)
+}
+func (m *Summary) XXX_Size() int {
+ return xxx_messageInfo_Summary.Size(m)
+}
+func (m *Summary) XXX_DiscardUnknown() {
+ xxx_messageInfo_Summary.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Summary proto.InternalMessageInfo
+
+func (m *Summary) GetSampleCount() uint64 {
+ if m != nil && m.SampleCount != nil {
+ return *m.SampleCount
+ }
+ return 0
+}
+
+func (m *Summary) GetSampleSum() float64 {
+ if m != nil && m.SampleSum != nil {
+ return *m.SampleSum
+ }
+ return 0
+}
+
+func (m *Summary) GetQuantile() []*Quantile {
+ if m != nil {
+ return m.Quantile
+ }
+ return nil
+}
+
+type Untyped struct {
+ Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Untyped) Reset() { *m = Untyped{} }
+func (m *Untyped) String() string { return proto.CompactTextString(m) }
+func (*Untyped) ProtoMessage() {}
+func (*Untyped) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{5}
+}
+func (m *Untyped) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Untyped.Unmarshal(m, b)
+}
+func (m *Untyped) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Untyped.Marshal(b, m, deterministic)
+}
+func (dst *Untyped) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Untyped.Merge(dst, src)
+}
+func (m *Untyped) XXX_Size() int {
+ return xxx_messageInfo_Untyped.Size(m)
+}
+func (m *Untyped) XXX_DiscardUnknown() {
+ xxx_messageInfo_Untyped.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Untyped proto.InternalMessageInfo
+
+func (m *Untyped) GetValue() float64 {
+ if m != nil && m.Value != nil {
+ return *m.Value
+ }
+ return 0
+}
+
+type Histogram struct {
+ SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"`
+ SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"`
+ Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Histogram) Reset() { *m = Histogram{} }
+func (m *Histogram) String() string { return proto.CompactTextString(m) }
+func (*Histogram) ProtoMessage() {}
+func (*Histogram) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{6}
+}
+func (m *Histogram) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Histogram.Unmarshal(m, b)
+}
+func (m *Histogram) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Histogram.Marshal(b, m, deterministic)
+}
+func (dst *Histogram) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Histogram.Merge(dst, src)
+}
+func (m *Histogram) XXX_Size() int {
+ return xxx_messageInfo_Histogram.Size(m)
+}
+func (m *Histogram) XXX_DiscardUnknown() {
+ xxx_messageInfo_Histogram.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Histogram proto.InternalMessageInfo
+
+func (m *Histogram) GetSampleCount() uint64 {
+ if m != nil && m.SampleCount != nil {
+ return *m.SampleCount
+ }
+ return 0
+}
+
+func (m *Histogram) GetSampleSum() float64 {
+ if m != nil && m.SampleSum != nil {
+ return *m.SampleSum
+ }
+ return 0
+}
+
+func (m *Histogram) GetBucket() []*Bucket {
+ if m != nil {
+ return m.Bucket
+ }
+ return nil
+}
+
+type Bucket struct {
+ CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"`
+ UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Bucket) Reset() { *m = Bucket{} }
+func (m *Bucket) String() string { return proto.CompactTextString(m) }
+func (*Bucket) ProtoMessage() {}
+func (*Bucket) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{7}
+}
+func (m *Bucket) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Bucket.Unmarshal(m, b)
+}
+func (m *Bucket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Bucket.Marshal(b, m, deterministic)
+}
+func (dst *Bucket) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Bucket.Merge(dst, src)
+}
+func (m *Bucket) XXX_Size() int {
+ return xxx_messageInfo_Bucket.Size(m)
+}
+func (m *Bucket) XXX_DiscardUnknown() {
+ xxx_messageInfo_Bucket.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Bucket proto.InternalMessageInfo
+
+func (m *Bucket) GetCumulativeCount() uint64 {
+ if m != nil && m.CumulativeCount != nil {
+ return *m.CumulativeCount
+ }
+ return 0
+}
+
+func (m *Bucket) GetUpperBound() float64 {
+ if m != nil && m.UpperBound != nil {
+ return *m.UpperBound
+ }
+ return 0
+}
+
+type Metric struct {
+ Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"`
+ Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"`
+ Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"`
+ Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"`
+ Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"`
+ Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"`
+ TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Metric) Reset() { *m = Metric{} }
+func (m *Metric) String() string { return proto.CompactTextString(m) }
+func (*Metric) ProtoMessage() {}
+func (*Metric) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{8}
+}
+func (m *Metric) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Metric.Unmarshal(m, b)
+}
+func (m *Metric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Metric.Marshal(b, m, deterministic)
+}
+func (dst *Metric) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Metric.Merge(dst, src)
+}
+func (m *Metric) XXX_Size() int {
+ return xxx_messageInfo_Metric.Size(m)
+}
+func (m *Metric) XXX_DiscardUnknown() {
+ xxx_messageInfo_Metric.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Metric proto.InternalMessageInfo
+
+func (m *Metric) GetLabel() []*LabelPair {
+ if m != nil {
+ return m.Label
+ }
+ return nil
+}
+
+func (m *Metric) GetGauge() *Gauge {
+ if m != nil {
+ return m.Gauge
+ }
+ return nil
+}
+
+func (m *Metric) GetCounter() *Counter {
+ if m != nil {
+ return m.Counter
+ }
+ return nil
+}
+
+func (m *Metric) GetSummary() *Summary {
+ if m != nil {
+ return m.Summary
+ }
+ return nil
+}
+
+func (m *Metric) GetUntyped() *Untyped {
+ if m != nil {
+ return m.Untyped
+ }
+ return nil
+}
+
+func (m *Metric) GetHistogram() *Histogram {
+ if m != nil {
+ return m.Histogram
+ }
+ return nil
+}
+
+func (m *Metric) GetTimestampMs() int64 {
+ if m != nil && m.TimestampMs != nil {
+ return *m.TimestampMs
+ }
+ return 0
+}
+
+type MetricFamily struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"`
+ Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"`
+ Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *MetricFamily) Reset() { *m = MetricFamily{} }
+func (m *MetricFamily) String() string { return proto.CompactTextString(m) }
+func (*MetricFamily) ProtoMessage() {}
+func (*MetricFamily) Descriptor() ([]byte, []int) {
+ return fileDescriptor_metrics_c97c9a2b9560cb8f, []int{9}
+}
+func (m *MetricFamily) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_MetricFamily.Unmarshal(m, b)
+}
+func (m *MetricFamily) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_MetricFamily.Marshal(b, m, deterministic)
+}
+func (dst *MetricFamily) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MetricFamily.Merge(dst, src)
+}
+func (m *MetricFamily) XXX_Size() int {
+ return xxx_messageInfo_MetricFamily.Size(m)
+}
+func (m *MetricFamily) XXX_DiscardUnknown() {
+ xxx_messageInfo_MetricFamily.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MetricFamily proto.InternalMessageInfo
+
+func (m *MetricFamily) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *MetricFamily) GetHelp() string {
+ if m != nil && m.Help != nil {
+ return *m.Help
+ }
+ return ""
+}
+
+func (m *MetricFamily) GetType() MetricType {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return MetricType_COUNTER
+}
+
+func (m *MetricFamily) GetMetric() []*Metric {
+ if m != nil {
+ return m.Metric
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*LabelPair)(nil), "io.prometheus.client.LabelPair")
+ proto.RegisterType((*Gauge)(nil), "io.prometheus.client.Gauge")
+ proto.RegisterType((*Counter)(nil), "io.prometheus.client.Counter")
+ proto.RegisterType((*Quantile)(nil), "io.prometheus.client.Quantile")
+ proto.RegisterType((*Summary)(nil), "io.prometheus.client.Summary")
+ proto.RegisterType((*Untyped)(nil), "io.prometheus.client.Untyped")
+ proto.RegisterType((*Histogram)(nil), "io.prometheus.client.Histogram")
+ proto.RegisterType((*Bucket)(nil), "io.prometheus.client.Bucket")
+ proto.RegisterType((*Metric)(nil), "io.prometheus.client.Metric")
+ proto.RegisterType((*MetricFamily)(nil), "io.prometheus.client.MetricFamily")
+ proto.RegisterEnum("io.prometheus.client.MetricType", MetricType_name, MetricType_value)
+}
+
+func init() { proto.RegisterFile("metrics.proto", fileDescriptor_metrics_c97c9a2b9560cb8f) }
+
+var fileDescriptor_metrics_c97c9a2b9560cb8f = []byte{
+ // 591 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xdb, 0x4e,
+ 0x14, 0xfc, 0x99, 0xd8, 0x09, 0x7e, 0x86, 0x5f, 0xad, 0x15, 0x07, 0xab, 0x2d, 0x25, 0xcd, 0x89,
+ 0xf6, 0x10, 0x54, 0x04, 0xaa, 0x44, 0xdb, 0x03, 0x50, 0x1a, 0x2a, 0xd5, 0x40, 0x37, 0xc9, 0x81,
+ 0x5e, 0xac, 0x8d, 0x59, 0x25, 0x56, 0xbd, 0xb6, 0x6b, 0xef, 0x22, 0xe5, 0xdc, 0x43, 0xbf, 0x47,
+ 0xbf, 0x68, 0xab, 0xfd, 0xe3, 0x18, 0x24, 0xc3, 0xa9, 0xb7, 0xb7, 0xf3, 0x66, 0xde, 0x8e, 0x77,
+ 0xc7, 0x0b, 0x9b, 0x8c, 0xf2, 0x32, 0x89, 0xab, 0x61, 0x51, 0xe6, 0x3c, 0x47, 0x5b, 0x49, 0x2e,
+ 0x2b, 0x46, 0xf9, 0x82, 0x8a, 0x6a, 0x18, 0xa7, 0x09, 0xcd, 0xf8, 0xe0, 0x10, 0xdc, 0x2f, 0x64,
+ 0x46, 0xd3, 0x2b, 0x92, 0x94, 0x08, 0x81, 0x9d, 0x11, 0x46, 0x03, 0xab, 0x6f, 0xed, 0xba, 0x58,
+ 0xd5, 0x68, 0x0b, 0x9c, 0x5b, 0x92, 0x0a, 0x1a, 0xac, 0x29, 0x50, 0x2f, 0x06, 0xdb, 0xe0, 0x8c,
+ 0x88, 0x98, 0xdf, 0x69, 0x4b, 0x8d, 0x55, 0xb7, 0x77, 0xa0, 0x77, 0x9a, 0x8b, 0x8c, 0xd3, 0xf2,
+ 0x01, 0xc2, 0x7b, 0x58, 0xff, 0x2a, 0x48, 0xc6, 0x93, 0x94, 0xa2, 0xa7, 0xb0, 0xfe, 0xc3, 0xd4,
+ 0x86, 0xb4, 0x5a, 0xdf, 0xdf, 0x7d, 0xa5, 0xfe, 0x65, 0x41, 0x6f, 0x2c, 0x18, 0x23, 0xe5, 0x12,
+ 0xbd, 0x84, 0x8d, 0x8a, 0xb0, 0x22, 0xa5, 0x51, 0x2c, 0x77, 0x54, 0x13, 0x6c, 0xec, 0x69, 0x4c,
+ 0x99, 0x40, 0xdb, 0x00, 0x86, 0x52, 0x09, 0x66, 0x26, 0xb9, 0x1a, 0x19, 0x0b, 0x86, 0x8e, 0xee,
+ 0xec, 0xdf, 0xe9, 0x77, 0x76, 0xbd, 0xfd, 0x17, 0xc3, 0xb6, 0xb3, 0x1a, 0xd6, 0x8e, 0x1b, 0x7f,
+ 0xf2, 0x43, 0xa7, 0x19, 0x5f, 0x16, 0xf4, 0xe6, 0x81, 0x0f, 0xfd, 0x69, 0x81, 0x7b, 0x9e, 0x54,
+ 0x3c, 0x9f, 0x97, 0x84, 0xfd, 0x03, 0xb3, 0x07, 0xd0, 0x9d, 0x89, 0xf8, 0x3b, 0xe5, 0xc6, 0xea,
+ 0xf3, 0x76, 0xab, 0x27, 0x8a, 0x83, 0x0d, 0x77, 0x30, 0x81, 0xae, 0x46, 0xd0, 0x2b, 0xf0, 0x63,
+ 0xc1, 0x44, 0x4a, 0x78, 0x72, 0x7b, 0xdf, 0xc5, 0x93, 0x06, 0xd7, 0x4e, 0x76, 0xc0, 0x13, 0x45,
+ 0x41, 0xcb, 0x68, 0x96, 0x8b, 0xec, 0xc6, 0x58, 0x01, 0x05, 0x9d, 0x48, 0x64, 0xf0, 0x67, 0x0d,
+ 0xba, 0xa1, 0xca, 0x18, 0x3a, 0x04, 0x27, 0x95, 0x31, 0x0a, 0x2c, 0xe5, 0x6a, 0xa7, 0xdd, 0xd5,
+ 0x2a, 0x69, 0x58, 0xb3, 0xd1, 0x1b, 0x70, 0xe6, 0x32, 0x46, 0x6a, 0xb8, 0xb7, 0xff, 0xac, 0x5d,
+ 0xa6, 0x92, 0x86, 0x35, 0x13, 0xbd, 0x85, 0x5e, 0xac, 0xa3, 0x15, 0x74, 0x94, 0x68, 0xbb, 0x5d,
+ 0x64, 0xf2, 0x87, 0x6b, 0xb6, 0x14, 0x56, 0x3a, 0x33, 0x81, 0xfd, 0x98, 0xd0, 0x04, 0x0b, 0xd7,
+ 0x6c, 0x29, 0x14, 0xfa, 0x8e, 0x03, 0xe7, 0x31, 0xa1, 0x09, 0x02, 0xae, 0xd9, 0xe8, 0x03, 0xb8,
+ 0x8b, 0xfa, 0xea, 0x83, 0x9e, 0x92, 0x3e, 0x70, 0x30, 0xab, 0x84, 0xe0, 0x46, 0x21, 0xc3, 0xc2,
+ 0x13, 0x46, 0x2b, 0x4e, 0x58, 0x11, 0xb1, 0x2a, 0xe8, 0xf6, 0xad, 0xdd, 0x0e, 0xf6, 0x56, 0x58,
+ 0x58, 0x0d, 0x7e, 0x5b, 0xb0, 0xa1, 0x6f, 0xe0, 0x13, 0x61, 0x49, 0xba, 0x6c, 0xfd, 0x83, 0x11,
+ 0xd8, 0x0b, 0x9a, 0x16, 0xe6, 0x07, 0x56, 0x35, 0x3a, 0x00, 0x5b, 0x7a, 0x54, 0x47, 0xf8, 0xff,
+ 0x7e, 0xbf, 0xdd, 0x95, 0x9e, 0x3c, 0x59, 0x16, 0x14, 0x2b, 0xb6, 0x0c, 0x9f, 0x7e, 0x53, 0x02,
+ 0xfb, 0xb1, 0xf0, 0x69, 0x1d, 0x36, 0xdc, 0xd7, 0x21, 0x40, 0x33, 0x09, 0x79, 0xd0, 0x3b, 0xbd,
+ 0x9c, 0x5e, 0x4c, 0xce, 0xb0, 0xff, 0x1f, 0x72, 0xc1, 0x19, 0x1d, 0x4f, 0x47, 0x67, 0xbe, 0x25,
+ 0xf1, 0xf1, 0x34, 0x0c, 0x8f, 0xf1, 0xb5, 0xbf, 0x26, 0x17, 0xd3, 0x8b, 0xc9, 0xf5, 0xd5, 0xd9,
+ 0x47, 0xbf, 0x83, 0x36, 0xc1, 0x3d, 0xff, 0x3c, 0x9e, 0x5c, 0x8e, 0xf0, 0x71, 0xe8, 0xdb, 0x27,
+ 0x18, 0x5a, 0x5f, 0xb2, 0x6f, 0x47, 0xf3, 0x84, 0x2f, 0xc4, 0x6c, 0x18, 0xe7, 0x6c, 0xaf, 0xe9,
+ 0xee, 0xe9, 0x6e, 0xc4, 0xf2, 0x1b, 0x9a, 0xee, 0xcd, 0xf3, 0x77, 0x49, 0x1e, 0x35, 0xdd, 0x48,
+ 0x77, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x45, 0x21, 0x7f, 0x64, 0x2b, 0x05, 0x00, 0x00,
+}
diff --git a/vendor/github.com/prometheus/client_model/ruby/LICENSE b/vendor/github.com/prometheus/client_model/ruby/LICENSE
new file mode 100644
index 00000000..11069edd
--- /dev/null
+++ b/vendor/github.com/prometheus/client_model/ruby/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/github.com/prometheus/common/LICENSE b/vendor/github.com/prometheus/common/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/vendor/github.com/prometheus/common/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/prometheus/common/NOTICE b/vendor/github.com/prometheus/common/NOTICE
new file mode 100644
index 00000000..636a2c1a
--- /dev/null
+++ b/vendor/github.com/prometheus/common/NOTICE
@@ -0,0 +1,5 @@
+Common libraries shared by Prometheus Go components.
+Copyright 2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go
new file mode 100644
index 00000000..c092723e
--- /dev/null
+++ b/vendor/github.com/prometheus/common/expfmt/decode.go
@@ -0,0 +1,429 @@
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "mime"
+ "net/http"
+
+ dto "github.com/prometheus/client_model/go"
+
+ "github.com/matttproud/golang_protobuf_extensions/pbutil"
+ "github.com/prometheus/common/model"
+)
+
+// Decoder types decode an input stream into metric families.
+type Decoder interface {
+ Decode(*dto.MetricFamily) error
+}
+
+// DecodeOptions contains options used by the Decoder and in sample extraction.
+type DecodeOptions struct {
+ // Timestamp is added to each value from the stream that has no explicit timestamp set.
+ Timestamp model.Time
+}
+
+// ResponseFormat extracts the correct format from a HTTP response header.
+// If no matching format can be found FormatUnknown is returned.
+func ResponseFormat(h http.Header) Format {
+ ct := h.Get(hdrContentType)
+
+ mediatype, params, err := mime.ParseMediaType(ct)
+ if err != nil {
+ return FmtUnknown
+ }
+
+ const textType = "text/plain"
+
+ switch mediatype {
+ case ProtoType:
+ if p, ok := params["proto"]; ok && p != ProtoProtocol {
+ return FmtUnknown
+ }
+ if e, ok := params["encoding"]; ok && e != "delimited" {
+ return FmtUnknown
+ }
+ return FmtProtoDelim
+
+ case textType:
+ if v, ok := params["version"]; ok && v != TextVersion {
+ return FmtUnknown
+ }
+ return FmtText
+ }
+
+ return FmtUnknown
+}
+
+// NewDecoder returns a new decoder based on the given input format.
+// If the input format does not imply otherwise, a text format decoder is returned.
+func NewDecoder(r io.Reader, format Format) Decoder {
+ switch format {
+ case FmtProtoDelim:
+ return &protoDecoder{r: r}
+ }
+ return &textDecoder{r: r}
+}
+
+// protoDecoder implements the Decoder interface for protocol buffers.
+type protoDecoder struct {
+ r io.Reader
+}
+
+// Decode implements the Decoder interface.
+func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
+ _, err := pbutil.ReadDelimited(d.r, v)
+ if err != nil {
+ return err
+ }
+ if !model.IsValidMetricName(model.LabelValue(v.GetName())) {
+ return fmt.Errorf("invalid metric name %q", v.GetName())
+ }
+ for _, m := range v.GetMetric() {
+ if m == nil {
+ continue
+ }
+ for _, l := range m.GetLabel() {
+ if l == nil {
+ continue
+ }
+ if !model.LabelValue(l.GetValue()).IsValid() {
+ return fmt.Errorf("invalid label value %q", l.GetValue())
+ }
+ if !model.LabelName(l.GetName()).IsValid() {
+ return fmt.Errorf("invalid label name %q", l.GetName())
+ }
+ }
+ }
+ return nil
+}
+
+// textDecoder implements the Decoder interface for the text protocol.
+type textDecoder struct {
+ r io.Reader
+ p TextParser
+ fams []*dto.MetricFamily
+}
+
+// Decode implements the Decoder interface.
+func (d *textDecoder) Decode(v *dto.MetricFamily) error {
+ // TODO(fabxc): Wrap this as a line reader to make streaming safer.
+ if len(d.fams) == 0 {
+ // No cached metric families, read everything and parse metrics.
+ fams, err := d.p.TextToMetricFamilies(d.r)
+ if err != nil {
+ return err
+ }
+ if len(fams) == 0 {
+ return io.EOF
+ }
+ d.fams = make([]*dto.MetricFamily, 0, len(fams))
+ for _, f := range fams {
+ d.fams = append(d.fams, f)
+ }
+ }
+
+ *v = *d.fams[0]
+ d.fams = d.fams[1:]
+
+ return nil
+}
+
+// SampleDecoder wraps a Decoder to extract samples from the metric families
+// decoded by the wrapped Decoder.
+type SampleDecoder struct {
+ Dec Decoder
+ Opts *DecodeOptions
+
+ f dto.MetricFamily
+}
+
+// Decode calls the Decode method of the wrapped Decoder and then extracts the
+// samples from the decoded MetricFamily into the provided model.Vector.
+func (sd *SampleDecoder) Decode(s *model.Vector) error {
+ err := sd.Dec.Decode(&sd.f)
+ if err != nil {
+ return err
+ }
+ *s, err = extractSamples(&sd.f, sd.Opts)
+ return err
+}
+
+// ExtractSamples builds a slice of samples from the provided metric
+// families. If an error occurrs during sample extraction, it continues to
+// extract from the remaining metric families. The returned error is the last
+// error that has occurred.
+func ExtractSamples(o *DecodeOptions, fams ...*dto.MetricFamily) (model.Vector, error) {
+ var (
+ all model.Vector
+ lastErr error
+ )
+ for _, f := range fams {
+ some, err := extractSamples(f, o)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ all = append(all, some...)
+ }
+ return all, lastErr
+}
+
+func extractSamples(f *dto.MetricFamily, o *DecodeOptions) (model.Vector, error) {
+ switch f.GetType() {
+ case dto.MetricType_COUNTER:
+ return extractCounter(o, f), nil
+ case dto.MetricType_GAUGE:
+ return extractGauge(o, f), nil
+ case dto.MetricType_SUMMARY:
+ return extractSummary(o, f), nil
+ case dto.MetricType_UNTYPED:
+ return extractUntyped(o, f), nil
+ case dto.MetricType_HISTOGRAM:
+ return extractHistogram(o, f), nil
+ }
+ return nil, fmt.Errorf("expfmt.extractSamples: unknown metric family type %v", f.GetType())
+}
+
+func extractCounter(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Counter == nil {
+ continue
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ smpl := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Counter.GetValue()),
+ }
+
+ if m.TimestampMs != nil {
+ smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ } else {
+ smpl.Timestamp = o.Timestamp
+ }
+
+ samples = append(samples, smpl)
+ }
+
+ return samples
+}
+
+func extractGauge(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Gauge == nil {
+ continue
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ smpl := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Gauge.GetValue()),
+ }
+
+ if m.TimestampMs != nil {
+ smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ } else {
+ smpl.Timestamp = o.Timestamp
+ }
+
+ samples = append(samples, smpl)
+ }
+
+ return samples
+}
+
+func extractUntyped(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Untyped == nil {
+ continue
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ smpl := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Untyped.GetValue()),
+ }
+
+ if m.TimestampMs != nil {
+ smpl.Timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ } else {
+ smpl.Timestamp = o.Timestamp
+ }
+
+ samples = append(samples, smpl)
+ }
+
+ return samples
+}
+
+func extractSummary(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Summary == nil {
+ continue
+ }
+
+ timestamp := o.Timestamp
+ if m.TimestampMs != nil {
+ timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ }
+
+ for _, q := range m.Summary.Quantile {
+ lset := make(model.LabelSet, len(m.Label)+2)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ // BUG(matt): Update other names to "quantile".
+ lset[model.LabelName(model.QuantileLabel)] = model.LabelValue(fmt.Sprint(q.GetQuantile()))
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName())
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(q.GetValue()),
+ Timestamp: timestamp,
+ })
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Summary.GetSampleSum()),
+ Timestamp: timestamp,
+ })
+
+ lset = make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Summary.GetSampleCount()),
+ Timestamp: timestamp,
+ })
+ }
+
+ return samples
+}
+
+func extractHistogram(o *DecodeOptions, f *dto.MetricFamily) model.Vector {
+ samples := make(model.Vector, 0, len(f.Metric))
+
+ for _, m := range f.Metric {
+ if m.Histogram == nil {
+ continue
+ }
+
+ timestamp := o.Timestamp
+ if m.TimestampMs != nil {
+ timestamp = model.TimeFromUnixNano(*m.TimestampMs * 1000000)
+ }
+
+ infSeen := false
+
+ for _, q := range m.Histogram.Bucket {
+ lset := make(model.LabelSet, len(m.Label)+2)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.LabelName(model.BucketLabel)] = model.LabelValue(fmt.Sprint(q.GetUpperBound()))
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")
+
+ if math.IsInf(q.GetUpperBound(), +1) {
+ infSeen = true
+ }
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(q.GetCumulativeCount()),
+ Timestamp: timestamp,
+ })
+ }
+
+ lset := make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_sum")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Histogram.GetSampleSum()),
+ Timestamp: timestamp,
+ })
+
+ lset = make(model.LabelSet, len(m.Label)+1)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_count")
+
+ count := &model.Sample{
+ Metric: model.Metric(lset),
+ Value: model.SampleValue(m.Histogram.GetSampleCount()),
+ Timestamp: timestamp,
+ }
+ samples = append(samples, count)
+
+ if !infSeen {
+ // Append an infinity bucket sample.
+ lset := make(model.LabelSet, len(m.Label)+2)
+ for _, p := range m.Label {
+ lset[model.LabelName(p.GetName())] = model.LabelValue(p.GetValue())
+ }
+ lset[model.LabelName(model.BucketLabel)] = model.LabelValue("+Inf")
+ lset[model.MetricNameLabel] = model.LabelValue(f.GetName() + "_bucket")
+
+ samples = append(samples, &model.Sample{
+ Metric: model.Metric(lset),
+ Value: count.Value,
+ Timestamp: timestamp,
+ })
+ }
+ }
+
+ return samples
+}
diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go
new file mode 100644
index 00000000..11839ed6
--- /dev/null
+++ b/vendor/github.com/prometheus/common/expfmt/encode.go
@@ -0,0 +1,88 @@
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/matttproud/golang_protobuf_extensions/pbutil"
+ "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
+
+ dto "github.com/prometheus/client_model/go"
+)
+
+// Encoder types encode metric families into an underlying wire protocol.
+type Encoder interface {
+ Encode(*dto.MetricFamily) error
+}
+
+type encoder func(*dto.MetricFamily) error
+
+func (e encoder) Encode(v *dto.MetricFamily) error {
+ return e(v)
+}
+
+// Negotiate returns the Content-Type based on the given Accept header.
+// If no appropriate accepted type is found, FmtText is returned.
+func Negotiate(h http.Header) Format {
+ for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
+ // Check for protocol buffer
+ if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
+ switch ac.Params["encoding"] {
+ case "delimited":
+ return FmtProtoDelim
+ case "text":
+ return FmtProtoText
+ case "compact-text":
+ return FmtProtoCompact
+ }
+ }
+ // Check for text format.
+ ver := ac.Params["version"]
+ if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
+ return FmtText
+ }
+ }
+ return FmtText
+}
+
+// NewEncoder returns a new encoder based on content type negotiation.
+func NewEncoder(w io.Writer, format Format) Encoder {
+ switch format {
+ case FmtProtoDelim:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := pbutil.WriteDelimited(w, v)
+ return err
+ })
+ case FmtProtoCompact:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := fmt.Fprintln(w, v.String())
+ return err
+ })
+ case FmtProtoText:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := fmt.Fprintln(w, proto.MarshalTextString(v))
+ return err
+ })
+ case FmtText:
+ return encoder(func(v *dto.MetricFamily) error {
+ _, err := MetricFamilyToText(w, v)
+ return err
+ })
+ }
+ panic("expfmt.NewEncoder: unknown format")
+}
diff --git a/vendor/github.com/prometheus/common/expfmt/expfmt.go b/vendor/github.com/prometheus/common/expfmt/expfmt.go
new file mode 100644
index 00000000..c71bcb98
--- /dev/null
+++ b/vendor/github.com/prometheus/common/expfmt/expfmt.go
@@ -0,0 +1,38 @@
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package expfmt contains tools for reading and writing Prometheus metrics.
+package expfmt
+
+// Format specifies the HTTP content type of the different wire protocols.
+type Format string
+
+// Constants to assemble the Content-Type values for the different wire protocols.
+const (
+ TextVersion = "0.0.4"
+ ProtoType = `application/vnd.google.protobuf`
+ ProtoProtocol = `io.prometheus.client.MetricFamily`
+ ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
+
+ // The Content-Type values for the different wire protocols.
+ FmtUnknown Format = ``
+ FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
+ FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
+ FmtProtoText Format = ProtoFmt + ` encoding=text`
+ FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
+)
+
+const (
+ hdrContentType = "Content-Type"
+ hdrAccept = "Accept"
+)
diff --git a/vendor/github.com/prometheus/common/expfmt/fuzz.go b/vendor/github.com/prometheus/common/expfmt/fuzz.go
new file mode 100644
index 00000000..dc2eedee
--- /dev/null
+++ b/vendor/github.com/prometheus/common/expfmt/fuzz.go
@@ -0,0 +1,36 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Build only when actually fuzzing
+// +build gofuzz
+
+package expfmt
+
+import "bytes"
+
+// Fuzz text metric parser with with github.com/dvyukov/go-fuzz:
+//
+// go-fuzz-build github.com/prometheus/common/expfmt
+// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz
+//
+// Further input samples should go in the folder fuzz/corpus.
+func Fuzz(in []byte) int {
+ parser := TextParser{}
+ _, err := parser.TextToMetricFamilies(bytes.NewReader(in))
+
+ if err != nil {
+ return 0
+ }
+
+ return 1
+}
diff --git a/vendor/github.com/prometheus/common/expfmt/text_create.go b/vendor/github.com/prometheus/common/expfmt/text_create.go
new file mode 100644
index 00000000..f11321cd
--- /dev/null
+++ b/vendor/github.com/prometheus/common/expfmt/text_create.go
@@ -0,0 +1,303 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "strings"
+
+ dto "github.com/prometheus/client_model/go"
+ "github.com/prometheus/common/model"
+)
+
+// MetricFamilyToText converts a MetricFamily proto message into text format and
+// writes the resulting lines to 'out'. It returns the number of bytes written
+// and any error encountered. The output will have the same order as the input,
+// no further sorting is performed. Furthermore, this function assumes the input
+// is already sanitized and does not perform any sanity checks. If the input
+// contains duplicate metrics or invalid metric or label names, the conversion
+// will result in invalid text format output.
+//
+// This method fulfills the type 'prometheus.encoder'.
+func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
+ var written int
+
+ // Fail-fast checks.
+ if len(in.Metric) == 0 {
+ return written, fmt.Errorf("MetricFamily has no metrics: %s", in)
+ }
+ name := in.GetName()
+ if name == "" {
+ return written, fmt.Errorf("MetricFamily has no name: %s", in)
+ }
+
+ // Comments, first HELP, then TYPE.
+ if in.Help != nil {
+ n, err := fmt.Fprintf(
+ out, "# HELP %s %s\n",
+ name, escapeString(*in.Help, false),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ metricType := in.GetType()
+ n, err := fmt.Fprintf(
+ out, "# TYPE %s %s\n",
+ name, strings.ToLower(metricType.String()),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+
+ // Finally the samples, one line for each.
+ for _, metric := range in.Metric {
+ switch metricType {
+ case dto.MetricType_COUNTER:
+ if metric.Counter == nil {
+ return written, fmt.Errorf(
+ "expected counter in metric %s %s", name, metric,
+ )
+ }
+ n, err = writeSample(
+ name, metric, "", "",
+ metric.Counter.GetValue(),
+ out,
+ )
+ case dto.MetricType_GAUGE:
+ if metric.Gauge == nil {
+ return written, fmt.Errorf(
+ "expected gauge in metric %s %s", name, metric,
+ )
+ }
+ n, err = writeSample(
+ name, metric, "", "",
+ metric.Gauge.GetValue(),
+ out,
+ )
+ case dto.MetricType_UNTYPED:
+ if metric.Untyped == nil {
+ return written, fmt.Errorf(
+ "expected untyped in metric %s %s", name, metric,
+ )
+ }
+ n, err = writeSample(
+ name, metric, "", "",
+ metric.Untyped.GetValue(),
+ out,
+ )
+ case dto.MetricType_SUMMARY:
+ if metric.Summary == nil {
+ return written, fmt.Errorf(
+ "expected summary in metric %s %s", name, metric,
+ )
+ }
+ for _, q := range metric.Summary.Quantile {
+ n, err = writeSample(
+ name, metric,
+ model.QuantileLabel, fmt.Sprint(q.GetQuantile()),
+ q.GetValue(),
+ out,
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ n, err = writeSample(
+ name+"_sum", metric, "", "",
+ metric.Summary.GetSampleSum(),
+ out,
+ )
+ if err != nil {
+ return written, err
+ }
+ written += n
+ n, err = writeSample(
+ name+"_count", metric, "", "",
+ float64(metric.Summary.GetSampleCount()),
+ out,
+ )
+ case dto.MetricType_HISTOGRAM:
+ if metric.Histogram == nil {
+ return written, fmt.Errorf(
+ "expected histogram in metric %s %s", name, metric,
+ )
+ }
+ infSeen := false
+ for _, q := range metric.Histogram.Bucket {
+ n, err = writeSample(
+ name+"_bucket", metric,
+ model.BucketLabel, fmt.Sprint(q.GetUpperBound()),
+ float64(q.GetCumulativeCount()),
+ out,
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ if math.IsInf(q.GetUpperBound(), +1) {
+ infSeen = true
+ }
+ }
+ if !infSeen {
+ n, err = writeSample(
+ name+"_bucket", metric,
+ model.BucketLabel, "+Inf",
+ float64(metric.Histogram.GetSampleCount()),
+ out,
+ )
+ if err != nil {
+ return written, err
+ }
+ written += n
+ }
+ n, err = writeSample(
+ name+"_sum", metric, "", "",
+ metric.Histogram.GetSampleSum(),
+ out,
+ )
+ if err != nil {
+ return written, err
+ }
+ written += n
+ n, err = writeSample(
+ name+"_count", metric, "", "",
+ float64(metric.Histogram.GetSampleCount()),
+ out,
+ )
+ default:
+ return written, fmt.Errorf(
+ "unexpected type in metric %s %s", name, metric,
+ )
+ }
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ return written, nil
+}
+
+// writeSample writes a single sample in text format to out, given the metric
+// name, the metric proto message itself, optionally an additional label name
+// and value (use empty strings if not required), and the value. The function
+// returns the number of bytes written and any error encountered.
+func writeSample(
+ name string,
+ metric *dto.Metric,
+ additionalLabelName, additionalLabelValue string,
+ value float64,
+ out io.Writer,
+) (int, error) {
+ var written int
+ n, err := fmt.Fprint(out, name)
+ written += n
+ if err != nil {
+ return written, err
+ }
+ n, err = labelPairsToText(
+ metric.Label,
+ additionalLabelName, additionalLabelValue,
+ out,
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ n, err = fmt.Fprintf(out, " %v", value)
+ written += n
+ if err != nil {
+ return written, err
+ }
+ if metric.TimestampMs != nil {
+ n, err = fmt.Fprintf(out, " %v", *metric.TimestampMs)
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ n, err = out.Write([]byte{'\n'})
+ written += n
+ if err != nil {
+ return written, err
+ }
+ return written, nil
+}
+
+// labelPairsToText converts a slice of LabelPair proto messages plus the
+// explicitly given additional label pair into text formatted as required by the
+// text format and writes it to 'out'. An empty slice in combination with an
+// empty string 'additionalLabelName' results in nothing being
+// written. Otherwise, the label pairs are written, escaped as required by the
+// text format, and enclosed in '{...}'. The function returns the number of
+// bytes written and any error encountered.
+func labelPairsToText(
+ in []*dto.LabelPair,
+ additionalLabelName, additionalLabelValue string,
+ out io.Writer,
+) (int, error) {
+ if len(in) == 0 && additionalLabelName == "" {
+ return 0, nil
+ }
+ var written int
+ separator := '{'
+ for _, lp := range in {
+ n, err := fmt.Fprintf(
+ out, `%c%s="%s"`,
+ separator, lp.GetName(), escapeString(lp.GetValue(), true),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ separator = ','
+ }
+ if additionalLabelName != "" {
+ n, err := fmt.Fprintf(
+ out, `%c%s="%s"`,
+ separator, additionalLabelName,
+ escapeString(additionalLabelValue, true),
+ )
+ written += n
+ if err != nil {
+ return written, err
+ }
+ }
+ n, err := out.Write([]byte{'}'})
+ written += n
+ if err != nil {
+ return written, err
+ }
+ return written, nil
+}
+
+var (
+ escape = strings.NewReplacer("\\", `\\`, "\n", `\n`)
+ escapeWithDoubleQuote = strings.NewReplacer("\\", `\\`, "\n", `\n`, "\"", `\"`)
+)
+
+// escapeString replaces '\' by '\\', new line character by '\n', and - if
+// includeDoubleQuote is true - '"' by '\"'.
+func escapeString(v string, includeDoubleQuote bool) string {
+ if includeDoubleQuote {
+ return escapeWithDoubleQuote.Replace(v)
+ }
+
+ return escape.Replace(v)
+}
diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse.go b/vendor/github.com/prometheus/common/expfmt/text_parse.go
new file mode 100644
index 00000000..ec3d86ba
--- /dev/null
+++ b/vendor/github.com/prometheus/common/expfmt/text_parse.go
@@ -0,0 +1,757 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package expfmt
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "math"
+ "strconv"
+ "strings"
+
+ dto "github.com/prometheus/client_model/go"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/prometheus/common/model"
+)
+
+// A stateFn is a function that represents a state in a state machine. By
+// executing it, the state is progressed to the next state. The stateFn returns
+// another stateFn, which represents the new state. The end state is represented
+// by nil.
+type stateFn func() stateFn
+
+// ParseError signals errors while parsing the simple and flat text-based
+// exchange format.
+type ParseError struct {
+ Line int
+ Msg string
+}
+
+// Error implements the error interface.
+func (e ParseError) Error() string {
+ return fmt.Sprintf("text format parsing error in line %d: %s", e.Line, e.Msg)
+}
+
+// TextParser is used to parse the simple and flat text-based exchange format. Its
+// zero value is ready to use.
+type TextParser struct {
+ metricFamiliesByName map[string]*dto.MetricFamily
+ buf *bufio.Reader // Where the parsed input is read through.
+ err error // Most recent error.
+ lineCount int // Tracks the line count for error messages.
+ currentByte byte // The most recent byte read.
+ currentToken bytes.Buffer // Re-used each time a token has to be gathered from multiple bytes.
+ currentMF *dto.MetricFamily
+ currentMetric *dto.Metric
+ currentLabelPair *dto.LabelPair
+
+ // The remaining member variables are only used for summaries/histograms.
+ currentLabels map[string]string // All labels including '__name__' but excluding 'quantile'/'le'
+ // Summary specific.
+ summaries map[uint64]*dto.Metric // Key is created with LabelsToSignature.
+ currentQuantile float64
+ // Histogram specific.
+ histograms map[uint64]*dto.Metric // Key is created with LabelsToSignature.
+ currentBucket float64
+ // These tell us if the currently processed line ends on '_count' or
+ // '_sum' respectively and belong to a summary/histogram, representing the sample
+ // count and sum of that summary/histogram.
+ currentIsSummaryCount, currentIsSummarySum bool
+ currentIsHistogramCount, currentIsHistogramSum bool
+}
+
+// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
+// format and creates MetricFamily proto messages. It returns the MetricFamily
+// proto messages in a map where the metric names are the keys, along with any
+// error encountered.
+//
+// If the input contains duplicate metrics (i.e. lines with the same metric name
+// and exactly the same label set), the resulting MetricFamily will contain
+// duplicate Metric proto messages. Similar is true for duplicate label
+// names. Checks for duplicates have to be performed separately, if required.
+// Also note that neither the metrics within each MetricFamily are sorted nor
+// the label pairs within each Metric. Sorting is not required for the most
+// frequent use of this method, which is sample ingestion in the Prometheus
+// server. However, for presentation purposes, you might want to sort the
+// metrics, and in some cases, you must sort the labels, e.g. for consumption by
+// the metric family injection hook of the Prometheus registry.
+//
+// Summaries and histograms are rather special beasts. You would probably not
+// use them in the simple text format anyway. This method can deal with
+// summaries and histograms if they are presented in exactly the way the
+// text.Create function creates them.
+//
+// This method must not be called concurrently. If you want to parse different
+// input concurrently, instantiate a separate Parser for each goroutine.
+func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) {
+ p.reset(in)
+ for nextState := p.startOfLine; nextState != nil; nextState = nextState() {
+ // Magic happens here...
+ }
+ // Get rid of empty metric families.
+ for k, mf := range p.metricFamiliesByName {
+ if len(mf.GetMetric()) == 0 {
+ delete(p.metricFamiliesByName, k)
+ }
+ }
+ // If p.err is io.EOF now, we have run into a premature end of the input
+ // stream. Turn this error into something nicer and more
+ // meaningful. (io.EOF is often used as a signal for the legitimate end
+ // of an input stream.)
+ if p.err == io.EOF {
+ p.parseError("unexpected end of input stream")
+ }
+ return p.metricFamiliesByName, p.err
+}
+
+func (p *TextParser) reset(in io.Reader) {
+ p.metricFamiliesByName = map[string]*dto.MetricFamily{}
+ if p.buf == nil {
+ p.buf = bufio.NewReader(in)
+ } else {
+ p.buf.Reset(in)
+ }
+ p.err = nil
+ p.lineCount = 0
+ if p.summaries == nil || len(p.summaries) > 0 {
+ p.summaries = map[uint64]*dto.Metric{}
+ }
+ if p.histograms == nil || len(p.histograms) > 0 {
+ p.histograms = map[uint64]*dto.Metric{}
+ }
+ p.currentQuantile = math.NaN()
+ p.currentBucket = math.NaN()
+}
+
+// startOfLine represents the state where the next byte read from p.buf is the
+// start of a line (or whitespace leading up to it).
+func (p *TextParser) startOfLine() stateFn {
+ p.lineCount++
+ if p.skipBlankTab(); p.err != nil {
+ // End of input reached. This is the only case where
+ // that is not an error but a signal that we are done.
+ p.err = nil
+ return nil
+ }
+ switch p.currentByte {
+ case '#':
+ return p.startComment
+ case '\n':
+ return p.startOfLine // Empty line, start the next one.
+ }
+ return p.readingMetricName
+}
+
+// startComment represents the state where the next byte read from p.buf is the
+// start of a comment (or whitespace leading up to it).
+func (p *TextParser) startComment() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '\n' {
+ return p.startOfLine
+ }
+ if p.readTokenUntilWhitespace(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ // If we have hit the end of line already, there is nothing left
+ // to do. This is not considered a syntax error.
+ if p.currentByte == '\n' {
+ return p.startOfLine
+ }
+ keyword := p.currentToken.String()
+ if keyword != "HELP" && keyword != "TYPE" {
+ // Generic comment, ignore by fast forwarding to end of line.
+ for p.currentByte != '\n' {
+ if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ }
+ return p.startOfLine
+ }
+ // There is something. Next has to be a metric name.
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.readTokenAsMetricName(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '\n' {
+ // At the end of the line already.
+ // Again, this is not considered a syntax error.
+ return p.startOfLine
+ }
+ if !isBlankOrTab(p.currentByte) {
+ p.parseError("invalid metric name in comment")
+ return nil
+ }
+ p.setOrCreateCurrentMF()
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '\n' {
+ // At the end of the line already.
+ // Again, this is not considered a syntax error.
+ return p.startOfLine
+ }
+ switch keyword {
+ case "HELP":
+ return p.readingHelp
+ case "TYPE":
+ return p.readingType
+ }
+ panic(fmt.Sprintf("code error: unexpected keyword %q", keyword))
+}
+
+// readingMetricName represents the state where the last byte read (now in
+// p.currentByte) is the first byte of a metric name.
+func (p *TextParser) readingMetricName() stateFn {
+ if p.readTokenAsMetricName(); p.err != nil {
+ return nil
+ }
+ if p.currentToken.Len() == 0 {
+ p.parseError("invalid metric name")
+ return nil
+ }
+ p.setOrCreateCurrentMF()
+ // Now is the time to fix the type if it hasn't happened yet.
+ if p.currentMF.Type == nil {
+ p.currentMF.Type = dto.MetricType_UNTYPED.Enum()
+ }
+ p.currentMetric = &dto.Metric{}
+ // Do not append the newly created currentMetric to
+ // currentMF.Metric right now. First wait if this is a summary,
+ // and the metric exists already, which we can only know after
+ // having read all the labels.
+ if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ return p.readingLabels
+}
+
+// readingLabels represents the state where the last byte read (now in
+// p.currentByte) is either the first byte of the label set (i.e. a '{'), or the
+// first byte of the value (otherwise).
+func (p *TextParser) readingLabels() stateFn {
+ // Summaries/histograms are special. We have to reset the
+ // currentLabels map, currentQuantile and currentBucket before starting to
+ // read labels.
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY || p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ p.currentLabels = map[string]string{}
+ p.currentLabels[string(model.MetricNameLabel)] = p.currentMF.GetName()
+ p.currentQuantile = math.NaN()
+ p.currentBucket = math.NaN()
+ }
+ if p.currentByte != '{' {
+ return p.readingValue
+ }
+ return p.startLabelName
+}
+
+// startLabelName represents the state where the next byte read from p.buf is
+// the start of a label name (or whitespace leading up to it).
+func (p *TextParser) startLabelName() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte == '}' {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ return p.readingValue
+ }
+ if p.readTokenAsLabelName(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentToken.Len() == 0 {
+ p.parseError(fmt.Sprintf("invalid label name for metric %q", p.currentMF.GetName()))
+ return nil
+ }
+ p.currentLabelPair = &dto.LabelPair{Name: proto.String(p.currentToken.String())}
+ if p.currentLabelPair.GetName() == string(model.MetricNameLabel) {
+ p.parseError(fmt.Sprintf("label name %q is reserved", model.MetricNameLabel))
+ return nil
+ }
+ // Special summary/histogram treatment. Don't add 'quantile' and 'le'
+ // labels to 'real' labels.
+ if !(p.currentMF.GetType() == dto.MetricType_SUMMARY && p.currentLabelPair.GetName() == model.QuantileLabel) &&
+ !(p.currentMF.GetType() == dto.MetricType_HISTOGRAM && p.currentLabelPair.GetName() == model.BucketLabel) {
+ p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPair)
+ }
+ if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte != '=' {
+ p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
+ return nil
+ }
+ return p.startLabelValue
+}
+
+// startLabelValue represents the state where the next byte read from p.buf is
+// the start of a (quoted) label value (or whitespace leading up to it).
+func (p *TextParser) startLabelValue() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentByte != '"' {
+ p.parseError(fmt.Sprintf("expected '\"' at start of label value, found %q", p.currentByte))
+ return nil
+ }
+ if p.readTokenAsLabelValue(); p.err != nil {
+ return nil
+ }
+ if !model.LabelValue(p.currentToken.String()).IsValid() {
+ p.parseError(fmt.Sprintf("invalid label value %q", p.currentToken.String()))
+ return nil
+ }
+ p.currentLabelPair.Value = proto.String(p.currentToken.String())
+ // Special treatment of summaries:
+ // - Quantile labels are special, will result in dto.Quantile later.
+ // - Other labels have to be added to currentLabels for signature calculation.
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY {
+ if p.currentLabelPair.GetName() == model.QuantileLabel {
+ if p.currentQuantile, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected float as value for 'quantile' label, got %q", p.currentLabelPair.GetValue()))
+ return nil
+ }
+ } else {
+ p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue()
+ }
+ }
+ // Similar special treatment of histograms.
+ if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ if p.currentLabelPair.GetName() == model.BucketLabel {
+ if p.currentBucket, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected float as value for 'le' label, got %q", p.currentLabelPair.GetValue()))
+ return nil
+ }
+ } else {
+ p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue()
+ }
+ }
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ switch p.currentByte {
+ case ',':
+ return p.startLabelName
+
+ case '}':
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ return p.readingValue
+ default:
+ p.parseError(fmt.Sprintf("unexpected end of label value %q", p.currentLabelPair.GetValue()))
+ return nil
+ }
+}
+
+// readingValue represents the state where the last byte read (now in
+// p.currentByte) is the first byte of the sample value (i.e. a float).
+func (p *TextParser) readingValue() stateFn {
+ // When we are here, we have read all the labels, so for the
+ // special case of a summary/histogram, we can finally find out
+ // if the metric already exists.
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY {
+ signature := model.LabelsToSignature(p.currentLabels)
+ if summary := p.summaries[signature]; summary != nil {
+ p.currentMetric = summary
+ } else {
+ p.summaries[signature] = p.currentMetric
+ p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
+ }
+ } else if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ signature := model.LabelsToSignature(p.currentLabels)
+ if histogram := p.histograms[signature]; histogram != nil {
+ p.currentMetric = histogram
+ } else {
+ p.histograms[signature] = p.currentMetric
+ p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
+ }
+ } else {
+ p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
+ }
+ if p.readTokenUntilWhitespace(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ value, err := strconv.ParseFloat(p.currentToken.String(), 64)
+ if err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected float as value, got %q", p.currentToken.String()))
+ return nil
+ }
+ switch p.currentMF.GetType() {
+ case dto.MetricType_COUNTER:
+ p.currentMetric.Counter = &dto.Counter{Value: proto.Float64(value)}
+ case dto.MetricType_GAUGE:
+ p.currentMetric.Gauge = &dto.Gauge{Value: proto.Float64(value)}
+ case dto.MetricType_UNTYPED:
+ p.currentMetric.Untyped = &dto.Untyped{Value: proto.Float64(value)}
+ case dto.MetricType_SUMMARY:
+ // *sigh*
+ if p.currentMetric.Summary == nil {
+ p.currentMetric.Summary = &dto.Summary{}
+ }
+ switch {
+ case p.currentIsSummaryCount:
+ p.currentMetric.Summary.SampleCount = proto.Uint64(uint64(value))
+ case p.currentIsSummarySum:
+ p.currentMetric.Summary.SampleSum = proto.Float64(value)
+ case !math.IsNaN(p.currentQuantile):
+ p.currentMetric.Summary.Quantile = append(
+ p.currentMetric.Summary.Quantile,
+ &dto.Quantile{
+ Quantile: proto.Float64(p.currentQuantile),
+ Value: proto.Float64(value),
+ },
+ )
+ }
+ case dto.MetricType_HISTOGRAM:
+ // *sigh*
+ if p.currentMetric.Histogram == nil {
+ p.currentMetric.Histogram = &dto.Histogram{}
+ }
+ switch {
+ case p.currentIsHistogramCount:
+ p.currentMetric.Histogram.SampleCount = proto.Uint64(uint64(value))
+ case p.currentIsHistogramSum:
+ p.currentMetric.Histogram.SampleSum = proto.Float64(value)
+ case !math.IsNaN(p.currentBucket):
+ p.currentMetric.Histogram.Bucket = append(
+ p.currentMetric.Histogram.Bucket,
+ &dto.Bucket{
+ UpperBound: proto.Float64(p.currentBucket),
+ CumulativeCount: proto.Uint64(uint64(value)),
+ },
+ )
+ }
+ default:
+ p.err = fmt.Errorf("unexpected type for metric name %q", p.currentMF.GetName())
+ }
+ if p.currentByte == '\n' {
+ return p.startOfLine
+ }
+ return p.startTimestamp
+}
+
+// startTimestamp represents the state where the next byte read from p.buf is
+// the start of the timestamp (or whitespace leading up to it).
+func (p *TextParser) startTimestamp() stateFn {
+ if p.skipBlankTab(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.readTokenUntilWhitespace(); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ timestamp, err := strconv.ParseInt(p.currentToken.String(), 10, 64)
+ if err != nil {
+ // Create a more helpful error message.
+ p.parseError(fmt.Sprintf("expected integer as timestamp, got %q", p.currentToken.String()))
+ return nil
+ }
+ p.currentMetric.TimestampMs = proto.Int64(timestamp)
+ if p.readTokenUntilNewline(false); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ if p.currentToken.Len() > 0 {
+ p.parseError(fmt.Sprintf("spurious string after timestamp: %q", p.currentToken.String()))
+ return nil
+ }
+ return p.startOfLine
+}
+
+// readingHelp represents the state where the last byte read (now in
+// p.currentByte) is the first byte of the docstring after 'HELP'.
+func (p *TextParser) readingHelp() stateFn {
+ if p.currentMF.Help != nil {
+ p.parseError(fmt.Sprintf("second HELP line for metric name %q", p.currentMF.GetName()))
+ return nil
+ }
+ // Rest of line is the docstring.
+ if p.readTokenUntilNewline(true); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ p.currentMF.Help = proto.String(p.currentToken.String())
+ return p.startOfLine
+}
+
+// readingType represents the state where the last byte read (now in
+// p.currentByte) is the first byte of the type hint after 'HELP'.
+func (p *TextParser) readingType() stateFn {
+ if p.currentMF.Type != nil {
+ p.parseError(fmt.Sprintf("second TYPE line for metric name %q, or TYPE reported after samples", p.currentMF.GetName()))
+ return nil
+ }
+ // Rest of line is the type.
+ if p.readTokenUntilNewline(false); p.err != nil {
+ return nil // Unexpected end of input.
+ }
+ metricType, ok := dto.MetricType_value[strings.ToUpper(p.currentToken.String())]
+ if !ok {
+ p.parseError(fmt.Sprintf("unknown metric type %q", p.currentToken.String()))
+ return nil
+ }
+ p.currentMF.Type = dto.MetricType(metricType).Enum()
+ return p.startOfLine
+}
+
+// parseError sets p.err to a ParseError at the current line with the given
+// message.
+func (p *TextParser) parseError(msg string) {
+ p.err = ParseError{
+ Line: p.lineCount,
+ Msg: msg,
+ }
+}
+
+// skipBlankTab reads (and discards) bytes from p.buf until it encounters a byte
+// that is neither ' ' nor '\t'. That byte is left in p.currentByte.
+func (p *TextParser) skipBlankTab() {
+ for {
+ if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil || !isBlankOrTab(p.currentByte) {
+ return
+ }
+ }
+}
+
+// skipBlankTabIfCurrentBlankTab works exactly as skipBlankTab but doesn't do
+// anything if p.currentByte is neither ' ' nor '\t'.
+func (p *TextParser) skipBlankTabIfCurrentBlankTab() {
+ if isBlankOrTab(p.currentByte) {
+ p.skipBlankTab()
+ }
+}
+
+// readTokenUntilWhitespace copies bytes from p.buf into p.currentToken. The
+// first byte considered is the byte already read (now in p.currentByte). The
+// first whitespace byte encountered is still copied into p.currentByte, but not
+// into p.currentToken.
+func (p *TextParser) readTokenUntilWhitespace() {
+ p.currentToken.Reset()
+ for p.err == nil && !isBlankOrTab(p.currentByte) && p.currentByte != '\n' {
+ p.currentToken.WriteByte(p.currentByte)
+ p.currentByte, p.err = p.buf.ReadByte()
+ }
+}
+
+// readTokenUntilNewline copies bytes from p.buf into p.currentToken. The first
+// byte considered is the byte already read (now in p.currentByte). The first
+// newline byte encountered is still copied into p.currentByte, but not into
+// p.currentToken. If recognizeEscapeSequence is true, two escape sequences are
+// recognized: '\\' translates into '\', and '\n' into a line-feed character.
+// All other escape sequences are invalid and cause an error.
+func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) {
+ p.currentToken.Reset()
+ escaped := false
+ for p.err == nil {
+ if recognizeEscapeSequence && escaped {
+ switch p.currentByte {
+ case '\\':
+ p.currentToken.WriteByte(p.currentByte)
+ case 'n':
+ p.currentToken.WriteByte('\n')
+ default:
+ p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
+ return
+ }
+ escaped = false
+ } else {
+ switch p.currentByte {
+ case '\n':
+ return
+ case '\\':
+ escaped = true
+ default:
+ p.currentToken.WriteByte(p.currentByte)
+ }
+ }
+ p.currentByte, p.err = p.buf.ReadByte()
+ }
+}
+
+// readTokenAsMetricName copies a metric name from p.buf into p.currentToken.
+// The first byte considered is the byte already read (now in p.currentByte).
+// The first byte not part of a metric name is still copied into p.currentByte,
+// but not into p.currentToken.
+func (p *TextParser) readTokenAsMetricName() {
+ p.currentToken.Reset()
+ if !isValidMetricNameStart(p.currentByte) {
+ return
+ }
+ for {
+ p.currentToken.WriteByte(p.currentByte)
+ p.currentByte, p.err = p.buf.ReadByte()
+ if p.err != nil || !isValidMetricNameContinuation(p.currentByte) {
+ return
+ }
+ }
+}
+
+// readTokenAsLabelName copies a label name from p.buf into p.currentToken.
+// The first byte considered is the byte already read (now in p.currentByte).
+// The first byte not part of a label name is still copied into p.currentByte,
+// but not into p.currentToken.
+func (p *TextParser) readTokenAsLabelName() {
+ p.currentToken.Reset()
+ if !isValidLabelNameStart(p.currentByte) {
+ return
+ }
+ for {
+ p.currentToken.WriteByte(p.currentByte)
+ p.currentByte, p.err = p.buf.ReadByte()
+ if p.err != nil || !isValidLabelNameContinuation(p.currentByte) {
+ return
+ }
+ }
+}
+
+// readTokenAsLabelValue copies a label value from p.buf into p.currentToken.
+// In contrast to the other 'readTokenAs...' functions, which start with the
+// last read byte in p.currentByte, this method ignores p.currentByte and starts
+// with reading a new byte from p.buf. The first byte not part of a label value
+// is still copied into p.currentByte, but not into p.currentToken.
+func (p *TextParser) readTokenAsLabelValue() {
+ p.currentToken.Reset()
+ escaped := false
+ for {
+ if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil {
+ return
+ }
+ if escaped {
+ switch p.currentByte {
+ case '"', '\\':
+ p.currentToken.WriteByte(p.currentByte)
+ case 'n':
+ p.currentToken.WriteByte('\n')
+ default:
+ p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
+ return
+ }
+ escaped = false
+ continue
+ }
+ switch p.currentByte {
+ case '"':
+ return
+ case '\n':
+ p.parseError(fmt.Sprintf("label value %q contains unescaped new-line", p.currentToken.String()))
+ return
+ case '\\':
+ escaped = true
+ default:
+ p.currentToken.WriteByte(p.currentByte)
+ }
+ }
+}
+
+func (p *TextParser) setOrCreateCurrentMF() {
+ p.currentIsSummaryCount = false
+ p.currentIsSummarySum = false
+ p.currentIsHistogramCount = false
+ p.currentIsHistogramSum = false
+ name := p.currentToken.String()
+ if p.currentMF = p.metricFamiliesByName[name]; p.currentMF != nil {
+ return
+ }
+ // Try out if this is a _sum or _count for a summary/histogram.
+ summaryName := summaryMetricName(name)
+ if p.currentMF = p.metricFamiliesByName[summaryName]; p.currentMF != nil {
+ if p.currentMF.GetType() == dto.MetricType_SUMMARY {
+ if isCount(name) {
+ p.currentIsSummaryCount = true
+ }
+ if isSum(name) {
+ p.currentIsSummarySum = true
+ }
+ return
+ }
+ }
+ histogramName := histogramMetricName(name)
+ if p.currentMF = p.metricFamiliesByName[histogramName]; p.currentMF != nil {
+ if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
+ if isCount(name) {
+ p.currentIsHistogramCount = true
+ }
+ if isSum(name) {
+ p.currentIsHistogramSum = true
+ }
+ return
+ }
+ }
+ p.currentMF = &dto.MetricFamily{Name: proto.String(name)}
+ p.metricFamiliesByName[name] = p.currentMF
+}
+
+func isValidLabelNameStart(b byte) bool {
+ return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_'
+}
+
+func isValidLabelNameContinuation(b byte) bool {
+ return isValidLabelNameStart(b) || (b >= '0' && b <= '9')
+}
+
+func isValidMetricNameStart(b byte) bool {
+ return isValidLabelNameStart(b) || b == ':'
+}
+
+func isValidMetricNameContinuation(b byte) bool {
+ return isValidLabelNameContinuation(b) || b == ':'
+}
+
+func isBlankOrTab(b byte) bool {
+ return b == ' ' || b == '\t'
+}
+
+func isCount(name string) bool {
+ return len(name) > 6 && name[len(name)-6:] == "_count"
+}
+
+func isSum(name string) bool {
+ return len(name) > 4 && name[len(name)-4:] == "_sum"
+}
+
+func isBucket(name string) bool {
+ return len(name) > 7 && name[len(name)-7:] == "_bucket"
+}
+
+func summaryMetricName(name string) string {
+ switch {
+ case isCount(name):
+ return name[:len(name)-6]
+ case isSum(name):
+ return name[:len(name)-4]
+ default:
+ return name
+ }
+}
+
+func histogramMetricName(name string) string {
+ switch {
+ case isCount(name):
+ return name[:len(name)-6]
+ case isSum(name):
+ return name[:len(name)-4]
+ case isBucket(name):
+ return name[:len(name)-7]
+ default:
+ return name
+ }
+}
diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go
new file mode 100644
index 00000000..648b38cb
--- /dev/null
+++ b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go
@@ -0,0 +1,162 @@
+/*
+HTTP Content-Type Autonegotiation.
+
+The functions in this package implement the behaviour specified in
+http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
+
+Copyright (c) 2011, Open Knowledge Foundation Ltd.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the Open Knowledge Foundation Ltd. nor the
+ names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+*/
+package goautoneg
+
+import (
+ "sort"
+ "strconv"
+ "strings"
+)
+
+// Structure to represent a clause in an HTTP Accept Header
+type Accept struct {
+ Type, SubType string
+ Q float64
+ Params map[string]string
+}
+
+// For internal use, so that we can use the sort interface
+type accept_slice []Accept
+
+func (accept accept_slice) Len() int {
+ slice := []Accept(accept)
+ return len(slice)
+}
+
+func (accept accept_slice) Less(i, j int) bool {
+ slice := []Accept(accept)
+ ai, aj := slice[i], slice[j]
+ if ai.Q > aj.Q {
+ return true
+ }
+ if ai.Type != "*" && aj.Type == "*" {
+ return true
+ }
+ if ai.SubType != "*" && aj.SubType == "*" {
+ return true
+ }
+ return false
+}
+
+func (accept accept_slice) Swap(i, j int) {
+ slice := []Accept(accept)
+ slice[i], slice[j] = slice[j], slice[i]
+}
+
+// Parse an Accept Header string returning a sorted list
+// of clauses
+func ParseAccept(header string) (accept []Accept) {
+ parts := strings.Split(header, ",")
+ accept = make([]Accept, 0, len(parts))
+ for _, part := range parts {
+ part := strings.Trim(part, " ")
+
+ a := Accept{}
+ a.Params = make(map[string]string)
+ a.Q = 1.0
+
+ mrp := strings.Split(part, ";")
+
+ media_range := mrp[0]
+ sp := strings.Split(media_range, "/")
+ a.Type = strings.Trim(sp[0], " ")
+
+ switch {
+ case len(sp) == 1 && a.Type == "*":
+ a.SubType = "*"
+ case len(sp) == 2:
+ a.SubType = strings.Trim(sp[1], " ")
+ default:
+ continue
+ }
+
+ if len(mrp) == 1 {
+ accept = append(accept, a)
+ continue
+ }
+
+ for _, param := range mrp[1:] {
+ sp := strings.SplitN(param, "=", 2)
+ if len(sp) != 2 {
+ continue
+ }
+ token := strings.Trim(sp[0], " ")
+ if token == "q" {
+ a.Q, _ = strconv.ParseFloat(sp[1], 32)
+ } else {
+ a.Params[token] = strings.Trim(sp[1], " ")
+ }
+ }
+
+ accept = append(accept, a)
+ }
+
+ slice := accept_slice(accept)
+ sort.Sort(slice)
+
+ return
+}
+
+// Negotiate the most appropriate content_type given the accept header
+// and a list of alternatives.
+func Negotiate(header string, alternatives []string) (content_type string) {
+ asp := make([][]string, 0, len(alternatives))
+ for _, ctype := range alternatives {
+ asp = append(asp, strings.SplitN(ctype, "/", 2))
+ }
+ for _, clause := range ParseAccept(header) {
+ for i, ctsp := range asp {
+ if clause.Type == ctsp[0] && clause.SubType == ctsp[1] {
+ content_type = alternatives[i]
+ return
+ }
+ if clause.Type == ctsp[0] && clause.SubType == "*" {
+ content_type = alternatives[i]
+ return
+ }
+ if clause.Type == "*" && clause.SubType == "*" {
+ content_type = alternatives[i]
+ return
+ }
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/prometheus/common/model/alert.go b/vendor/github.com/prometheus/common/model/alert.go
new file mode 100644
index 00000000..35e739c7
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/alert.go
@@ -0,0 +1,136 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "time"
+)
+
+type AlertStatus string
+
+const (
+ AlertFiring AlertStatus = "firing"
+ AlertResolved AlertStatus = "resolved"
+)
+
+// Alert is a generic representation of an alert in the Prometheus eco-system.
+type Alert struct {
+ // Label value pairs for purpose of aggregation, matching, and disposition
+ // dispatching. This must minimally include an "alertname" label.
+ Labels LabelSet `json:"labels"`
+
+ // Extra key/value information which does not define alert identity.
+ Annotations LabelSet `json:"annotations"`
+
+ // The known time range for this alert. Both ends are optional.
+ StartsAt time.Time `json:"startsAt,omitempty"`
+ EndsAt time.Time `json:"endsAt,omitempty"`
+ GeneratorURL string `json:"generatorURL"`
+}
+
+// Name returns the name of the alert. It is equivalent to the "alertname" label.
+func (a *Alert) Name() string {
+ return string(a.Labels[AlertNameLabel])
+}
+
+// Fingerprint returns a unique hash for the alert. It is equivalent to
+// the fingerprint of the alert's label set.
+func (a *Alert) Fingerprint() Fingerprint {
+ return a.Labels.Fingerprint()
+}
+
+func (a *Alert) String() string {
+ s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7])
+ if a.Resolved() {
+ return s + "[resolved]"
+ }
+ return s + "[active]"
+}
+
+// Resolved returns true iff the activity interval ended in the past.
+func (a *Alert) Resolved() bool {
+ return a.ResolvedAt(time.Now())
+}
+
+// ResolvedAt returns true off the activity interval ended before
+// the given timestamp.
+func (a *Alert) ResolvedAt(ts time.Time) bool {
+ if a.EndsAt.IsZero() {
+ return false
+ }
+ return !a.EndsAt.After(ts)
+}
+
+// Status returns the status of the alert.
+func (a *Alert) Status() AlertStatus {
+ if a.Resolved() {
+ return AlertResolved
+ }
+ return AlertFiring
+}
+
+// Validate checks whether the alert data is inconsistent.
+func (a *Alert) Validate() error {
+ if a.StartsAt.IsZero() {
+ return fmt.Errorf("start time missing")
+ }
+ if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) {
+ return fmt.Errorf("start time must be before end time")
+ }
+ if err := a.Labels.Validate(); err != nil {
+ return fmt.Errorf("invalid label set: %s", err)
+ }
+ if len(a.Labels) == 0 {
+ return fmt.Errorf("at least one label pair required")
+ }
+ if err := a.Annotations.Validate(); err != nil {
+ return fmt.Errorf("invalid annotations: %s", err)
+ }
+ return nil
+}
+
+// Alert is a list of alerts that can be sorted in chronological order.
+type Alerts []*Alert
+
+func (as Alerts) Len() int { return len(as) }
+func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] }
+
+func (as Alerts) Less(i, j int) bool {
+ if as[i].StartsAt.Before(as[j].StartsAt) {
+ return true
+ }
+ if as[i].EndsAt.Before(as[j].EndsAt) {
+ return true
+ }
+ return as[i].Fingerprint() < as[j].Fingerprint()
+}
+
+// HasFiring returns true iff one of the alerts is not resolved.
+func (as Alerts) HasFiring() bool {
+ for _, a := range as {
+ if !a.Resolved() {
+ return true
+ }
+ }
+ return false
+}
+
+// Status returns StatusFiring iff at least one of the alerts is firing.
+func (as Alerts) Status() AlertStatus {
+ if as.HasFiring() {
+ return AlertFiring
+ }
+ return AlertResolved
+}
diff --git a/vendor/github.com/prometheus/common/model/fingerprinting.go b/vendor/github.com/prometheus/common/model/fingerprinting.go
new file mode 100644
index 00000000..fc4de410
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/fingerprinting.go
@@ -0,0 +1,105 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "strconv"
+)
+
+// Fingerprint provides a hash-capable representation of a Metric.
+// For our purposes, FNV-1A 64-bit is used.
+type Fingerprint uint64
+
+// FingerprintFromString transforms a string representation into a Fingerprint.
+func FingerprintFromString(s string) (Fingerprint, error) {
+ num, err := strconv.ParseUint(s, 16, 64)
+ return Fingerprint(num), err
+}
+
+// ParseFingerprint parses the input string into a fingerprint.
+func ParseFingerprint(s string) (Fingerprint, error) {
+ num, err := strconv.ParseUint(s, 16, 64)
+ if err != nil {
+ return 0, err
+ }
+ return Fingerprint(num), nil
+}
+
+func (f Fingerprint) String() string {
+ return fmt.Sprintf("%016x", uint64(f))
+}
+
+// Fingerprints represents a collection of Fingerprint subject to a given
+// natural sorting scheme. It implements sort.Interface.
+type Fingerprints []Fingerprint
+
+// Len implements sort.Interface.
+func (f Fingerprints) Len() int {
+ return len(f)
+}
+
+// Less implements sort.Interface.
+func (f Fingerprints) Less(i, j int) bool {
+ return f[i] < f[j]
+}
+
+// Swap implements sort.Interface.
+func (f Fingerprints) Swap(i, j int) {
+ f[i], f[j] = f[j], f[i]
+}
+
+// FingerprintSet is a set of Fingerprints.
+type FingerprintSet map[Fingerprint]struct{}
+
+// Equal returns true if both sets contain the same elements (and not more).
+func (s FingerprintSet) Equal(o FingerprintSet) bool {
+ if len(s) != len(o) {
+ return false
+ }
+
+ for k := range s {
+ if _, ok := o[k]; !ok {
+ return false
+ }
+ }
+
+ return true
+}
+
+// Intersection returns the elements contained in both sets.
+func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet {
+ myLength, otherLength := len(s), len(o)
+ if myLength == 0 || otherLength == 0 {
+ return FingerprintSet{}
+ }
+
+ subSet := s
+ superSet := o
+
+ if otherLength < myLength {
+ subSet = o
+ superSet = s
+ }
+
+ out := FingerprintSet{}
+
+ for k := range subSet {
+ if _, ok := superSet[k]; ok {
+ out[k] = struct{}{}
+ }
+ }
+
+ return out
+}
diff --git a/vendor/github.com/prometheus/common/model/fnv.go b/vendor/github.com/prometheus/common/model/fnv.go
new file mode 100644
index 00000000..038fc1c9
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/fnv.go
@@ -0,0 +1,42 @@
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+// Inline and byte-free variant of hash/fnv's fnv64a.
+
+const (
+ offset64 = 14695981039346656037
+ prime64 = 1099511628211
+)
+
+// hashNew initializies a new fnv64a hash value.
+func hashNew() uint64 {
+ return offset64
+}
+
+// hashAdd adds a string to a fnv64a hash value, returning the updated hash.
+func hashAdd(h uint64, s string) uint64 {
+ for i := 0; i < len(s); i++ {
+ h ^= uint64(s[i])
+ h *= prime64
+ }
+ return h
+}
+
+// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash.
+func hashAddByte(h uint64, b byte) uint64 {
+ h ^= uint64(b)
+ h *= prime64
+ return h
+}
diff --git a/vendor/github.com/prometheus/common/model/labels.go b/vendor/github.com/prometheus/common/model/labels.go
new file mode 100644
index 00000000..41051a01
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/labels.go
@@ -0,0 +1,210 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "strings"
+ "unicode/utf8"
+)
+
+const (
+ // AlertNameLabel is the name of the label containing the an alert's name.
+ AlertNameLabel = "alertname"
+
+ // ExportedLabelPrefix is the prefix to prepend to the label names present in
+ // exported metrics if a label of the same name is added by the server.
+ ExportedLabelPrefix = "exported_"
+
+ // MetricNameLabel is the label name indicating the metric name of a
+ // timeseries.
+ MetricNameLabel = "__name__"
+
+ // SchemeLabel is the name of the label that holds the scheme on which to
+ // scrape a target.
+ SchemeLabel = "__scheme__"
+
+ // AddressLabel is the name of the label that holds the address of
+ // a scrape target.
+ AddressLabel = "__address__"
+
+ // MetricsPathLabel is the name of the label that holds the path on which to
+ // scrape a target.
+ MetricsPathLabel = "__metrics_path__"
+
+ // ReservedLabelPrefix is a prefix which is not legal in user-supplied
+ // label names.
+ ReservedLabelPrefix = "__"
+
+ // MetaLabelPrefix is a prefix for labels that provide meta information.
+ // Labels with this prefix are used for intermediate label processing and
+ // will not be attached to time series.
+ MetaLabelPrefix = "__meta_"
+
+ // TmpLabelPrefix is a prefix for temporary labels as part of relabelling.
+ // Labels with this prefix are used for intermediate label processing and
+ // will not be attached to time series. This is reserved for use in
+ // Prometheus configuration files by users.
+ TmpLabelPrefix = "__tmp_"
+
+ // ParamLabelPrefix is a prefix for labels that provide URL parameters
+ // used to scrape a target.
+ ParamLabelPrefix = "__param_"
+
+ // JobLabel is the label name indicating the job from which a timeseries
+ // was scraped.
+ JobLabel = "job"
+
+ // InstanceLabel is the label name used for the instance label.
+ InstanceLabel = "instance"
+
+ // BucketLabel is used for the label that defines the upper bound of a
+ // bucket of a histogram ("le" -> "less or equal").
+ BucketLabel = "le"
+
+ // QuantileLabel is used for the label that defines the quantile in a
+ // summary.
+ QuantileLabel = "quantile"
+)
+
+// LabelNameRE is a regular expression matching valid label names. Note that the
+// IsValid method of LabelName performs the same check but faster than a match
+// with this regular expression.
+var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
+
+// A LabelName is a key for a LabelSet or Metric. It has a value associated
+// therewith.
+type LabelName string
+
+// IsValid is true iff the label name matches the pattern of LabelNameRE. This
+// method, however, does not use LabelNameRE for the check but a much faster
+// hardcoded implementation.
+func (ln LabelName) IsValid() bool {
+ if len(ln) == 0 {
+ return false
+ }
+ for i, b := range ln {
+ if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
+ return false
+ }
+ }
+ return true
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ if err := unmarshal(&s); err != nil {
+ return err
+ }
+ if !LabelName(s).IsValid() {
+ return fmt.Errorf("%q is not a valid label name", s)
+ }
+ *ln = LabelName(s)
+ return nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (ln *LabelName) UnmarshalJSON(b []byte) error {
+ var s string
+ if err := json.Unmarshal(b, &s); err != nil {
+ return err
+ }
+ if !LabelName(s).IsValid() {
+ return fmt.Errorf("%q is not a valid label name", s)
+ }
+ *ln = LabelName(s)
+ return nil
+}
+
+// LabelNames is a sortable LabelName slice. In implements sort.Interface.
+type LabelNames []LabelName
+
+func (l LabelNames) Len() int {
+ return len(l)
+}
+
+func (l LabelNames) Less(i, j int) bool {
+ return l[i] < l[j]
+}
+
+func (l LabelNames) Swap(i, j int) {
+ l[i], l[j] = l[j], l[i]
+}
+
+func (l LabelNames) String() string {
+ labelStrings := make([]string, 0, len(l))
+ for _, label := range l {
+ labelStrings = append(labelStrings, string(label))
+ }
+ return strings.Join(labelStrings, ", ")
+}
+
+// A LabelValue is an associated value for a LabelName.
+type LabelValue string
+
+// IsValid returns true iff the string is a valid UTF8.
+func (lv LabelValue) IsValid() bool {
+ return utf8.ValidString(string(lv))
+}
+
+// LabelValues is a sortable LabelValue slice. It implements sort.Interface.
+type LabelValues []LabelValue
+
+func (l LabelValues) Len() int {
+ return len(l)
+}
+
+func (l LabelValues) Less(i, j int) bool {
+ return string(l[i]) < string(l[j])
+}
+
+func (l LabelValues) Swap(i, j int) {
+ l[i], l[j] = l[j], l[i]
+}
+
+// LabelPair pairs a name with a value.
+type LabelPair struct {
+ Name LabelName
+ Value LabelValue
+}
+
+// LabelPairs is a sortable slice of LabelPair pointers. It implements
+// sort.Interface.
+type LabelPairs []*LabelPair
+
+func (l LabelPairs) Len() int {
+ return len(l)
+}
+
+func (l LabelPairs) Less(i, j int) bool {
+ switch {
+ case l[i].Name > l[j].Name:
+ return false
+ case l[i].Name < l[j].Name:
+ return true
+ case l[i].Value > l[j].Value:
+ return false
+ case l[i].Value < l[j].Value:
+ return true
+ default:
+ return false
+ }
+}
+
+func (l LabelPairs) Swap(i, j int) {
+ l[i], l[j] = l[j], l[i]
+}
diff --git a/vendor/github.com/prometheus/common/model/labelset.go b/vendor/github.com/prometheus/common/model/labelset.go
new file mode 100644
index 00000000..6eda08a7
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/labelset.go
@@ -0,0 +1,169 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet
+// may be fully-qualified down to the point where it may resolve to a single
+// Metric in the data store or not. All operations that occur within the realm
+// of a LabelSet can emit a vector of Metric entities to which the LabelSet may
+// match.
+type LabelSet map[LabelName]LabelValue
+
+// Validate checks whether all names and values in the label set
+// are valid.
+func (ls LabelSet) Validate() error {
+ for ln, lv := range ls {
+ if !ln.IsValid() {
+ return fmt.Errorf("invalid name %q", ln)
+ }
+ if !lv.IsValid() {
+ return fmt.Errorf("invalid value %q", lv)
+ }
+ }
+ return nil
+}
+
+// Equal returns true iff both label sets have exactly the same key/value pairs.
+func (ls LabelSet) Equal(o LabelSet) bool {
+ if len(ls) != len(o) {
+ return false
+ }
+ for ln, lv := range ls {
+ olv, ok := o[ln]
+ if !ok {
+ return false
+ }
+ if olv != lv {
+ return false
+ }
+ }
+ return true
+}
+
+// Before compares the metrics, using the following criteria:
+//
+// If m has fewer labels than o, it is before o. If it has more, it is not.
+//
+// If the number of labels is the same, the superset of all label names is
+// sorted alphanumerically. The first differing label pair found in that order
+// determines the outcome: If the label does not exist at all in m, then m is
+// before o, and vice versa. Otherwise the label value is compared
+// alphanumerically.
+//
+// If m and o are equal, the method returns false.
+func (ls LabelSet) Before(o LabelSet) bool {
+ if len(ls) < len(o) {
+ return true
+ }
+ if len(ls) > len(o) {
+ return false
+ }
+
+ lns := make(LabelNames, 0, len(ls)+len(o))
+ for ln := range ls {
+ lns = append(lns, ln)
+ }
+ for ln := range o {
+ lns = append(lns, ln)
+ }
+ // It's probably not worth it to de-dup lns.
+ sort.Sort(lns)
+ for _, ln := range lns {
+ mlv, ok := ls[ln]
+ if !ok {
+ return true
+ }
+ olv, ok := o[ln]
+ if !ok {
+ return false
+ }
+ if mlv < olv {
+ return true
+ }
+ if mlv > olv {
+ return false
+ }
+ }
+ return false
+}
+
+// Clone returns a copy of the label set.
+func (ls LabelSet) Clone() LabelSet {
+ lsn := make(LabelSet, len(ls))
+ for ln, lv := range ls {
+ lsn[ln] = lv
+ }
+ return lsn
+}
+
+// Merge is a helper function to non-destructively merge two label sets.
+func (l LabelSet) Merge(other LabelSet) LabelSet {
+ result := make(LabelSet, len(l))
+
+ for k, v := range l {
+ result[k] = v
+ }
+
+ for k, v := range other {
+ result[k] = v
+ }
+
+ return result
+}
+
+func (l LabelSet) String() string {
+ lstrs := make([]string, 0, len(l))
+ for l, v := range l {
+ lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v))
+ }
+
+ sort.Strings(lstrs)
+ return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
+}
+
+// Fingerprint returns the LabelSet's fingerprint.
+func (ls LabelSet) Fingerprint() Fingerprint {
+ return labelSetToFingerprint(ls)
+}
+
+// FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing
+// algorithm, which is, however, more susceptible to hash collisions.
+func (ls LabelSet) FastFingerprint() Fingerprint {
+ return labelSetToFastFingerprint(ls)
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (l *LabelSet) UnmarshalJSON(b []byte) error {
+ var m map[LabelName]LabelValue
+ if err := json.Unmarshal(b, &m); err != nil {
+ return err
+ }
+ // encoding/json only unmarshals maps of the form map[string]T. It treats
+ // LabelName as a string and does not call its UnmarshalJSON method.
+ // Thus, we have to replicate the behavior here.
+ for ln := range m {
+ if !ln.IsValid() {
+ return fmt.Errorf("%q is not a valid label name", ln)
+ }
+ }
+ *l = LabelSet(m)
+ return nil
+}
diff --git a/vendor/github.com/prometheus/common/model/metric.go b/vendor/github.com/prometheus/common/model/metric.go
new file mode 100644
index 00000000..f7250909
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/metric.go
@@ -0,0 +1,103 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "regexp"
+ "sort"
+ "strings"
+)
+
+var (
+ separator = []byte{0}
+ // MetricNameRE is a regular expression matching valid metric
+ // names. Note that the IsValidMetricName function performs the same
+ // check but faster than a match with this regular expression.
+ MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`)
+)
+
+// A Metric is similar to a LabelSet, but the key difference is that a Metric is
+// a singleton and refers to one and only one stream of samples.
+type Metric LabelSet
+
+// Equal compares the metrics.
+func (m Metric) Equal(o Metric) bool {
+ return LabelSet(m).Equal(LabelSet(o))
+}
+
+// Before compares the metrics' underlying label sets.
+func (m Metric) Before(o Metric) bool {
+ return LabelSet(m).Before(LabelSet(o))
+}
+
+// Clone returns a copy of the Metric.
+func (m Metric) Clone() Metric {
+ clone := make(Metric, len(m))
+ for k, v := range m {
+ clone[k] = v
+ }
+ return clone
+}
+
+func (m Metric) String() string {
+ metricName, hasName := m[MetricNameLabel]
+ numLabels := len(m) - 1
+ if !hasName {
+ numLabels = len(m)
+ }
+ labelStrings := make([]string, 0, numLabels)
+ for label, value := range m {
+ if label != MetricNameLabel {
+ labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
+ }
+ }
+
+ switch numLabels {
+ case 0:
+ if hasName {
+ return string(metricName)
+ }
+ return "{}"
+ default:
+ sort.Strings(labelStrings)
+ return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", "))
+ }
+}
+
+// Fingerprint returns a Metric's Fingerprint.
+func (m Metric) Fingerprint() Fingerprint {
+ return LabelSet(m).Fingerprint()
+}
+
+// FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing
+// algorithm, which is, however, more susceptible to hash collisions.
+func (m Metric) FastFingerprint() Fingerprint {
+ return LabelSet(m).FastFingerprint()
+}
+
+// IsValidMetricName returns true iff name matches the pattern of MetricNameRE.
+// This function, however, does not use MetricNameRE for the check but a much
+// faster hardcoded implementation.
+func IsValidMetricName(n LabelValue) bool {
+ if len(n) == 0 {
+ return false
+ }
+ for i, b := range n {
+ if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/prometheus/common/model/model.go b/vendor/github.com/prometheus/common/model/model.go
new file mode 100644
index 00000000..a7b96917
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/model.go
@@ -0,0 +1,16 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package model contains common data structures that are shared across
+// Prometheus components and libraries.
+package model
diff --git a/vendor/github.com/prometheus/common/model/signature.go b/vendor/github.com/prometheus/common/model/signature.go
new file mode 100644
index 00000000..8762b13c
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/signature.go
@@ -0,0 +1,144 @@
+// Copyright 2014 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "sort"
+)
+
+// SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is
+// used to separate label names, label values, and other strings from each other
+// when calculating their combined hash value (aka signature aka fingerprint).
+const SeparatorByte byte = 255
+
+var (
+ // cache the signature of an empty label set.
+ emptyLabelSignature = hashNew()
+)
+
+// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
+// given label set. (Collisions are possible but unlikely if the number of label
+// sets the function is applied to is small.)
+func LabelsToSignature(labels map[string]string) uint64 {
+ if len(labels) == 0 {
+ return emptyLabelSignature
+ }
+
+ labelNames := make([]string, 0, len(labels))
+ for labelName := range labels {
+ labelNames = append(labelNames, labelName)
+ }
+ sort.Strings(labelNames)
+
+ sum := hashNew()
+ for _, labelName := range labelNames {
+ sum = hashAdd(sum, labelName)
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, labels[labelName])
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return sum
+}
+
+// labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as
+// parameter (rather than a label map) and returns a Fingerprint.
+func labelSetToFingerprint(ls LabelSet) Fingerprint {
+ if len(ls) == 0 {
+ return Fingerprint(emptyLabelSignature)
+ }
+
+ labelNames := make(LabelNames, 0, len(ls))
+ for labelName := range ls {
+ labelNames = append(labelNames, labelName)
+ }
+ sort.Sort(labelNames)
+
+ sum := hashNew()
+ for _, labelName := range labelNames {
+ sum = hashAdd(sum, string(labelName))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(ls[labelName]))
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return Fingerprint(sum)
+}
+
+// labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a
+// faster and less allocation-heavy hash function, which is more susceptible to
+// create hash collisions. Therefore, collision detection should be applied.
+func labelSetToFastFingerprint(ls LabelSet) Fingerprint {
+ if len(ls) == 0 {
+ return Fingerprint(emptyLabelSignature)
+ }
+
+ var result uint64
+ for labelName, labelValue := range ls {
+ sum := hashNew()
+ sum = hashAdd(sum, string(labelName))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(labelValue))
+ result ^= sum
+ }
+ return Fingerprint(result)
+}
+
+// SignatureForLabels works like LabelsToSignature but takes a Metric as
+// parameter (rather than a label map) and only includes the labels with the
+// specified LabelNames into the signature calculation. The labels passed in
+// will be sorted by this function.
+func SignatureForLabels(m Metric, labels ...LabelName) uint64 {
+ if len(labels) == 0 {
+ return emptyLabelSignature
+ }
+
+ sort.Sort(LabelNames(labels))
+
+ sum := hashNew()
+ for _, label := range labels {
+ sum = hashAdd(sum, string(label))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(m[label]))
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return sum
+}
+
+// SignatureWithoutLabels works like LabelsToSignature but takes a Metric as
+// parameter (rather than a label map) and excludes the labels with any of the
+// specified LabelNames from the signature calculation.
+func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 {
+ if len(m) == 0 {
+ return emptyLabelSignature
+ }
+
+ labelNames := make(LabelNames, 0, len(m))
+ for labelName := range m {
+ if _, exclude := labels[labelName]; !exclude {
+ labelNames = append(labelNames, labelName)
+ }
+ }
+ if len(labelNames) == 0 {
+ return emptyLabelSignature
+ }
+ sort.Sort(labelNames)
+
+ sum := hashNew()
+ for _, labelName := range labelNames {
+ sum = hashAdd(sum, string(labelName))
+ sum = hashAddByte(sum, SeparatorByte)
+ sum = hashAdd(sum, string(m[labelName]))
+ sum = hashAddByte(sum, SeparatorByte)
+ }
+ return sum
+}
diff --git a/vendor/github.com/prometheus/common/model/silence.go b/vendor/github.com/prometheus/common/model/silence.go
new file mode 100644
index 00000000..bb99889d
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/silence.go
@@ -0,0 +1,106 @@
+// Copyright 2015 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "time"
+)
+
+// Matcher describes a matches the value of a given label.
+type Matcher struct {
+ Name LabelName `json:"name"`
+ Value string `json:"value"`
+ IsRegex bool `json:"isRegex"`
+}
+
+func (m *Matcher) UnmarshalJSON(b []byte) error {
+ type plain Matcher
+ if err := json.Unmarshal(b, (*plain)(m)); err != nil {
+ return err
+ }
+
+ if len(m.Name) == 0 {
+ return fmt.Errorf("label name in matcher must not be empty")
+ }
+ if m.IsRegex {
+ if _, err := regexp.Compile(m.Value); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Validate returns true iff all fields of the matcher have valid values.
+func (m *Matcher) Validate() error {
+ if !m.Name.IsValid() {
+ return fmt.Errorf("invalid name %q", m.Name)
+ }
+ if m.IsRegex {
+ if _, err := regexp.Compile(m.Value); err != nil {
+ return fmt.Errorf("invalid regular expression %q", m.Value)
+ }
+ } else if !LabelValue(m.Value).IsValid() || len(m.Value) == 0 {
+ return fmt.Errorf("invalid value %q", m.Value)
+ }
+ return nil
+}
+
+// Silence defines the representation of a silence definition in the Prometheus
+// eco-system.
+type Silence struct {
+ ID uint64 `json:"id,omitempty"`
+
+ Matchers []*Matcher `json:"matchers"`
+
+ StartsAt time.Time `json:"startsAt"`
+ EndsAt time.Time `json:"endsAt"`
+
+ CreatedAt time.Time `json:"createdAt,omitempty"`
+ CreatedBy string `json:"createdBy"`
+ Comment string `json:"comment,omitempty"`
+}
+
+// Validate returns true iff all fields of the silence have valid values.
+func (s *Silence) Validate() error {
+ if len(s.Matchers) == 0 {
+ return fmt.Errorf("at least one matcher required")
+ }
+ for _, m := range s.Matchers {
+ if err := m.Validate(); err != nil {
+ return fmt.Errorf("invalid matcher: %s", err)
+ }
+ }
+ if s.StartsAt.IsZero() {
+ return fmt.Errorf("start time missing")
+ }
+ if s.EndsAt.IsZero() {
+ return fmt.Errorf("end time missing")
+ }
+ if s.EndsAt.Before(s.StartsAt) {
+ return fmt.Errorf("start time must be before end time")
+ }
+ if s.CreatedBy == "" {
+ return fmt.Errorf("creator information missing")
+ }
+ if s.Comment == "" {
+ return fmt.Errorf("comment missing")
+ }
+ if s.CreatedAt.IsZero() {
+ return fmt.Errorf("creation timestamp missing")
+ }
+ return nil
+}
diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go
new file mode 100644
index 00000000..74ed5a9f
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/time.go
@@ -0,0 +1,264 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "fmt"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+const (
+ // MinimumTick is the minimum supported time resolution. This has to be
+ // at least time.Second in order for the code below to work.
+ minimumTick = time.Millisecond
+ // second is the Time duration equivalent to one second.
+ second = int64(time.Second / minimumTick)
+ // The number of nanoseconds per minimum tick.
+ nanosPerTick = int64(minimumTick / time.Nanosecond)
+
+ // Earliest is the earliest Time representable. Handy for
+ // initializing a high watermark.
+ Earliest = Time(math.MinInt64)
+ // Latest is the latest Time representable. Handy for initializing
+ // a low watermark.
+ Latest = Time(math.MaxInt64)
+)
+
+// Time is the number of milliseconds since the epoch
+// (1970-01-01 00:00 UTC) excluding leap seconds.
+type Time int64
+
+// Interval describes and interval between two timestamps.
+type Interval struct {
+ Start, End Time
+}
+
+// Now returns the current time as a Time.
+func Now() Time {
+ return TimeFromUnixNano(time.Now().UnixNano())
+}
+
+// TimeFromUnix returns the Time equivalent to the Unix Time t
+// provided in seconds.
+func TimeFromUnix(t int64) Time {
+ return Time(t * second)
+}
+
+// TimeFromUnixNano returns the Time equivalent to the Unix Time
+// t provided in nanoseconds.
+func TimeFromUnixNano(t int64) Time {
+ return Time(t / nanosPerTick)
+}
+
+// Equal reports whether two Times represent the same instant.
+func (t Time) Equal(o Time) bool {
+ return t == o
+}
+
+// Before reports whether the Time t is before o.
+func (t Time) Before(o Time) bool {
+ return t < o
+}
+
+// After reports whether the Time t is after o.
+func (t Time) After(o Time) bool {
+ return t > o
+}
+
+// Add returns the Time t + d.
+func (t Time) Add(d time.Duration) Time {
+ return t + Time(d/minimumTick)
+}
+
+// Sub returns the Duration t - o.
+func (t Time) Sub(o Time) time.Duration {
+ return time.Duration(t-o) * minimumTick
+}
+
+// Time returns the time.Time representation of t.
+func (t Time) Time() time.Time {
+ return time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick)
+}
+
+// Unix returns t as a Unix time, the number of seconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) Unix() int64 {
+ return int64(t) / second
+}
+
+// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) UnixNano() int64 {
+ return int64(t) * nanosPerTick
+}
+
+// The number of digits after the dot.
+var dotPrecision = int(math.Log10(float64(second)))
+
+// String returns a string representation of the Time.
+func (t Time) String() string {
+ return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (t Time) MarshalJSON() ([]byte, error) {
+ return []byte(t.String()), nil
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (t *Time) UnmarshalJSON(b []byte) error {
+ p := strings.Split(string(b), ".")
+ switch len(p) {
+ case 1:
+ v, err := strconv.ParseInt(string(p[0]), 10, 64)
+ if err != nil {
+ return err
+ }
+ *t = Time(v * second)
+
+ case 2:
+ v, err := strconv.ParseInt(string(p[0]), 10, 64)
+ if err != nil {
+ return err
+ }
+ v *= second
+
+ prec := dotPrecision - len(p[1])
+ if prec < 0 {
+ p[1] = p[1][:dotPrecision]
+ } else if prec > 0 {
+ p[1] = p[1] + strings.Repeat("0", prec)
+ }
+
+ va, err := strconv.ParseInt(p[1], 10, 32)
+ if err != nil {
+ return err
+ }
+
+ *t = Time(v + va)
+
+ default:
+ return fmt.Errorf("invalid time %q", string(b))
+ }
+ return nil
+}
+
+// Duration wraps time.Duration. It is used to parse the custom duration format
+// from YAML.
+// This type should not propagate beyond the scope of input/output processing.
+type Duration time.Duration
+
+// Set implements pflag/flag.Value
+func (d *Duration) Set(s string) error {
+ var err error
+ *d, err = ParseDuration(s)
+ return err
+}
+
+// Type implements pflag.Value
+func (d *Duration) Type() string {
+ return "duration"
+}
+
+var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$")
+
+// ParseDuration parses a string into a time.Duration, assuming that a year
+// always has 365d, a week always has 7d, and a day always has 24h.
+func ParseDuration(durationStr string) (Duration, error) {
+ matches := durationRE.FindStringSubmatch(durationStr)
+ if len(matches) != 3 {
+ return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
+ }
+ var (
+ n, _ = strconv.Atoi(matches[1])
+ dur = time.Duration(n) * time.Millisecond
+ )
+ switch unit := matches[2]; unit {
+ case "y":
+ dur *= 1000 * 60 * 60 * 24 * 365
+ case "w":
+ dur *= 1000 * 60 * 60 * 24 * 7
+ case "d":
+ dur *= 1000 * 60 * 60 * 24
+ case "h":
+ dur *= 1000 * 60 * 60
+ case "m":
+ dur *= 1000 * 60
+ case "s":
+ dur *= 1000
+ case "ms":
+ // Value already correct
+ default:
+ return 0, fmt.Errorf("invalid time unit in duration string: %q", unit)
+ }
+ return Duration(dur), nil
+}
+
+func (d Duration) String() string {
+ var (
+ ms = int64(time.Duration(d) / time.Millisecond)
+ unit = "ms"
+ )
+ if ms == 0 {
+ return "0s"
+ }
+ factors := map[string]int64{
+ "y": 1000 * 60 * 60 * 24 * 365,
+ "w": 1000 * 60 * 60 * 24 * 7,
+ "d": 1000 * 60 * 60 * 24,
+ "h": 1000 * 60 * 60,
+ "m": 1000 * 60,
+ "s": 1000,
+ "ms": 1,
+ }
+
+ switch int64(0) {
+ case ms % factors["y"]:
+ unit = "y"
+ case ms % factors["w"]:
+ unit = "w"
+ case ms % factors["d"]:
+ unit = "d"
+ case ms % factors["h"]:
+ unit = "h"
+ case ms % factors["m"]:
+ unit = "m"
+ case ms % factors["s"]:
+ unit = "s"
+ }
+ return fmt.Sprintf("%v%v", ms/factors[unit], unit)
+}
+
+// MarshalYAML implements the yaml.Marshaler interface.
+func (d Duration) MarshalYAML() (interface{}, error) {
+ return d.String(), nil
+}
+
+// UnmarshalYAML implements the yaml.Unmarshaler interface.
+func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ if err := unmarshal(&s); err != nil {
+ return err
+ }
+ dur, err := ParseDuration(s)
+ if err != nil {
+ return err
+ }
+ *d = dur
+ return nil
+}
diff --git a/vendor/github.com/prometheus/common/model/value.go b/vendor/github.com/prometheus/common/model/value.go
new file mode 100644
index 00000000..c9d8fb1a
--- /dev/null
+++ b/vendor/github.com/prometheus/common/model/value.go
@@ -0,0 +1,416 @@
+// Copyright 2013 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package model
+
+import (
+ "encoding/json"
+ "fmt"
+ "math"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+var (
+ // ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
+ // non-existing sample pair. It is a SamplePair with timestamp Earliest and
+ // value 0.0. Note that the natural zero value of SamplePair has a timestamp
+ // of 0, which is possible to appear in a real SamplePair and thus not
+ // suitable to signal a non-existing SamplePair.
+ ZeroSamplePair = SamplePair{Timestamp: Earliest}
+
+ // ZeroSample is the pseudo zero-value of Sample used to signal a
+ // non-existing sample. It is a Sample with timestamp Earliest, value 0.0,
+ // and metric nil. Note that the natural zero value of Sample has a timestamp
+ // of 0, which is possible to appear in a real Sample and thus not suitable
+ // to signal a non-existing Sample.
+ ZeroSample = Sample{Timestamp: Earliest}
+)
+
+// A SampleValue is a representation of a value for a given sample at a given
+// time.
+type SampleValue float64
+
+// MarshalJSON implements json.Marshaler.
+func (v SampleValue) MarshalJSON() ([]byte, error) {
+ return json.Marshal(v.String())
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (v *SampleValue) UnmarshalJSON(b []byte) error {
+ if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
+ return fmt.Errorf("sample value must be a quoted string")
+ }
+ f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
+ if err != nil {
+ return err
+ }
+ *v = SampleValue(f)
+ return nil
+}
+
+// Equal returns true if the value of v and o is equal or if both are NaN. Note
+// that v==o is false if both are NaN. If you want the conventional float
+// behavior, use == to compare two SampleValues.
+func (v SampleValue) Equal(o SampleValue) bool {
+ if v == o {
+ return true
+ }
+ return math.IsNaN(float64(v)) && math.IsNaN(float64(o))
+}
+
+func (v SampleValue) String() string {
+ return strconv.FormatFloat(float64(v), 'f', -1, 64)
+}
+
+// SamplePair pairs a SampleValue with a Timestamp.
+type SamplePair struct {
+ Timestamp Time
+ Value SampleValue
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s SamplePair) MarshalJSON() ([]byte, error) {
+ t, err := json.Marshal(s.Timestamp)
+ if err != nil {
+ return nil, err
+ }
+ v, err := json.Marshal(s.Value)
+ if err != nil {
+ return nil, err
+ }
+ return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *SamplePair) UnmarshalJSON(b []byte) error {
+ v := [...]json.Unmarshaler{&s.Timestamp, &s.Value}
+ return json.Unmarshal(b, &v)
+}
+
+// Equal returns true if this SamplePair and o have equal Values and equal
+// Timestamps. The semantics of Value equality is defined by SampleValue.Equal.
+func (s *SamplePair) Equal(o *SamplePair) bool {
+ return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp))
+}
+
+func (s SamplePair) String() string {
+ return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp)
+}
+
+// Sample is a sample pair associated with a metric.
+type Sample struct {
+ Metric Metric `json:"metric"`
+ Value SampleValue `json:"value"`
+ Timestamp Time `json:"timestamp"`
+}
+
+// Equal compares first the metrics, then the timestamp, then the value. The
+// semantics of value equality is defined by SampleValue.Equal.
+func (s *Sample) Equal(o *Sample) bool {
+ if s == o {
+ return true
+ }
+
+ if !s.Metric.Equal(o.Metric) {
+ return false
+ }
+ if !s.Timestamp.Equal(o.Timestamp) {
+ return false
+ }
+
+ return s.Value.Equal(o.Value)
+}
+
+func (s Sample) String() string {
+ return fmt.Sprintf("%s => %s", s.Metric, SamplePair{
+ Timestamp: s.Timestamp,
+ Value: s.Value,
+ })
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s Sample) MarshalJSON() ([]byte, error) {
+ v := struct {
+ Metric Metric `json:"metric"`
+ Value SamplePair `json:"value"`
+ }{
+ Metric: s.Metric,
+ Value: SamplePair{
+ Timestamp: s.Timestamp,
+ Value: s.Value,
+ },
+ }
+
+ return json.Marshal(&v)
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *Sample) UnmarshalJSON(b []byte) error {
+ v := struct {
+ Metric Metric `json:"metric"`
+ Value SamplePair `json:"value"`
+ }{
+ Metric: s.Metric,
+ Value: SamplePair{
+ Timestamp: s.Timestamp,
+ Value: s.Value,
+ },
+ }
+
+ if err := json.Unmarshal(b, &v); err != nil {
+ return err
+ }
+
+ s.Metric = v.Metric
+ s.Timestamp = v.Value.Timestamp
+ s.Value = v.Value.Value
+
+ return nil
+}
+
+// Samples is a sortable Sample slice. It implements sort.Interface.
+type Samples []*Sample
+
+func (s Samples) Len() int {
+ return len(s)
+}
+
+// Less compares first the metrics, then the timestamp.
+func (s Samples) Less(i, j int) bool {
+ switch {
+ case s[i].Metric.Before(s[j].Metric):
+ return true
+ case s[j].Metric.Before(s[i].Metric):
+ return false
+ case s[i].Timestamp.Before(s[j].Timestamp):
+ return true
+ default:
+ return false
+ }
+}
+
+func (s Samples) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+// Equal compares two sets of samples and returns true if they are equal.
+func (s Samples) Equal(o Samples) bool {
+ if len(s) != len(o) {
+ return false
+ }
+
+ for i, sample := range s {
+ if !sample.Equal(o[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// SampleStream is a stream of Values belonging to an attached COWMetric.
+type SampleStream struct {
+ Metric Metric `json:"metric"`
+ Values []SamplePair `json:"values"`
+}
+
+func (ss SampleStream) String() string {
+ vals := make([]string, len(ss.Values))
+ for i, v := range ss.Values {
+ vals[i] = v.String()
+ }
+ return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n"))
+}
+
+// Value is a generic interface for values resulting from a query evaluation.
+type Value interface {
+ Type() ValueType
+ String() string
+}
+
+func (Matrix) Type() ValueType { return ValMatrix }
+func (Vector) Type() ValueType { return ValVector }
+func (*Scalar) Type() ValueType { return ValScalar }
+func (*String) Type() ValueType { return ValString }
+
+type ValueType int
+
+const (
+ ValNone ValueType = iota
+ ValScalar
+ ValVector
+ ValMatrix
+ ValString
+)
+
+// MarshalJSON implements json.Marshaler.
+func (et ValueType) MarshalJSON() ([]byte, error) {
+ return json.Marshal(et.String())
+}
+
+func (et *ValueType) UnmarshalJSON(b []byte) error {
+ var s string
+ if err := json.Unmarshal(b, &s); err != nil {
+ return err
+ }
+ switch s {
+ case "":
+ *et = ValNone
+ case "scalar":
+ *et = ValScalar
+ case "vector":
+ *et = ValVector
+ case "matrix":
+ *et = ValMatrix
+ case "string":
+ *et = ValString
+ default:
+ return fmt.Errorf("unknown value type %q", s)
+ }
+ return nil
+}
+
+func (e ValueType) String() string {
+ switch e {
+ case ValNone:
+ return ""
+ case ValScalar:
+ return "scalar"
+ case ValVector:
+ return "vector"
+ case ValMatrix:
+ return "matrix"
+ case ValString:
+ return "string"
+ }
+ panic("ValueType.String: unhandled value type")
+}
+
+// Scalar is a scalar value evaluated at the set timestamp.
+type Scalar struct {
+ Value SampleValue `json:"value"`
+ Timestamp Time `json:"timestamp"`
+}
+
+func (s Scalar) String() string {
+ return fmt.Sprintf("scalar: %v @[%v]", s.Value, s.Timestamp)
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s Scalar) MarshalJSON() ([]byte, error) {
+ v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64)
+ return json.Marshal([...]interface{}{s.Timestamp, string(v)})
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *Scalar) UnmarshalJSON(b []byte) error {
+ var f string
+ v := [...]interface{}{&s.Timestamp, &f}
+
+ if err := json.Unmarshal(b, &v); err != nil {
+ return err
+ }
+
+ value, err := strconv.ParseFloat(f, 64)
+ if err != nil {
+ return fmt.Errorf("error parsing sample value: %s", err)
+ }
+ s.Value = SampleValue(value)
+ return nil
+}
+
+// String is a string value evaluated at the set timestamp.
+type String struct {
+ Value string `json:"value"`
+ Timestamp Time `json:"timestamp"`
+}
+
+func (s *String) String() string {
+ return s.Value
+}
+
+// MarshalJSON implements json.Marshaler.
+func (s String) MarshalJSON() ([]byte, error) {
+ return json.Marshal([]interface{}{s.Timestamp, s.Value})
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (s *String) UnmarshalJSON(b []byte) error {
+ v := [...]interface{}{&s.Timestamp, &s.Value}
+ return json.Unmarshal(b, &v)
+}
+
+// Vector is basically only an alias for Samples, but the
+// contract is that in a Vector, all Samples have the same timestamp.
+type Vector []*Sample
+
+func (vec Vector) String() string {
+ entries := make([]string, len(vec))
+ for i, s := range vec {
+ entries[i] = s.String()
+ }
+ return strings.Join(entries, "\n")
+}
+
+func (vec Vector) Len() int { return len(vec) }
+func (vec Vector) Swap(i, j int) { vec[i], vec[j] = vec[j], vec[i] }
+
+// Less compares first the metrics, then the timestamp.
+func (vec Vector) Less(i, j int) bool {
+ switch {
+ case vec[i].Metric.Before(vec[j].Metric):
+ return true
+ case vec[j].Metric.Before(vec[i].Metric):
+ return false
+ case vec[i].Timestamp.Before(vec[j].Timestamp):
+ return true
+ default:
+ return false
+ }
+}
+
+// Equal compares two sets of samples and returns true if they are equal.
+func (vec Vector) Equal(o Vector) bool {
+ if len(vec) != len(o) {
+ return false
+ }
+
+ for i, sample := range vec {
+ if !sample.Equal(o[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// Matrix is a list of time series.
+type Matrix []*SampleStream
+
+func (m Matrix) Len() int { return len(m) }
+func (m Matrix) Less(i, j int) bool { return m[i].Metric.Before(m[j].Metric) }
+func (m Matrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
+
+func (mat Matrix) String() string {
+ matCp := make(Matrix, len(mat))
+ copy(matCp, mat)
+ sort.Sort(matCp)
+
+ strs := make([]string, len(matCp))
+
+ for i, ss := range matCp {
+ strs[i] = ss.String()
+ }
+
+ return strings.Join(strs, "\n")
+}
diff --git a/vendor/github.com/prometheus/procfs/LICENSE b/vendor/github.com/prometheus/procfs/LICENSE
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/prometheus/procfs/NOTICE b/vendor/github.com/prometheus/procfs/NOTICE
new file mode 100644
index 00000000..53c5e9aa
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/NOTICE
@@ -0,0 +1,7 @@
+procfs provides functions to retrieve system, kernel and process
+metrics from the pseudo-filesystem proc.
+
+Copyright 2014-2015 The Prometheus Authors
+
+This product includes software developed at
+SoundCloud Ltd. (http://soundcloud.com/).
diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go
new file mode 100644
index 00000000..d3a82680
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/buddyinfo.go
@@ -0,0 +1,95 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// A BuddyInfo is the details parsed from /proc/buddyinfo.
+// The data is comprised of an array of free fragments of each size.
+// The sizes are 2^n*PAGE_SIZE, where n is the array index.
+type BuddyInfo struct {
+ Node string
+ Zone string
+ Sizes []float64
+}
+
+// NewBuddyInfo reads the buddyinfo statistics.
+func NewBuddyInfo() ([]BuddyInfo, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return nil, err
+ }
+
+ return fs.NewBuddyInfo()
+}
+
+// NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem.
+func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) {
+ file, err := os.Open(fs.Path("buddyinfo"))
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ return parseBuddyInfo(file)
+}
+
+func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
+ var (
+ buddyInfo = []BuddyInfo{}
+ scanner = bufio.NewScanner(r)
+ bucketCount = -1
+ )
+
+ for scanner.Scan() {
+ var err error
+ line := scanner.Text()
+ parts := strings.Fields(line)
+
+ if len(parts) < 4 {
+ return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo")
+ }
+
+ node := strings.TrimRight(parts[1], ",")
+ zone := strings.TrimRight(parts[3], ",")
+ arraySize := len(parts[4:])
+
+ if bucketCount == -1 {
+ bucketCount = arraySize
+ } else {
+ if bucketCount != arraySize {
+ return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize)
+ }
+ }
+
+ sizes := make([]float64, arraySize)
+ for i := 0; i < arraySize; i++ {
+ sizes[i], err = strconv.ParseFloat(parts[i+4], 64)
+ if err != nil {
+ return nil, fmt.Errorf("invalid value in buddyinfo: %s", err)
+ }
+ }
+
+ buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes})
+ }
+
+ return buddyInfo, scanner.Err()
+}
diff --git a/vendor/github.com/prometheus/procfs/doc.go b/vendor/github.com/prometheus/procfs/doc.go
new file mode 100644
index 00000000..e2acd6d4
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/doc.go
@@ -0,0 +1,45 @@
+// Copyright 2014 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package procfs provides functions to retrieve system, kernel and process
+// metrics from the pseudo-filesystem proc.
+//
+// Example:
+//
+// package main
+//
+// import (
+// "fmt"
+// "log"
+//
+// "github.com/prometheus/procfs"
+// )
+//
+// func main() {
+// p, err := procfs.Self()
+// if err != nil {
+// log.Fatalf("could not get process: %s", err)
+// }
+//
+// stat, err := p.NewStat()
+// if err != nil {
+// log.Fatalf("could not get process stat: %s", err)
+// }
+//
+// fmt.Printf("command: %s\n", stat.Comm)
+// fmt.Printf("cpu time: %fs\n", stat.CPUTime())
+// fmt.Printf("vsize: %dB\n", stat.VirtualMemory())
+// fmt.Printf("rss: %dB\n", stat.ResidentMemory())
+// }
+//
+package procfs
diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go
new file mode 100644
index 00000000..b6c6b2ce
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/fs.go
@@ -0,0 +1,82 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "fmt"
+ "os"
+ "path"
+
+ "github.com/prometheus/procfs/nfs"
+ "github.com/prometheus/procfs/xfs"
+)
+
+// FS represents the pseudo-filesystem proc, which provides an interface to
+// kernel data structures.
+type FS string
+
+// DefaultMountPoint is the common mount point of the proc filesystem.
+const DefaultMountPoint = "/proc"
+
+// NewFS returns a new FS mounted under the given mountPoint. It will error
+// if the mount point can't be read.
+func NewFS(mountPoint string) (FS, error) {
+ info, err := os.Stat(mountPoint)
+ if err != nil {
+ return "", fmt.Errorf("could not read %s: %s", mountPoint, err)
+ }
+ if !info.IsDir() {
+ return "", fmt.Errorf("mount point %s is not a directory", mountPoint)
+ }
+
+ return FS(mountPoint), nil
+}
+
+// Path returns the path of the given subsystem relative to the procfs root.
+func (fs FS) Path(p ...string) string {
+ return path.Join(append([]string{string(fs)}, p...)...)
+}
+
+// XFSStats retrieves XFS filesystem runtime statistics.
+func (fs FS) XFSStats() (*xfs.Stats, error) {
+ f, err := os.Open(fs.Path("fs/xfs/stat"))
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return xfs.ParseStats(f)
+}
+
+// NFSClientRPCStats retrieves NFS client RPC statistics.
+func (fs FS) NFSClientRPCStats() (*nfs.ClientRPCStats, error) {
+ f, err := os.Open(fs.Path("net/rpc/nfs"))
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return nfs.ParseClientRPCStats(f)
+}
+
+// NFSdServerRPCStats retrieves NFS daemon RPC statistics.
+func (fs FS) NFSdServerRPCStats() (*nfs.ServerRPCStats, error) {
+ f, err := os.Open(fs.Path("net/rpc/nfsd"))
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return nfs.ParseServerRPCStats(f)
+}
diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go
new file mode 100644
index 00000000..1ad21c91
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/internal/util/parse.go
@@ -0,0 +1,46 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package util
+
+import "strconv"
+
+// ParseUint32s parses a slice of strings into a slice of uint32s.
+func ParseUint32s(ss []string) ([]uint32, error) {
+ us := make([]uint32, 0, len(ss))
+ for _, s := range ss {
+ u, err := strconv.ParseUint(s, 10, 32)
+ if err != nil {
+ return nil, err
+ }
+
+ us = append(us, uint32(u))
+ }
+
+ return us, nil
+}
+
+// ParseUint64s parses a slice of strings into a slice of uint64s.
+func ParseUint64s(ss []string) ([]uint64, error) {
+ us := make([]uint64, 0, len(ss))
+ for _, s := range ss {
+ u, err := strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ us = append(us, u)
+ }
+
+ return us, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go
new file mode 100644
index 00000000..e36d4a3b
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/ipvs.go
@@ -0,0 +1,259 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bufio"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// IPVSStats holds IPVS statistics, as exposed by the kernel in `/proc/net/ip_vs_stats`.
+type IPVSStats struct {
+ // Total count of connections.
+ Connections uint64
+ // Total incoming packages processed.
+ IncomingPackets uint64
+ // Total outgoing packages processed.
+ OutgoingPackets uint64
+ // Total incoming traffic.
+ IncomingBytes uint64
+ // Total outgoing traffic.
+ OutgoingBytes uint64
+}
+
+// IPVSBackendStatus holds current metrics of one virtual / real address pair.
+type IPVSBackendStatus struct {
+ // The local (virtual) IP address.
+ LocalAddress net.IP
+ // The remote (real) IP address.
+ RemoteAddress net.IP
+ // The local (virtual) port.
+ LocalPort uint16
+ // The remote (real) port.
+ RemotePort uint16
+ // The local firewall mark
+ LocalMark string
+ // The transport protocol (TCP, UDP).
+ Proto string
+ // The current number of active connections for this virtual/real address pair.
+ ActiveConn uint64
+ // The current number of inactive connections for this virtual/real address pair.
+ InactConn uint64
+ // The current weight of this virtual/real address pair.
+ Weight uint64
+}
+
+// NewIPVSStats reads the IPVS statistics.
+func NewIPVSStats() (IPVSStats, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+
+ return fs.NewIPVSStats()
+}
+
+// NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem.
+func (fs FS) NewIPVSStats() (IPVSStats, error) {
+ file, err := os.Open(fs.Path("net/ip_vs_stats"))
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ defer file.Close()
+
+ return parseIPVSStats(file)
+}
+
+// parseIPVSStats performs the actual parsing of `ip_vs_stats`.
+func parseIPVSStats(file io.Reader) (IPVSStats, error) {
+ var (
+ statContent []byte
+ statLines []string
+ statFields []string
+ stats IPVSStats
+ )
+
+ statContent, err := ioutil.ReadAll(file)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+
+ statLines = strings.SplitN(string(statContent), "\n", 4)
+ if len(statLines) != 4 {
+ return IPVSStats{}, errors.New("ip_vs_stats corrupt: too short")
+ }
+
+ statFields = strings.Fields(statLines[2])
+ if len(statFields) != 5 {
+ return IPVSStats{}, errors.New("ip_vs_stats corrupt: unexpected number of fields")
+ }
+
+ stats.Connections, err = strconv.ParseUint(statFields[0], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.IncomingPackets, err = strconv.ParseUint(statFields[1], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.OutgoingPackets, err = strconv.ParseUint(statFields[2], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.IncomingBytes, err = strconv.ParseUint(statFields[3], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+ stats.OutgoingBytes, err = strconv.ParseUint(statFields[4], 16, 64)
+ if err != nil {
+ return IPVSStats{}, err
+ }
+
+ return stats, nil
+}
+
+// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs.
+func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return []IPVSBackendStatus{}, err
+ }
+
+ return fs.NewIPVSBackendStatus()
+}
+
+// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
+func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
+ file, err := os.Open(fs.Path("net/ip_vs"))
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ return parseIPVSBackendStatus(file)
+}
+
+func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) {
+ var (
+ status []IPVSBackendStatus
+ scanner = bufio.NewScanner(file)
+ proto string
+ localMark string
+ localAddress net.IP
+ localPort uint16
+ err error
+ )
+
+ for scanner.Scan() {
+ fields := strings.Fields(scanner.Text())
+ if len(fields) == 0 {
+ continue
+ }
+ switch {
+ case fields[0] == "IP" || fields[0] == "Prot" || fields[1] == "RemoteAddress:Port":
+ continue
+ case fields[0] == "TCP" || fields[0] == "UDP":
+ if len(fields) < 2 {
+ continue
+ }
+ proto = fields[0]
+ localMark = ""
+ localAddress, localPort, err = parseIPPort(fields[1])
+ if err != nil {
+ return nil, err
+ }
+ case fields[0] == "FWM":
+ if len(fields) < 2 {
+ continue
+ }
+ proto = fields[0]
+ localMark = fields[1]
+ localAddress = nil
+ localPort = 0
+ case fields[0] == "->":
+ if len(fields) < 6 {
+ continue
+ }
+ remoteAddress, remotePort, err := parseIPPort(fields[1])
+ if err != nil {
+ return nil, err
+ }
+ weight, err := strconv.ParseUint(fields[3], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ activeConn, err := strconv.ParseUint(fields[4], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ inactConn, err := strconv.ParseUint(fields[5], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ status = append(status, IPVSBackendStatus{
+ LocalAddress: localAddress,
+ LocalPort: localPort,
+ LocalMark: localMark,
+ RemoteAddress: remoteAddress,
+ RemotePort: remotePort,
+ Proto: proto,
+ Weight: weight,
+ ActiveConn: activeConn,
+ InactConn: inactConn,
+ })
+ }
+ }
+ return status, nil
+}
+
+func parseIPPort(s string) (net.IP, uint16, error) {
+ var (
+ ip net.IP
+ err error
+ )
+
+ switch len(s) {
+ case 13:
+ ip, err = hex.DecodeString(s[0:8])
+ if err != nil {
+ return nil, 0, err
+ }
+ case 46:
+ ip = net.ParseIP(s[1:40])
+ if ip == nil {
+ return nil, 0, fmt.Errorf("invalid IPv6 address: %s", s[1:40])
+ }
+ default:
+ return nil, 0, fmt.Errorf("unexpected IP:Port: %s", s)
+ }
+
+ portString := s[len(s)-4:]
+ if len(portString) != 4 {
+ return nil, 0, fmt.Errorf("unexpected port string format: %s", portString)
+ }
+ port, err := strconv.ParseUint(portString, 16, 16)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ return ip, uint16(port), nil
+}
diff --git a/vendor/github.com/prometheus/procfs/mdstat.go b/vendor/github.com/prometheus/procfs/mdstat.go
new file mode 100644
index 00000000..9dc19583
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/mdstat.go
@@ -0,0 +1,151 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "fmt"
+ "io/ioutil"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`)
+ buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`)
+)
+
+// MDStat holds info parsed from /proc/mdstat.
+type MDStat struct {
+ // Name of the device.
+ Name string
+ // activity-state of the device.
+ ActivityState string
+ // Number of active disks.
+ DisksActive int64
+ // Total number of disks the device consists of.
+ DisksTotal int64
+ // Number of blocks the device holds.
+ BlocksTotal int64
+ // Number of blocks on the device that are in sync.
+ BlocksSynced int64
+}
+
+// ParseMDStat parses an mdstat-file and returns a struct with the relevant infos.
+func (fs FS) ParseMDStat() (mdstates []MDStat, err error) {
+ mdStatusFilePath := fs.Path("mdstat")
+ content, err := ioutil.ReadFile(mdStatusFilePath)
+ if err != nil {
+ return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
+ }
+
+ mdStates := []MDStat{}
+ lines := strings.Split(string(content), "\n")
+ for i, l := range lines {
+ if l == "" {
+ continue
+ }
+ if l[0] == ' ' {
+ continue
+ }
+ if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") {
+ continue
+ }
+
+ mainLine := strings.Split(l, " ")
+ if len(mainLine) < 3 {
+ return mdStates, fmt.Errorf("error parsing mdline: %s", l)
+ }
+ mdName := mainLine[0]
+ activityState := mainLine[2]
+
+ if len(lines) <= i+3 {
+ return mdStates, fmt.Errorf(
+ "error parsing %s: too few lines for md device %s",
+ mdStatusFilePath,
+ mdName,
+ )
+ }
+
+ active, total, size, err := evalStatusline(lines[i+1])
+ if err != nil {
+ return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
+ }
+
+ // j is the line number of the syncing-line.
+ j := i + 2
+ if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line
+ j = i + 3
+ }
+
+ // If device is syncing at the moment, get the number of currently
+ // synced bytes, otherwise that number equals the size of the device.
+ syncedBlocks := size
+ if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") {
+ syncedBlocks, err = evalBuildline(lines[j])
+ if err != nil {
+ return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
+ }
+ }
+
+ mdStates = append(mdStates, MDStat{
+ Name: mdName,
+ ActivityState: activityState,
+ DisksActive: active,
+ DisksTotal: total,
+ BlocksTotal: size,
+ BlocksSynced: syncedBlocks,
+ })
+ }
+
+ return mdStates, nil
+}
+
+func evalStatusline(statusline string) (active, total, size int64, err error) {
+ matches := statuslineRE.FindStringSubmatch(statusline)
+ if len(matches) != 4 {
+ return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline)
+ }
+
+ size, err = strconv.ParseInt(matches[1], 10, 64)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
+ }
+
+ total, err = strconv.ParseInt(matches[2], 10, 64)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
+ }
+
+ active, err = strconv.ParseInt(matches[3], 10, 64)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
+ }
+
+ return active, total, size, nil
+}
+
+func evalBuildline(buildline string) (syncedBlocks int64, err error) {
+ matches := buildlineRE.FindStringSubmatch(buildline)
+ if len(matches) != 2 {
+ return 0, fmt.Errorf("unexpected buildline: %s", buildline)
+ }
+
+ syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64)
+ if err != nil {
+ return 0, fmt.Errorf("%s in buildline: %s", err, buildline)
+ }
+
+ return syncedBlocks, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go
new file mode 100644
index 00000000..7a8a1e09
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/mountstats.go
@@ -0,0 +1,606 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+// While implementing parsing of /proc/[pid]/mountstats, this blog was used
+// heavily as a reference:
+// https://utcc.utoronto.ca/~cks/space/blog/linux/NFSMountstatsIndex
+//
+// Special thanks to Chris Siebenmann for all of his posts explaining the
+// various statistics available for NFS.
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// Constants shared between multiple functions.
+const (
+ deviceEntryLen = 8
+
+ fieldBytesLen = 8
+ fieldEventsLen = 27
+
+ statVersion10 = "1.0"
+ statVersion11 = "1.1"
+
+ fieldTransport10TCPLen = 10
+ fieldTransport10UDPLen = 7
+
+ fieldTransport11TCPLen = 13
+ fieldTransport11UDPLen = 10
+)
+
+// A Mount is a device mount parsed from /proc/[pid]/mountstats.
+type Mount struct {
+ // Name of the device.
+ Device string
+ // The mount point of the device.
+ Mount string
+ // The filesystem type used by the device.
+ Type string
+ // If available additional statistics related to this Mount.
+ // Use a type assertion to determine if additional statistics are available.
+ Stats MountStats
+}
+
+// A MountStats is a type which contains detailed statistics for a specific
+// type of Mount.
+type MountStats interface {
+ mountStats()
+}
+
+// A MountStatsNFS is a MountStats implementation for NFSv3 and v4 mounts.
+type MountStatsNFS struct {
+ // The version of statistics provided.
+ StatVersion string
+ // The age of the NFS mount.
+ Age time.Duration
+ // Statistics related to byte counters for various operations.
+ Bytes NFSBytesStats
+ // Statistics related to various NFS event occurrences.
+ Events NFSEventsStats
+ // Statistics broken down by filesystem operation.
+ Operations []NFSOperationStats
+ // Statistics about the NFS RPC transport.
+ Transport NFSTransportStats
+}
+
+// mountStats implements MountStats.
+func (m MountStatsNFS) mountStats() {}
+
+// A NFSBytesStats contains statistics about the number of bytes read and written
+// by an NFS client to and from an NFS server.
+type NFSBytesStats struct {
+ // Number of bytes read using the read() syscall.
+ Read uint64
+ // Number of bytes written using the write() syscall.
+ Write uint64
+ // Number of bytes read using the read() syscall in O_DIRECT mode.
+ DirectRead uint64
+ // Number of bytes written using the write() syscall in O_DIRECT mode.
+ DirectWrite uint64
+ // Number of bytes read from the NFS server, in total.
+ ReadTotal uint64
+ // Number of bytes written to the NFS server, in total.
+ WriteTotal uint64
+ // Number of pages read directly via mmap()'d files.
+ ReadPages uint64
+ // Number of pages written directly via mmap()'d files.
+ WritePages uint64
+}
+
+// A NFSEventsStats contains statistics about NFS event occurrences.
+type NFSEventsStats struct {
+ // Number of times cached inode attributes are re-validated from the server.
+ InodeRevalidate uint64
+ // Number of times cached dentry nodes are re-validated from the server.
+ DnodeRevalidate uint64
+ // Number of times an inode cache is cleared.
+ DataInvalidate uint64
+ // Number of times cached inode attributes are invalidated.
+ AttributeInvalidate uint64
+ // Number of times files or directories have been open()'d.
+ VFSOpen uint64
+ // Number of times a directory lookup has occurred.
+ VFSLookup uint64
+ // Number of times permissions have been checked.
+ VFSAccess uint64
+ // Number of updates (and potential writes) to pages.
+ VFSUpdatePage uint64
+ // Number of pages read directly via mmap()'d files.
+ VFSReadPage uint64
+ // Number of times a group of pages have been read.
+ VFSReadPages uint64
+ // Number of pages written directly via mmap()'d files.
+ VFSWritePage uint64
+ // Number of times a group of pages have been written.
+ VFSWritePages uint64
+ // Number of times directory entries have been read with getdents().
+ VFSGetdents uint64
+ // Number of times attributes have been set on inodes.
+ VFSSetattr uint64
+ // Number of pending writes that have been forcefully flushed to the server.
+ VFSFlush uint64
+ // Number of times fsync() has been called on directories and files.
+ VFSFsync uint64
+ // Number of times locking has been attempted on a file.
+ VFSLock uint64
+ // Number of times files have been closed and released.
+ VFSFileRelease uint64
+ // Unknown. Possibly unused.
+ CongestionWait uint64
+ // Number of times files have been truncated.
+ Truncation uint64
+ // Number of times a file has been grown due to writes beyond its existing end.
+ WriteExtension uint64
+ // Number of times a file was removed while still open by another process.
+ SillyRename uint64
+ // Number of times the NFS server gave less data than expected while reading.
+ ShortRead uint64
+ // Number of times the NFS server wrote less data than expected while writing.
+ ShortWrite uint64
+ // Number of times the NFS server indicated EJUKEBOX; retrieving data from
+ // offline storage.
+ JukeboxDelay uint64
+ // Number of NFS v4.1+ pNFS reads.
+ PNFSRead uint64
+ // Number of NFS v4.1+ pNFS writes.
+ PNFSWrite uint64
+}
+
+// A NFSOperationStats contains statistics for a single operation.
+type NFSOperationStats struct {
+ // The name of the operation.
+ Operation string
+ // Number of requests performed for this operation.
+ Requests uint64
+ // Number of times an actual RPC request has been transmitted for this operation.
+ Transmissions uint64
+ // Number of times a request has had a major timeout.
+ MajorTimeouts uint64
+ // Number of bytes sent for this operation, including RPC headers and payload.
+ BytesSent uint64
+ // Number of bytes received for this operation, including RPC headers and payload.
+ BytesReceived uint64
+ // Duration all requests spent queued for transmission before they were sent.
+ CumulativeQueueTime time.Duration
+ // Duration it took to get a reply back after the request was transmitted.
+ CumulativeTotalResponseTime time.Duration
+ // Duration from when a request was enqueued to when it was completely handled.
+ CumulativeTotalRequestTime time.Duration
+}
+
+// A NFSTransportStats contains statistics for the NFS mount RPC requests and
+// responses.
+type NFSTransportStats struct {
+ // The transport protocol used for the NFS mount.
+ Protocol string
+ // The local port used for the NFS mount.
+ Port uint64
+ // Number of times the client has had to establish a connection from scratch
+ // to the NFS server.
+ Bind uint64
+ // Number of times the client has made a TCP connection to the NFS server.
+ Connect uint64
+ // Duration (in jiffies, a kernel internal unit of time) the NFS mount has
+ // spent waiting for connections to the server to be established.
+ ConnectIdleTime uint64
+ // Duration since the NFS mount last saw any RPC traffic.
+ IdleTime time.Duration
+ // Number of RPC requests for this mount sent to the NFS server.
+ Sends uint64
+ // Number of RPC responses for this mount received from the NFS server.
+ Receives uint64
+ // Number of times the NFS server sent a response with a transaction ID
+ // unknown to this client.
+ BadTransactionIDs uint64
+ // A running counter, incremented on each request as the current difference
+ // ebetween sends and receives.
+ CumulativeActiveRequests uint64
+ // A running counter, incremented on each request by the current backlog
+ // queue size.
+ CumulativeBacklog uint64
+
+ // Stats below only available with stat version 1.1.
+
+ // Maximum number of simultaneously active RPC requests ever used.
+ MaximumRPCSlotsUsed uint64
+ // A running counter, incremented on each request as the current size of the
+ // sending queue.
+ CumulativeSendingQueue uint64
+ // A running counter, incremented on each request as the current size of the
+ // pending queue.
+ CumulativePendingQueue uint64
+}
+
+// parseMountStats parses a /proc/[pid]/mountstats file and returns a slice
+// of Mount structures containing detailed information about each mount.
+// If available, statistics for each mount are parsed as well.
+func parseMountStats(r io.Reader) ([]*Mount, error) {
+ const (
+ device = "device"
+ statVersionPrefix = "statvers="
+
+ nfs3Type = "nfs"
+ nfs4Type = "nfs4"
+ )
+
+ var mounts []*Mount
+
+ s := bufio.NewScanner(r)
+ for s.Scan() {
+ // Only look for device entries in this function
+ ss := strings.Fields(string(s.Bytes()))
+ if len(ss) == 0 || ss[0] != device {
+ continue
+ }
+
+ m, err := parseMount(ss)
+ if err != nil {
+ return nil, err
+ }
+
+ // Does this mount also possess statistics information?
+ if len(ss) > deviceEntryLen {
+ // Only NFSv3 and v4 are supported for parsing statistics
+ if m.Type != nfs3Type && m.Type != nfs4Type {
+ return nil, fmt.Errorf("cannot parse MountStats for fstype %q", m.Type)
+ }
+
+ statVersion := strings.TrimPrefix(ss[8], statVersionPrefix)
+
+ stats, err := parseMountStatsNFS(s, statVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ m.Stats = stats
+ }
+
+ mounts = append(mounts, m)
+ }
+
+ return mounts, s.Err()
+}
+
+// parseMount parses an entry in /proc/[pid]/mountstats in the format:
+// device [device] mounted on [mount] with fstype [type]
+func parseMount(ss []string) (*Mount, error) {
+ if len(ss) < deviceEntryLen {
+ return nil, fmt.Errorf("invalid device entry: %v", ss)
+ }
+
+ // Check for specific words appearing at specific indices to ensure
+ // the format is consistent with what we expect
+ format := []struct {
+ i int
+ s string
+ }{
+ {i: 0, s: "device"},
+ {i: 2, s: "mounted"},
+ {i: 3, s: "on"},
+ {i: 5, s: "with"},
+ {i: 6, s: "fstype"},
+ }
+
+ for _, f := range format {
+ if ss[f.i] != f.s {
+ return nil, fmt.Errorf("invalid device entry: %v", ss)
+ }
+ }
+
+ return &Mount{
+ Device: ss[1],
+ Mount: ss[4],
+ Type: ss[7],
+ }, nil
+}
+
+// parseMountStatsNFS parses a MountStatsNFS by scanning additional information
+// related to NFS statistics.
+func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, error) {
+ // Field indicators for parsing specific types of data
+ const (
+ fieldAge = "age:"
+ fieldBytes = "bytes:"
+ fieldEvents = "events:"
+ fieldPerOpStats = "per-op"
+ fieldTransport = "xprt:"
+ )
+
+ stats := &MountStatsNFS{
+ StatVersion: statVersion,
+ }
+
+ for s.Scan() {
+ ss := strings.Fields(string(s.Bytes()))
+ if len(ss) == 0 {
+ break
+ }
+ if len(ss) < 2 {
+ return nil, fmt.Errorf("not enough information for NFS stats: %v", ss)
+ }
+
+ switch ss[0] {
+ case fieldAge:
+ // Age integer is in seconds
+ d, err := time.ParseDuration(ss[1] + "s")
+ if err != nil {
+ return nil, err
+ }
+
+ stats.Age = d
+ case fieldBytes:
+ bstats, err := parseNFSBytesStats(ss[1:])
+ if err != nil {
+ return nil, err
+ }
+
+ stats.Bytes = *bstats
+ case fieldEvents:
+ estats, err := parseNFSEventsStats(ss[1:])
+ if err != nil {
+ return nil, err
+ }
+
+ stats.Events = *estats
+ case fieldTransport:
+ if len(ss) < 3 {
+ return nil, fmt.Errorf("not enough information for NFS transport stats: %v", ss)
+ }
+
+ tstats, err := parseNFSTransportStats(ss[1:], statVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ stats.Transport = *tstats
+ }
+
+ // When encountering "per-operation statistics", we must break this
+ // loop and parse them separately to ensure we can terminate parsing
+ // before reaching another device entry; hence why this 'if' statement
+ // is not just another switch case
+ if ss[0] == fieldPerOpStats {
+ break
+ }
+ }
+
+ if err := s.Err(); err != nil {
+ return nil, err
+ }
+
+ // NFS per-operation stats appear last before the next device entry
+ perOpStats, err := parseNFSOperationStats(s)
+ if err != nil {
+ return nil, err
+ }
+
+ stats.Operations = perOpStats
+
+ return stats, nil
+}
+
+// parseNFSBytesStats parses a NFSBytesStats line using an input set of
+// integer fields.
+func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) {
+ if len(ss) != fieldBytesLen {
+ return nil, fmt.Errorf("invalid NFS bytes stats: %v", ss)
+ }
+
+ ns := make([]uint64, 0, fieldBytesLen)
+ for _, s := range ss {
+ n, err := strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ ns = append(ns, n)
+ }
+
+ return &NFSBytesStats{
+ Read: ns[0],
+ Write: ns[1],
+ DirectRead: ns[2],
+ DirectWrite: ns[3],
+ ReadTotal: ns[4],
+ WriteTotal: ns[5],
+ ReadPages: ns[6],
+ WritePages: ns[7],
+ }, nil
+}
+
+// parseNFSEventsStats parses a NFSEventsStats line using an input set of
+// integer fields.
+func parseNFSEventsStats(ss []string) (*NFSEventsStats, error) {
+ if len(ss) != fieldEventsLen {
+ return nil, fmt.Errorf("invalid NFS events stats: %v", ss)
+ }
+
+ ns := make([]uint64, 0, fieldEventsLen)
+ for _, s := range ss {
+ n, err := strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ ns = append(ns, n)
+ }
+
+ return &NFSEventsStats{
+ InodeRevalidate: ns[0],
+ DnodeRevalidate: ns[1],
+ DataInvalidate: ns[2],
+ AttributeInvalidate: ns[3],
+ VFSOpen: ns[4],
+ VFSLookup: ns[5],
+ VFSAccess: ns[6],
+ VFSUpdatePage: ns[7],
+ VFSReadPage: ns[8],
+ VFSReadPages: ns[9],
+ VFSWritePage: ns[10],
+ VFSWritePages: ns[11],
+ VFSGetdents: ns[12],
+ VFSSetattr: ns[13],
+ VFSFlush: ns[14],
+ VFSFsync: ns[15],
+ VFSLock: ns[16],
+ VFSFileRelease: ns[17],
+ CongestionWait: ns[18],
+ Truncation: ns[19],
+ WriteExtension: ns[20],
+ SillyRename: ns[21],
+ ShortRead: ns[22],
+ ShortWrite: ns[23],
+ JukeboxDelay: ns[24],
+ PNFSRead: ns[25],
+ PNFSWrite: ns[26],
+ }, nil
+}
+
+// parseNFSOperationStats parses a slice of NFSOperationStats by scanning
+// additional information about per-operation statistics until an empty
+// line is reached.
+func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
+ const (
+ // Number of expected fields in each per-operation statistics set
+ numFields = 9
+ )
+
+ var ops []NFSOperationStats
+
+ for s.Scan() {
+ ss := strings.Fields(string(s.Bytes()))
+ if len(ss) == 0 {
+ // Must break when reading a blank line after per-operation stats to
+ // enable top-level function to parse the next device entry
+ break
+ }
+
+ if len(ss) != numFields {
+ return nil, fmt.Errorf("invalid NFS per-operations stats: %v", ss)
+ }
+
+ // Skip string operation name for integers
+ ns := make([]uint64, 0, numFields-1)
+ for _, st := range ss[1:] {
+ n, err := strconv.ParseUint(st, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ ns = append(ns, n)
+ }
+
+ ops = append(ops, NFSOperationStats{
+ Operation: strings.TrimSuffix(ss[0], ":"),
+ Requests: ns[0],
+ Transmissions: ns[1],
+ MajorTimeouts: ns[2],
+ BytesSent: ns[3],
+ BytesReceived: ns[4],
+ CumulativeQueueTime: time.Duration(ns[5]) * time.Millisecond,
+ CumulativeTotalResponseTime: time.Duration(ns[6]) * time.Millisecond,
+ CumulativeTotalRequestTime: time.Duration(ns[7]) * time.Millisecond,
+ })
+ }
+
+ return ops, s.Err()
+}
+
+// parseNFSTransportStats parses a NFSTransportStats line using an input set of
+// integer fields matched to a specific stats version.
+func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats, error) {
+ // Extract the protocol field. It is the only string value in the line
+ protocol := ss[0]
+ ss = ss[1:]
+
+ switch statVersion {
+ case statVersion10:
+ var expectedLength int
+ if protocol == "tcp" {
+ expectedLength = fieldTransport10TCPLen
+ } else if protocol == "udp" {
+ expectedLength = fieldTransport10UDPLen
+ } else {
+ return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.0 statement: %v", protocol, ss)
+ }
+ if len(ss) != expectedLength {
+ return nil, fmt.Errorf("invalid NFS transport stats 1.0 statement: %v", ss)
+ }
+ case statVersion11:
+ var expectedLength int
+ if protocol == "tcp" {
+ expectedLength = fieldTransport11TCPLen
+ } else if protocol == "udp" {
+ expectedLength = fieldTransport11UDPLen
+ } else {
+ return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.1 statement: %v", protocol, ss)
+ }
+ if len(ss) != expectedLength {
+ return nil, fmt.Errorf("invalid NFS transport stats 1.1 statement: %v", ss)
+ }
+ default:
+ return nil, fmt.Errorf("unrecognized NFS transport stats version: %q", statVersion)
+ }
+
+ // Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay
+ // in a v1.0 response. Since the stat length is bigger for TCP stats, we use
+ // the TCP length here.
+ //
+ // Note: slice length must be set to length of v1.1 stats to avoid a panic when
+ // only v1.0 stats are present.
+ // See: https://github.com/prometheus/node_exporter/issues/571.
+ ns := make([]uint64, fieldTransport11TCPLen)
+ for i, s := range ss {
+ n, err := strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ ns[i] = n
+ }
+
+ // The fields differ depending on the transport protocol (TCP or UDP)
+ // From https://utcc.utoronto.ca/%7Ecks/space/blog/linux/NFSMountstatsXprt
+ //
+ // For the udp RPC transport there is no connection count, connect idle time,
+ // or idle time (fields #3, #4, and #5); all other fields are the same. So
+ // we set them to 0 here.
+ if protocol == "udp" {
+ ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
+ }
+
+ return &NFSTransportStats{
+ Protocol: protocol,
+ Port: ns[0],
+ Bind: ns[1],
+ Connect: ns[2],
+ ConnectIdleTime: ns[3],
+ IdleTime: time.Duration(ns[4]) * time.Second,
+ Sends: ns[5],
+ Receives: ns[6],
+ BadTransactionIDs: ns[7],
+ CumulativeActiveRequests: ns[8],
+ CumulativeBacklog: ns[9],
+ MaximumRPCSlotsUsed: ns[10],
+ CumulativeSendingQueue: ns[11],
+ CumulativePendingQueue: ns[12],
+ }, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/net_dev.go b/vendor/github.com/prometheus/procfs/net_dev.go
new file mode 100644
index 00000000..3f252337
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/net_dev.go
@@ -0,0 +1,216 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bufio"
+ "errors"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev.
+type NetDevLine struct {
+ Name string `json:"name"` // The name of the interface.
+ RxBytes uint64 `json:"rx_bytes"` // Cumulative count of bytes received.
+ RxPackets uint64 `json:"rx_packets"` // Cumulative count of packets received.
+ RxErrors uint64 `json:"rx_errors"` // Cumulative count of receive errors encountered.
+ RxDropped uint64 `json:"rx_dropped"` // Cumulative count of packets dropped while receiving.
+ RxFIFO uint64 `json:"rx_fifo"` // Cumulative count of FIFO buffer errors.
+ RxFrame uint64 `json:"rx_frame"` // Cumulative count of packet framing errors.
+ RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver.
+ RxMulticast uint64 `json:"rx_multicast"` // Cumulative count of multicast frames received by the device driver.
+ TxBytes uint64 `json:"tx_bytes"` // Cumulative count of bytes transmitted.
+ TxPackets uint64 `json:"tx_packets"` // Cumulative count of packets transmitted.
+ TxErrors uint64 `json:"tx_errors"` // Cumulative count of transmit errors encountered.
+ TxDropped uint64 `json:"tx_dropped"` // Cumulative count of packets dropped while transmitting.
+ TxFIFO uint64 `json:"tx_fifo"` // Cumulative count of FIFO buffer errors.
+ TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface.
+ TxCarrier uint64 `json:"tx_carrier"` // Cumulative count of carrier losses detected by the device driver.
+ TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver.
+}
+
+// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys
+// are interface names.
+type NetDev map[string]NetDevLine
+
+// NewNetDev returns kernel/system statistics read from /proc/net/dev.
+func NewNetDev() (NetDev, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return nil, err
+ }
+
+ return fs.NewNetDev()
+}
+
+// NewNetDev returns kernel/system statistics read from /proc/net/dev.
+func (fs FS) NewNetDev() (NetDev, error) {
+ return newNetDev(fs.Path("net/dev"))
+}
+
+// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
+func (p Proc) NewNetDev() (NetDev, error) {
+ return newNetDev(p.path("net/dev"))
+}
+
+// newNetDev creates a new NetDev from the contents of the given file.
+func newNetDev(file string) (NetDev, error) {
+ f, err := os.Open(file)
+ if err != nil {
+ return NetDev{}, err
+ }
+ defer f.Close()
+
+ nd := NetDev{}
+ s := bufio.NewScanner(f)
+ for n := 0; s.Scan(); n++ {
+ // Skip the 2 header lines.
+ if n < 2 {
+ continue
+ }
+
+ line, err := nd.parseLine(s.Text())
+ if err != nil {
+ return nd, err
+ }
+
+ nd[line.Name] = *line
+ }
+
+ return nd, s.Err()
+}
+
+// parseLine parses a single line from the /proc/net/dev file. Header lines
+// must be filtered prior to calling this method.
+func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
+ parts := strings.SplitN(rawLine, ":", 2)
+ if len(parts) != 2 {
+ return nil, errors.New("invalid net/dev line, missing colon")
+ }
+ fields := strings.Fields(strings.TrimSpace(parts[1]))
+
+ var err error
+ line := &NetDevLine{}
+
+ // Interface Name
+ line.Name = strings.TrimSpace(parts[0])
+ if line.Name == "" {
+ return nil, errors.New("invalid net/dev line, empty interface name")
+ }
+
+ // RX
+ line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ // TX
+ line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+
+ return line, nil
+}
+
+// Total aggregates the values across interfaces and returns a new NetDevLine.
+// The Name field will be a sorted comma separated list of interface names.
+func (nd NetDev) Total() NetDevLine {
+ total := NetDevLine{}
+
+ names := make([]string, 0, len(nd))
+ for _, ifc := range nd {
+ names = append(names, ifc.Name)
+ total.RxBytes += ifc.RxBytes
+ total.RxPackets += ifc.RxPackets
+ total.RxPackets += ifc.RxPackets
+ total.RxErrors += ifc.RxErrors
+ total.RxDropped += ifc.RxDropped
+ total.RxFIFO += ifc.RxFIFO
+ total.RxFrame += ifc.RxFrame
+ total.RxCompressed += ifc.RxCompressed
+ total.RxMulticast += ifc.RxMulticast
+ total.TxBytes += ifc.TxBytes
+ total.TxPackets += ifc.TxPackets
+ total.TxErrors += ifc.TxErrors
+ total.TxDropped += ifc.TxDropped
+ total.TxFIFO += ifc.TxFIFO
+ total.TxCollisions += ifc.TxCollisions
+ total.TxCarrier += ifc.TxCarrier
+ total.TxCompressed += ifc.TxCompressed
+ }
+ sort.Strings(names)
+ total.Name = strings.Join(names, ", ")
+
+ return total
+}
diff --git a/vendor/github.com/prometheus/procfs/nfs/nfs.go b/vendor/github.com/prometheus/procfs/nfs/nfs.go
new file mode 100644
index 00000000..651bf681
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/nfs/nfs.go
@@ -0,0 +1,263 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package nfs implements parsing of /proc/net/rpc/nfsd.
+// Fields are documented in https://www.svennd.be/nfsd-stats-explained-procnetrpcnfsd/
+package nfs
+
+// ReplyCache models the "rc" line.
+type ReplyCache struct {
+ Hits uint64
+ Misses uint64
+ NoCache uint64
+}
+
+// FileHandles models the "fh" line.
+type FileHandles struct {
+ Stale uint64
+ TotalLookups uint64
+ AnonLookups uint64
+ DirNoCache uint64
+ NoDirNoCache uint64
+}
+
+// InputOutput models the "io" line.
+type InputOutput struct {
+ Read uint64
+ Write uint64
+}
+
+// Threads models the "th" line.
+type Threads struct {
+ Threads uint64
+ FullCnt uint64
+}
+
+// ReadAheadCache models the "ra" line.
+type ReadAheadCache struct {
+ CacheSize uint64
+ CacheHistogram []uint64
+ NotFound uint64
+}
+
+// Network models the "net" line.
+type Network struct {
+ NetCount uint64
+ UDPCount uint64
+ TCPCount uint64
+ TCPConnect uint64
+}
+
+// ClientRPC models the nfs "rpc" line.
+type ClientRPC struct {
+ RPCCount uint64
+ Retransmissions uint64
+ AuthRefreshes uint64
+}
+
+// ServerRPC models the nfsd "rpc" line.
+type ServerRPC struct {
+ RPCCount uint64
+ BadCnt uint64
+ BadFmt uint64
+ BadAuth uint64
+ BadcInt uint64
+}
+
+// V2Stats models the "proc2" line.
+type V2Stats struct {
+ Null uint64
+ GetAttr uint64
+ SetAttr uint64
+ Root uint64
+ Lookup uint64
+ ReadLink uint64
+ Read uint64
+ WrCache uint64
+ Write uint64
+ Create uint64
+ Remove uint64
+ Rename uint64
+ Link uint64
+ SymLink uint64
+ MkDir uint64
+ RmDir uint64
+ ReadDir uint64
+ FsStat uint64
+}
+
+// V3Stats models the "proc3" line.
+type V3Stats struct {
+ Null uint64
+ GetAttr uint64
+ SetAttr uint64
+ Lookup uint64
+ Access uint64
+ ReadLink uint64
+ Read uint64
+ Write uint64
+ Create uint64
+ MkDir uint64
+ SymLink uint64
+ MkNod uint64
+ Remove uint64
+ RmDir uint64
+ Rename uint64
+ Link uint64
+ ReadDir uint64
+ ReadDirPlus uint64
+ FsStat uint64
+ FsInfo uint64
+ PathConf uint64
+ Commit uint64
+}
+
+// ClientV4Stats models the nfs "proc4" line.
+type ClientV4Stats struct {
+ Null uint64
+ Read uint64
+ Write uint64
+ Commit uint64
+ Open uint64
+ OpenConfirm uint64
+ OpenNoattr uint64
+ OpenDowngrade uint64
+ Close uint64
+ Setattr uint64
+ FsInfo uint64
+ Renew uint64
+ SetClientID uint64
+ SetClientIDConfirm uint64
+ Lock uint64
+ Lockt uint64
+ Locku uint64
+ Access uint64
+ Getattr uint64
+ Lookup uint64
+ LookupRoot uint64
+ Remove uint64
+ Rename uint64
+ Link uint64
+ Symlink uint64
+ Create uint64
+ Pathconf uint64
+ StatFs uint64
+ ReadLink uint64
+ ReadDir uint64
+ ServerCaps uint64
+ DelegReturn uint64
+ GetACL uint64
+ SetACL uint64
+ FsLocations uint64
+ ReleaseLockowner uint64
+ Secinfo uint64
+ FsidPresent uint64
+ ExchangeID uint64
+ CreateSession uint64
+ DestroySession uint64
+ Sequence uint64
+ GetLeaseTime uint64
+ ReclaimComplete uint64
+ LayoutGet uint64
+ GetDeviceInfo uint64
+ LayoutCommit uint64
+ LayoutReturn uint64
+ SecinfoNoName uint64
+ TestStateID uint64
+ FreeStateID uint64
+ GetDeviceList uint64
+ BindConnToSession uint64
+ DestroyClientID uint64
+ Seek uint64
+ Allocate uint64
+ DeAllocate uint64
+ LayoutStats uint64
+ Clone uint64
+}
+
+// ServerV4Stats models the nfsd "proc4" line.
+type ServerV4Stats struct {
+ Null uint64
+ Compound uint64
+}
+
+// V4Ops models the "proc4ops" line: NFSv4 operations
+// Variable list, see:
+// v4.0 https://tools.ietf.org/html/rfc3010 (38 operations)
+// v4.1 https://tools.ietf.org/html/rfc5661 (58 operations)
+// v4.2 https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41 (71 operations)
+type V4Ops struct {
+ //Values uint64 // Variable depending on v4.x sub-version. TODO: Will this always at least include the fields in this struct?
+ Op0Unused uint64
+ Op1Unused uint64
+ Op2Future uint64
+ Access uint64
+ Close uint64
+ Commit uint64
+ Create uint64
+ DelegPurge uint64
+ DelegReturn uint64
+ GetAttr uint64
+ GetFH uint64
+ Link uint64
+ Lock uint64
+ Lockt uint64
+ Locku uint64
+ Lookup uint64
+ LookupRoot uint64
+ Nverify uint64
+ Open uint64
+ OpenAttr uint64
+ OpenConfirm uint64
+ OpenDgrd uint64
+ PutFH uint64
+ PutPubFH uint64
+ PutRootFH uint64
+ Read uint64
+ ReadDir uint64
+ ReadLink uint64
+ Remove uint64
+ Rename uint64
+ Renew uint64
+ RestoreFH uint64
+ SaveFH uint64
+ SecInfo uint64
+ SetAttr uint64
+ Verify uint64
+ Write uint64
+ RelLockOwner uint64
+}
+
+// ClientRPCStats models all stats from /proc/net/rpc/nfs.
+type ClientRPCStats struct {
+ Network Network
+ ClientRPC ClientRPC
+ V2Stats V2Stats
+ V3Stats V3Stats
+ ClientV4Stats ClientV4Stats
+}
+
+// ServerRPCStats models all stats from /proc/net/rpc/nfsd.
+type ServerRPCStats struct {
+ ReplyCache ReplyCache
+ FileHandles FileHandles
+ InputOutput InputOutput
+ Threads Threads
+ ReadAheadCache ReadAheadCache
+ Network Network
+ ServerRPC ServerRPC
+ V2Stats V2Stats
+ V3Stats V3Stats
+ ServerV4Stats ServerV4Stats
+ V4Ops V4Ops
+}
diff --git a/vendor/github.com/prometheus/procfs/nfs/parse.go b/vendor/github.com/prometheus/procfs/nfs/parse.go
new file mode 100644
index 00000000..95a83cc5
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/nfs/parse.go
@@ -0,0 +1,317 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package nfs
+
+import (
+ "fmt"
+)
+
+func parseReplyCache(v []uint64) (ReplyCache, error) {
+ if len(v) != 3 {
+ return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v)
+ }
+
+ return ReplyCache{
+ Hits: v[0],
+ Misses: v[1],
+ NoCache: v[2],
+ }, nil
+}
+
+func parseFileHandles(v []uint64) (FileHandles, error) {
+ if len(v) != 5 {
+ return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v)
+ }
+
+ return FileHandles{
+ Stale: v[0],
+ TotalLookups: v[1],
+ AnonLookups: v[2],
+ DirNoCache: v[3],
+ NoDirNoCache: v[4],
+ }, nil
+}
+
+func parseInputOutput(v []uint64) (InputOutput, error) {
+ if len(v) != 2 {
+ return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v)
+ }
+
+ return InputOutput{
+ Read: v[0],
+ Write: v[1],
+ }, nil
+}
+
+func parseThreads(v []uint64) (Threads, error) {
+ if len(v) != 2 {
+ return Threads{}, fmt.Errorf("invalid Threads line %q", v)
+ }
+
+ return Threads{
+ Threads: v[0],
+ FullCnt: v[1],
+ }, nil
+}
+
+func parseReadAheadCache(v []uint64) (ReadAheadCache, error) {
+ if len(v) != 12 {
+ return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v)
+ }
+
+ return ReadAheadCache{
+ CacheSize: v[0],
+ CacheHistogram: v[1:11],
+ NotFound: v[11],
+ }, nil
+}
+
+func parseNetwork(v []uint64) (Network, error) {
+ if len(v) != 4 {
+ return Network{}, fmt.Errorf("invalid Network line %q", v)
+ }
+
+ return Network{
+ NetCount: v[0],
+ UDPCount: v[1],
+ TCPCount: v[2],
+ TCPConnect: v[3],
+ }, nil
+}
+
+func parseServerRPC(v []uint64) (ServerRPC, error) {
+ if len(v) != 5 {
+ return ServerRPC{}, fmt.Errorf("invalid RPC line %q", v)
+ }
+
+ return ServerRPC{
+ RPCCount: v[0],
+ BadCnt: v[1],
+ BadFmt: v[2],
+ BadAuth: v[3],
+ BadcInt: v[4],
+ }, nil
+}
+
+func parseClientRPC(v []uint64) (ClientRPC, error) {
+ if len(v) != 3 {
+ return ClientRPC{}, fmt.Errorf("invalid RPC line %q", v)
+ }
+
+ return ClientRPC{
+ RPCCount: v[0],
+ Retransmissions: v[1],
+ AuthRefreshes: v[2],
+ }, nil
+}
+
+func parseV2Stats(v []uint64) (V2Stats, error) {
+ values := int(v[0])
+ if len(v[1:]) != values || values != 18 {
+ return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v)
+ }
+
+ return V2Stats{
+ Null: v[1],
+ GetAttr: v[2],
+ SetAttr: v[3],
+ Root: v[4],
+ Lookup: v[5],
+ ReadLink: v[6],
+ Read: v[7],
+ WrCache: v[8],
+ Write: v[9],
+ Create: v[10],
+ Remove: v[11],
+ Rename: v[12],
+ Link: v[13],
+ SymLink: v[14],
+ MkDir: v[15],
+ RmDir: v[16],
+ ReadDir: v[17],
+ FsStat: v[18],
+ }, nil
+}
+
+func parseV3Stats(v []uint64) (V3Stats, error) {
+ values := int(v[0])
+ if len(v[1:]) != values || values != 22 {
+ return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v)
+ }
+
+ return V3Stats{
+ Null: v[1],
+ GetAttr: v[2],
+ SetAttr: v[3],
+ Lookup: v[4],
+ Access: v[5],
+ ReadLink: v[6],
+ Read: v[7],
+ Write: v[8],
+ Create: v[9],
+ MkDir: v[10],
+ SymLink: v[11],
+ MkNod: v[12],
+ Remove: v[13],
+ RmDir: v[14],
+ Rename: v[15],
+ Link: v[16],
+ ReadDir: v[17],
+ ReadDirPlus: v[18],
+ FsStat: v[19],
+ FsInfo: v[20],
+ PathConf: v[21],
+ Commit: v[22],
+ }, nil
+}
+
+func parseClientV4Stats(v []uint64) (ClientV4Stats, error) {
+ values := int(v[0])
+ if len(v[1:]) != values {
+ return ClientV4Stats{}, fmt.Errorf("invalid ClientV4Stats line %q", v)
+ }
+
+ // This function currently supports mapping 59 NFS v4 client stats. Older
+ // kernels may emit fewer stats, so we must detect this and pad out the
+ // values to match the expected slice size.
+ if values < 59 {
+ newValues := make([]uint64, 60)
+ copy(newValues, v)
+ v = newValues
+ }
+
+ return ClientV4Stats{
+ Null: v[1],
+ Read: v[2],
+ Write: v[3],
+ Commit: v[4],
+ Open: v[5],
+ OpenConfirm: v[6],
+ OpenNoattr: v[7],
+ OpenDowngrade: v[8],
+ Close: v[9],
+ Setattr: v[10],
+ FsInfo: v[11],
+ Renew: v[12],
+ SetClientID: v[13],
+ SetClientIDConfirm: v[14],
+ Lock: v[15],
+ Lockt: v[16],
+ Locku: v[17],
+ Access: v[18],
+ Getattr: v[19],
+ Lookup: v[20],
+ LookupRoot: v[21],
+ Remove: v[22],
+ Rename: v[23],
+ Link: v[24],
+ Symlink: v[25],
+ Create: v[26],
+ Pathconf: v[27],
+ StatFs: v[28],
+ ReadLink: v[29],
+ ReadDir: v[30],
+ ServerCaps: v[31],
+ DelegReturn: v[32],
+ GetACL: v[33],
+ SetACL: v[34],
+ FsLocations: v[35],
+ ReleaseLockowner: v[36],
+ Secinfo: v[37],
+ FsidPresent: v[38],
+ ExchangeID: v[39],
+ CreateSession: v[40],
+ DestroySession: v[41],
+ Sequence: v[42],
+ GetLeaseTime: v[43],
+ ReclaimComplete: v[44],
+ LayoutGet: v[45],
+ GetDeviceInfo: v[46],
+ LayoutCommit: v[47],
+ LayoutReturn: v[48],
+ SecinfoNoName: v[49],
+ TestStateID: v[50],
+ FreeStateID: v[51],
+ GetDeviceList: v[52],
+ BindConnToSession: v[53],
+ DestroyClientID: v[54],
+ Seek: v[55],
+ Allocate: v[56],
+ DeAllocate: v[57],
+ LayoutStats: v[58],
+ Clone: v[59],
+ }, nil
+}
+
+func parseServerV4Stats(v []uint64) (ServerV4Stats, error) {
+ values := int(v[0])
+ if len(v[1:]) != values || values != 2 {
+ return ServerV4Stats{}, fmt.Errorf("invalid V4Stats line %q", v)
+ }
+
+ return ServerV4Stats{
+ Null: v[1],
+ Compound: v[2],
+ }, nil
+}
+
+func parseV4Ops(v []uint64) (V4Ops, error) {
+ values := int(v[0])
+ if len(v[1:]) != values || values < 39 {
+ return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v)
+ }
+
+ stats := V4Ops{
+ Op0Unused: v[1],
+ Op1Unused: v[2],
+ Op2Future: v[3],
+ Access: v[4],
+ Close: v[5],
+ Commit: v[6],
+ Create: v[7],
+ DelegPurge: v[8],
+ DelegReturn: v[9],
+ GetAttr: v[10],
+ GetFH: v[11],
+ Link: v[12],
+ Lock: v[13],
+ Lockt: v[14],
+ Locku: v[15],
+ Lookup: v[16],
+ LookupRoot: v[17],
+ Nverify: v[18],
+ Open: v[19],
+ OpenAttr: v[20],
+ OpenConfirm: v[21],
+ OpenDgrd: v[22],
+ PutFH: v[23],
+ PutPubFH: v[24],
+ PutRootFH: v[25],
+ Read: v[26],
+ ReadDir: v[27],
+ ReadLink: v[28],
+ Remove: v[29],
+ Rename: v[30],
+ Renew: v[31],
+ RestoreFH: v[32],
+ SaveFH: v[33],
+ SecInfo: v[34],
+ SetAttr: v[35],
+ Verify: v[36],
+ Write: v[37],
+ RelLockOwner: v[38],
+ }
+
+ return stats, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go b/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go
new file mode 100644
index 00000000..c0d3a5ad
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go
@@ -0,0 +1,67 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package nfs
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/prometheus/procfs/internal/util"
+)
+
+// ParseClientRPCStats returns stats read from /proc/net/rpc/nfs
+func ParseClientRPCStats(r io.Reader) (*ClientRPCStats, error) {
+ stats := &ClientRPCStats{}
+
+ scanner := bufio.NewScanner(r)
+ for scanner.Scan() {
+ line := scanner.Text()
+ parts := strings.Fields(scanner.Text())
+ // require at least
+ if len(parts) < 2 {
+ return nil, fmt.Errorf("invalid NFS metric line %q", line)
+ }
+
+ values, err := util.ParseUint64s(parts[1:])
+ if err != nil {
+ return nil, fmt.Errorf("error parsing NFS metric line: %s", err)
+ }
+
+ switch metricLine := parts[0]; metricLine {
+ case "net":
+ stats.Network, err = parseNetwork(values)
+ case "rpc":
+ stats.ClientRPC, err = parseClientRPC(values)
+ case "proc2":
+ stats.V2Stats, err = parseV2Stats(values)
+ case "proc3":
+ stats.V3Stats, err = parseV3Stats(values)
+ case "proc4":
+ stats.ClientV4Stats, err = parseClientV4Stats(values)
+ default:
+ return nil, fmt.Errorf("unknown NFS metric line %q", metricLine)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("errors parsing NFS metric line: %s", err)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("error scanning NFS file: %s", err)
+ }
+
+ return stats, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go b/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go
new file mode 100644
index 00000000..57bb4a35
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go
@@ -0,0 +1,89 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package nfs
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/prometheus/procfs/internal/util"
+)
+
+// ParseServerRPCStats returns stats read from /proc/net/rpc/nfsd
+func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) {
+ stats := &ServerRPCStats{}
+
+ scanner := bufio.NewScanner(r)
+ for scanner.Scan() {
+ line := scanner.Text()
+ parts := strings.Fields(scanner.Text())
+ // require at least
+ if len(parts) < 2 {
+ return nil, fmt.Errorf("invalid NFSd metric line %q", line)
+ }
+ label := parts[0]
+
+ var values []uint64
+ var err error
+ if label == "th" {
+ if len(parts) < 3 {
+ return nil, fmt.Errorf("invalid NFSd th metric line %q", line)
+ }
+ values, err = util.ParseUint64s(parts[1:3])
+ } else {
+ values, err = util.ParseUint64s(parts[1:])
+ }
+ if err != nil {
+ return nil, fmt.Errorf("error parsing NFSd metric line: %s", err)
+ }
+
+ switch metricLine := parts[0]; metricLine {
+ case "rc":
+ stats.ReplyCache, err = parseReplyCache(values)
+ case "fh":
+ stats.FileHandles, err = parseFileHandles(values)
+ case "io":
+ stats.InputOutput, err = parseInputOutput(values)
+ case "th":
+ stats.Threads, err = parseThreads(values)
+ case "ra":
+ stats.ReadAheadCache, err = parseReadAheadCache(values)
+ case "net":
+ stats.Network, err = parseNetwork(values)
+ case "rpc":
+ stats.ServerRPC, err = parseServerRPC(values)
+ case "proc2":
+ stats.V2Stats, err = parseV2Stats(values)
+ case "proc3":
+ stats.V3Stats, err = parseV3Stats(values)
+ case "proc4":
+ stats.ServerV4Stats, err = parseServerV4Stats(values)
+ case "proc4ops":
+ stats.V4Ops, err = parseV4Ops(values)
+ default:
+ return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("error scanning NFSd file: %s", err)
+ }
+
+ return stats, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/proc.go b/vendor/github.com/prometheus/procfs/proc.go
new file mode 100644
index 00000000..7cf5b8ac
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/proc.go
@@ -0,0 +1,238 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// Proc provides information about a running process.
+type Proc struct {
+ // The process ID.
+ PID int
+
+ fs FS
+}
+
+// Procs represents a list of Proc structs.
+type Procs []Proc
+
+func (p Procs) Len() int { return len(p) }
+func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID }
+
+// Self returns a process for the current process read via /proc/self.
+func Self() (Proc, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return Proc{}, err
+ }
+ return fs.Self()
+}
+
+// NewProc returns a process for the given pid under /proc.
+func NewProc(pid int) (Proc, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return Proc{}, err
+ }
+ return fs.NewProc(pid)
+}
+
+// AllProcs returns a list of all currently available processes under /proc.
+func AllProcs() (Procs, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return Procs{}, err
+ }
+ return fs.AllProcs()
+}
+
+// Self returns a process for the current process.
+func (fs FS) Self() (Proc, error) {
+ p, err := os.Readlink(fs.Path("self"))
+ if err != nil {
+ return Proc{}, err
+ }
+ pid, err := strconv.Atoi(strings.Replace(p, string(fs), "", -1))
+ if err != nil {
+ return Proc{}, err
+ }
+ return fs.NewProc(pid)
+}
+
+// NewProc returns a process for the given pid.
+func (fs FS) NewProc(pid int) (Proc, error) {
+ if _, err := os.Stat(fs.Path(strconv.Itoa(pid))); err != nil {
+ return Proc{}, err
+ }
+ return Proc{PID: pid, fs: fs}, nil
+}
+
+// AllProcs returns a list of all currently available processes.
+func (fs FS) AllProcs() (Procs, error) {
+ d, err := os.Open(fs.Path())
+ if err != nil {
+ return Procs{}, err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(-1)
+ if err != nil {
+ return Procs{}, fmt.Errorf("could not read %s: %s", d.Name(), err)
+ }
+
+ p := Procs{}
+ for _, n := range names {
+ pid, err := strconv.ParseInt(n, 10, 64)
+ if err != nil {
+ continue
+ }
+ p = append(p, Proc{PID: int(pid), fs: fs})
+ }
+
+ return p, nil
+}
+
+// CmdLine returns the command line of a process.
+func (p Proc) CmdLine() ([]string, error) {
+ f, err := os.Open(p.path("cmdline"))
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ data, err := ioutil.ReadAll(f)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(data) < 1 {
+ return []string{}, nil
+ }
+
+ return strings.Split(string(bytes.TrimRight(data, string("\x00"))), string(byte(0))), nil
+}
+
+// Comm returns the command name of a process.
+func (p Proc) Comm() (string, error) {
+ f, err := os.Open(p.path("comm"))
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ data, err := ioutil.ReadAll(f)
+ if err != nil {
+ return "", err
+ }
+
+ return strings.TrimSpace(string(data)), nil
+}
+
+// Executable returns the absolute path of the executable command of a process.
+func (p Proc) Executable() (string, error) {
+ exe, err := os.Readlink(p.path("exe"))
+ if os.IsNotExist(err) {
+ return "", nil
+ }
+
+ return exe, err
+}
+
+// FileDescriptors returns the currently open file descriptors of a process.
+func (p Proc) FileDescriptors() ([]uintptr, error) {
+ names, err := p.fileDescriptors()
+ if err != nil {
+ return nil, err
+ }
+
+ fds := make([]uintptr, len(names))
+ for i, n := range names {
+ fd, err := strconv.ParseInt(n, 10, 32)
+ if err != nil {
+ return nil, fmt.Errorf("could not parse fd %s: %s", n, err)
+ }
+ fds[i] = uintptr(fd)
+ }
+
+ return fds, nil
+}
+
+// FileDescriptorTargets returns the targets of all file descriptors of a process.
+// If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string.
+func (p Proc) FileDescriptorTargets() ([]string, error) {
+ names, err := p.fileDescriptors()
+ if err != nil {
+ return nil, err
+ }
+
+ targets := make([]string, len(names))
+
+ for i, name := range names {
+ target, err := os.Readlink(p.path("fd", name))
+ if err == nil {
+ targets[i] = target
+ }
+ }
+
+ return targets, nil
+}
+
+// FileDescriptorsLen returns the number of currently open file descriptors of
+// a process.
+func (p Proc) FileDescriptorsLen() (int, error) {
+ fds, err := p.fileDescriptors()
+ if err != nil {
+ return 0, err
+ }
+
+ return len(fds), nil
+}
+
+// MountStats retrieves statistics and configuration for mount points in a
+// process's namespace.
+func (p Proc) MountStats() ([]*Mount, error) {
+ f, err := os.Open(p.path("mountstats"))
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return parseMountStats(f)
+}
+
+func (p Proc) fileDescriptors() ([]string, error) {
+ d, err := os.Open(p.path("fd"))
+ if err != nil {
+ return nil, err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(-1)
+ if err != nil {
+ return nil, fmt.Errorf("could not read %s: %s", d.Name(), err)
+ }
+
+ return names, nil
+}
+
+func (p Proc) path(pa ...string) string {
+ return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
+}
diff --git a/vendor/github.com/prometheus/procfs/proc_io.go b/vendor/github.com/prometheus/procfs/proc_io.go
new file mode 100644
index 00000000..0251c83b
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/proc_io.go
@@ -0,0 +1,65 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+)
+
+// ProcIO models the content of /proc//io.
+type ProcIO struct {
+ // Chars read.
+ RChar uint64
+ // Chars written.
+ WChar uint64
+ // Read syscalls.
+ SyscR uint64
+ // Write syscalls.
+ SyscW uint64
+ // Bytes read.
+ ReadBytes uint64
+ // Bytes written.
+ WriteBytes uint64
+ // Bytes written, but taking into account truncation. See
+ // Documentation/filesystems/proc.txt in the kernel sources for
+ // detailed explanation.
+ CancelledWriteBytes int64
+}
+
+// NewIO creates a new ProcIO instance from a given Proc instance.
+func (p Proc) NewIO() (ProcIO, error) {
+ pio := ProcIO{}
+
+ f, err := os.Open(p.path("io"))
+ if err != nil {
+ return pio, err
+ }
+ defer f.Close()
+
+ data, err := ioutil.ReadAll(f)
+ if err != nil {
+ return pio, err
+ }
+
+ ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" +
+ "read_bytes: %d\nwrite_bytes: %d\n" +
+ "cancelled_write_bytes: %d\n"
+
+ _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
+ &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
+
+ return pio, err
+}
diff --git a/vendor/github.com/prometheus/procfs/proc_limits.go b/vendor/github.com/prometheus/procfs/proc_limits.go
new file mode 100644
index 00000000..f04ba6fd
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/proc_limits.go
@@ -0,0 +1,150 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "regexp"
+ "strconv"
+)
+
+// ProcLimits represents the soft limits for each of the process's resource
+// limits. For more information see getrlimit(2):
+// http://man7.org/linux/man-pages/man2/getrlimit.2.html.
+type ProcLimits struct {
+ // CPU time limit in seconds.
+ CPUTime int64
+ // Maximum size of files that the process may create.
+ FileSize int64
+ // Maximum size of the process's data segment (initialized data,
+ // uninitialized data, and heap).
+ DataSize int64
+ // Maximum size of the process stack in bytes.
+ StackSize int64
+ // Maximum size of a core file.
+ CoreFileSize int64
+ // Limit of the process's resident set in pages.
+ ResidentSet int64
+ // Maximum number of processes that can be created for the real user ID of
+ // the calling process.
+ Processes int64
+ // Value one greater than the maximum file descriptor number that can be
+ // opened by this process.
+ OpenFiles int64
+ // Maximum number of bytes of memory that may be locked into RAM.
+ LockedMemory int64
+ // Maximum size of the process's virtual memory address space in bytes.
+ AddressSpace int64
+ // Limit on the combined number of flock(2) locks and fcntl(2) leases that
+ // this process may establish.
+ FileLocks int64
+ // Limit of signals that may be queued for the real user ID of the calling
+ // process.
+ PendingSignals int64
+ // Limit on the number of bytes that can be allocated for POSIX message
+ // queues for the real user ID of the calling process.
+ MsqqueueSize int64
+ // Limit of the nice priority set using setpriority(2) or nice(2).
+ NicePriority int64
+ // Limit of the real-time priority set using sched_setscheduler(2) or
+ // sched_setparam(2).
+ RealtimePriority int64
+ // Limit (in microseconds) on the amount of CPU time that a process
+ // scheduled under a real-time scheduling policy may consume without making
+ // a blocking system call.
+ RealtimeTimeout int64
+}
+
+const (
+ limitsFields = 3
+ limitsUnlimited = "unlimited"
+)
+
+var (
+ limitsDelimiter = regexp.MustCompile(" +")
+)
+
+// NewLimits returns the current soft limits of the process.
+func (p Proc) NewLimits() (ProcLimits, error) {
+ f, err := os.Open(p.path("limits"))
+ if err != nil {
+ return ProcLimits{}, err
+ }
+ defer f.Close()
+
+ var (
+ l = ProcLimits{}
+ s = bufio.NewScanner(f)
+ )
+ for s.Scan() {
+ fields := limitsDelimiter.Split(s.Text(), limitsFields)
+ if len(fields) != limitsFields {
+ return ProcLimits{}, fmt.Errorf(
+ "couldn't parse %s line %s", f.Name(), s.Text())
+ }
+
+ switch fields[0] {
+ case "Max cpu time":
+ l.CPUTime, err = parseInt(fields[1])
+ case "Max file size":
+ l.FileSize, err = parseInt(fields[1])
+ case "Max data size":
+ l.DataSize, err = parseInt(fields[1])
+ case "Max stack size":
+ l.StackSize, err = parseInt(fields[1])
+ case "Max core file size":
+ l.CoreFileSize, err = parseInt(fields[1])
+ case "Max resident set":
+ l.ResidentSet, err = parseInt(fields[1])
+ case "Max processes":
+ l.Processes, err = parseInt(fields[1])
+ case "Max open files":
+ l.OpenFiles, err = parseInt(fields[1])
+ case "Max locked memory":
+ l.LockedMemory, err = parseInt(fields[1])
+ case "Max address space":
+ l.AddressSpace, err = parseInt(fields[1])
+ case "Max file locks":
+ l.FileLocks, err = parseInt(fields[1])
+ case "Max pending signals":
+ l.PendingSignals, err = parseInt(fields[1])
+ case "Max msgqueue size":
+ l.MsqqueueSize, err = parseInt(fields[1])
+ case "Max nice priority":
+ l.NicePriority, err = parseInt(fields[1])
+ case "Max realtime priority":
+ l.RealtimePriority, err = parseInt(fields[1])
+ case "Max realtime timeout":
+ l.RealtimeTimeout, err = parseInt(fields[1])
+ }
+ if err != nil {
+ return ProcLimits{}, err
+ }
+ }
+
+ return l, s.Err()
+}
+
+func parseInt(s string) (int64, error) {
+ if s == limitsUnlimited {
+ return -1, nil
+ }
+ i, err := strconv.ParseInt(s, 10, 64)
+ if err != nil {
+ return 0, fmt.Errorf("couldn't parse value %s: %s", s, err)
+ }
+ return i, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/proc_ns.go b/vendor/github.com/prometheus/procfs/proc_ns.go
new file mode 100644
index 00000000..d06c26eb
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/proc_ns.go
@@ -0,0 +1,68 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// Namespace represents a single namespace of a process.
+type Namespace struct {
+ Type string // Namespace type.
+ Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match.
+}
+
+// Namespaces contains all of the namespaces that the process is contained in.
+type Namespaces map[string]Namespace
+
+// NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the
+// process is a member.
+func (p Proc) NewNamespaces() (Namespaces, error) {
+ d, err := os.Open(p.path("ns"))
+ if err != nil {
+ return nil, err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(-1)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read contents of ns dir: %v", err)
+ }
+
+ ns := make(Namespaces, len(names))
+ for _, name := range names {
+ target, err := os.Readlink(p.path("ns", name))
+ if err != nil {
+ return nil, err
+ }
+
+ fields := strings.SplitN(target, ":", 2)
+ if len(fields) != 2 {
+ return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target)
+ }
+
+ typ := fields[0]
+ inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err)
+ }
+
+ ns[name] = Namespace{typ, uint32(inode)}
+ }
+
+ return ns, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/proc_stat.go b/vendor/github.com/prometheus/procfs/proc_stat.go
new file mode 100644
index 00000000..3cf2a9f1
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/proc_stat.go
@@ -0,0 +1,188 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+)
+
+// Originally, this USER_HZ value was dynamically retrieved via a sysconf call
+// which required cgo. However, that caused a lot of problems regarding
+// cross-compilation. Alternatives such as running a binary to determine the
+// value, or trying to derive it in some other way were all problematic. After
+// much research it was determined that USER_HZ is actually hardcoded to 100 on
+// all Go-supported platforms as of the time of this writing. This is why we
+// decided to hardcode it here as well. It is not impossible that there could
+// be systems with exceptions, but they should be very exotic edge cases, and
+// in that case, the worst outcome will be two misreported metrics.
+//
+// See also the following discussions:
+//
+// - https://github.com/prometheus/node_exporter/issues/52
+// - https://github.com/prometheus/procfs/pull/2
+// - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue
+const userHZ = 100
+
+// ProcStat provides status information about the process,
+// read from /proc/[pid]/stat.
+type ProcStat struct {
+ // The process ID.
+ PID int
+ // The filename of the executable.
+ Comm string
+ // The process state.
+ State string
+ // The PID of the parent of this process.
+ PPID int
+ // The process group ID of the process.
+ PGRP int
+ // The session ID of the process.
+ Session int
+ // The controlling terminal of the process.
+ TTY int
+ // The ID of the foreground process group of the controlling terminal of
+ // the process.
+ TPGID int
+ // The kernel flags word of the process.
+ Flags uint
+ // The number of minor faults the process has made which have not required
+ // loading a memory page from disk.
+ MinFlt uint
+ // The number of minor faults that the process's waited-for children have
+ // made.
+ CMinFlt uint
+ // The number of major faults the process has made which have required
+ // loading a memory page from disk.
+ MajFlt uint
+ // The number of major faults that the process's waited-for children have
+ // made.
+ CMajFlt uint
+ // Amount of time that this process has been scheduled in user mode,
+ // measured in clock ticks.
+ UTime uint
+ // Amount of time that this process has been scheduled in kernel mode,
+ // measured in clock ticks.
+ STime uint
+ // Amount of time that this process's waited-for children have been
+ // scheduled in user mode, measured in clock ticks.
+ CUTime uint
+ // Amount of time that this process's waited-for children have been
+ // scheduled in kernel mode, measured in clock ticks.
+ CSTime uint
+ // For processes running a real-time scheduling policy, this is the negated
+ // scheduling priority, minus one.
+ Priority int
+ // The nice value, a value in the range 19 (low priority) to -20 (high
+ // priority).
+ Nice int
+ // Number of threads in this process.
+ NumThreads int
+ // The time the process started after system boot, the value is expressed
+ // in clock ticks.
+ Starttime uint64
+ // Virtual memory size in bytes.
+ VSize int
+ // Resident set size in pages.
+ RSS int
+
+ fs FS
+}
+
+// NewStat returns the current status information of the process.
+func (p Proc) NewStat() (ProcStat, error) {
+ f, err := os.Open(p.path("stat"))
+ if err != nil {
+ return ProcStat{}, err
+ }
+ defer f.Close()
+
+ data, err := ioutil.ReadAll(f)
+ if err != nil {
+ return ProcStat{}, err
+ }
+
+ var (
+ ignore int
+
+ s = ProcStat{PID: p.PID, fs: p.fs}
+ l = bytes.Index(data, []byte("("))
+ r = bytes.LastIndex(data, []byte(")"))
+ )
+
+ if l < 0 || r < 0 {
+ return ProcStat{}, fmt.Errorf(
+ "unexpected format, couldn't extract comm: %s",
+ data,
+ )
+ }
+
+ s.Comm = string(data[l+1 : r])
+ _, err = fmt.Fscan(
+ bytes.NewBuffer(data[r+2:]),
+ &s.State,
+ &s.PPID,
+ &s.PGRP,
+ &s.Session,
+ &s.TTY,
+ &s.TPGID,
+ &s.Flags,
+ &s.MinFlt,
+ &s.CMinFlt,
+ &s.MajFlt,
+ &s.CMajFlt,
+ &s.UTime,
+ &s.STime,
+ &s.CUTime,
+ &s.CSTime,
+ &s.Priority,
+ &s.Nice,
+ &s.NumThreads,
+ &ignore,
+ &s.Starttime,
+ &s.VSize,
+ &s.RSS,
+ )
+ if err != nil {
+ return ProcStat{}, err
+ }
+
+ return s, nil
+}
+
+// VirtualMemory returns the virtual memory size in bytes.
+func (s ProcStat) VirtualMemory() int {
+ return s.VSize
+}
+
+// ResidentMemory returns the resident memory size in bytes.
+func (s ProcStat) ResidentMemory() int {
+ return s.RSS * os.Getpagesize()
+}
+
+// StartTime returns the unix timestamp of the process in seconds.
+func (s ProcStat) StartTime() (float64, error) {
+ stat, err := s.fs.NewStat()
+ if err != nil {
+ return 0, err
+ }
+ return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil
+}
+
+// CPUTime returns the total CPU user and system time in seconds.
+func (s ProcStat) CPUTime() float64 {
+ return float64(s.UTime+s.STime) / userHZ
+}
diff --git a/vendor/github.com/prometheus/procfs/stat.go b/vendor/github.com/prometheus/procfs/stat.go
new file mode 100644
index 00000000..61eb6b0e
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/stat.go
@@ -0,0 +1,232 @@
+// Copyright 2018 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// CPUStat shows how much time the cpu spend in various stages.
+type CPUStat struct {
+ User float64
+ Nice float64
+ System float64
+ Idle float64
+ Iowait float64
+ IRQ float64
+ SoftIRQ float64
+ Steal float64
+ Guest float64
+ GuestNice float64
+}
+
+// SoftIRQStat represent the softirq statistics as exported in the procfs stat file.
+// A nice introduction can be found at https://0xax.gitbooks.io/linux-insides/content/interrupts/interrupts-9.html
+// It is possible to get per-cpu stats by reading /proc/softirqs
+type SoftIRQStat struct {
+ Hi uint64
+ Timer uint64
+ NetTx uint64
+ NetRx uint64
+ Block uint64
+ BlockIoPoll uint64
+ Tasklet uint64
+ Sched uint64
+ Hrtimer uint64
+ Rcu uint64
+}
+
+// Stat represents kernel/system statistics.
+type Stat struct {
+ // Boot time in seconds since the Epoch.
+ BootTime uint64
+ // Summed up cpu statistics.
+ CPUTotal CPUStat
+ // Per-CPU statistics.
+ CPU []CPUStat
+ // Number of times interrupts were handled, which contains numbered and unnumbered IRQs.
+ IRQTotal uint64
+ // Number of times a numbered IRQ was triggered.
+ IRQ []uint64
+ // Number of times a context switch happened.
+ ContextSwitches uint64
+ // Number of times a process was created.
+ ProcessCreated uint64
+ // Number of processes currently running.
+ ProcessesRunning uint64
+ // Number of processes currently blocked (waiting for IO).
+ ProcessesBlocked uint64
+ // Number of times a softirq was scheduled.
+ SoftIRQTotal uint64
+ // Detailed softirq statistics.
+ SoftIRQ SoftIRQStat
+}
+
+// NewStat returns kernel/system statistics read from /proc/stat.
+func NewStat() (Stat, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return Stat{}, err
+ }
+
+ return fs.NewStat()
+}
+
+// Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum).
+func parseCPUStat(line string) (CPUStat, int64, error) {
+ cpuStat := CPUStat{}
+ var cpu string
+
+ count, err := fmt.Sscanf(line, "%s %f %f %f %f %f %f %f %f %f %f",
+ &cpu,
+ &cpuStat.User, &cpuStat.Nice, &cpuStat.System, &cpuStat.Idle,
+ &cpuStat.Iowait, &cpuStat.IRQ, &cpuStat.SoftIRQ, &cpuStat.Steal,
+ &cpuStat.Guest, &cpuStat.GuestNice)
+
+ if err != nil && err != io.EOF {
+ return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): %s", line, err)
+ }
+ if count == 0 {
+ return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu): 0 elements parsed", line)
+ }
+
+ cpuStat.User /= userHZ
+ cpuStat.Nice /= userHZ
+ cpuStat.System /= userHZ
+ cpuStat.Idle /= userHZ
+ cpuStat.Iowait /= userHZ
+ cpuStat.IRQ /= userHZ
+ cpuStat.SoftIRQ /= userHZ
+ cpuStat.Steal /= userHZ
+ cpuStat.Guest /= userHZ
+ cpuStat.GuestNice /= userHZ
+
+ if cpu == "cpu" {
+ return cpuStat, -1, nil
+ }
+
+ cpuID, err := strconv.ParseInt(cpu[3:], 10, 64)
+ if err != nil {
+ return CPUStat{}, -1, fmt.Errorf("couldn't parse %s (cpu/cpuid): %s", line, err)
+ }
+
+ return cpuStat, cpuID, nil
+}
+
+// Parse a softirq line.
+func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) {
+ softIRQStat := SoftIRQStat{}
+ var total uint64
+ var prefix string
+
+ _, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d",
+ &prefix, &total,
+ &softIRQStat.Hi, &softIRQStat.Timer, &softIRQStat.NetTx, &softIRQStat.NetRx,
+ &softIRQStat.Block, &softIRQStat.BlockIoPoll,
+ &softIRQStat.Tasklet, &softIRQStat.Sched,
+ &softIRQStat.Hrtimer, &softIRQStat.Rcu)
+
+ if err != nil {
+ return SoftIRQStat{}, 0, fmt.Errorf("couldn't parse %s (softirq): %s", line, err)
+ }
+
+ return softIRQStat, total, nil
+}
+
+// NewStat returns an information about current kernel/system statistics.
+func (fs FS) NewStat() (Stat, error) {
+ // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
+
+ f, err := os.Open(fs.Path("stat"))
+ if err != nil {
+ return Stat{}, err
+ }
+ defer f.Close()
+
+ stat := Stat{}
+
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ line := scanner.Text()
+ parts := strings.Fields(scanner.Text())
+ // require at least
+ if len(parts) < 2 {
+ continue
+ }
+ switch {
+ case parts[0] == "btime":
+ if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s (btime): %s", parts[1], err)
+ }
+ case parts[0] == "intr":
+ if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s (intr): %s", parts[1], err)
+ }
+ numberedIRQs := parts[2:]
+ stat.IRQ = make([]uint64, len(numberedIRQs))
+ for i, count := range numberedIRQs {
+ if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s (intr%d): %s", count, i, err)
+ }
+ }
+ case parts[0] == "ctxt":
+ if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s (ctxt): %s", parts[1], err)
+ }
+ case parts[0] == "processes":
+ if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s (processes): %s", parts[1], err)
+ }
+ case parts[0] == "procs_running":
+ if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s (procs_running): %s", parts[1], err)
+ }
+ case parts[0] == "procs_blocked":
+ if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s (procs_blocked): %s", parts[1], err)
+ }
+ case parts[0] == "softirq":
+ softIRQStats, total, err := parseSoftIRQStat(line)
+ if err != nil {
+ return Stat{}, err
+ }
+ stat.SoftIRQTotal = total
+ stat.SoftIRQ = softIRQStats
+ case strings.HasPrefix(parts[0], "cpu"):
+ cpuStat, cpuID, err := parseCPUStat(line)
+ if err != nil {
+ return Stat{}, err
+ }
+ if cpuID == -1 {
+ stat.CPUTotal = cpuStat
+ } else {
+ for int64(len(stat.CPU)) <= cpuID {
+ stat.CPU = append(stat.CPU, CPUStat{})
+ }
+ stat.CPU[cpuID] = cpuStat
+ }
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return Stat{}, fmt.Errorf("couldn't parse %s: %s", f.Name(), err)
+ }
+
+ return stat, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/xfrm.go b/vendor/github.com/prometheus/procfs/xfrm.go
new file mode 100644
index 00000000..8f1508f0
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/xfrm.go
@@ -0,0 +1,187 @@
+// Copyright 2017 Prometheus Team
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package procfs
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// XfrmStat models the contents of /proc/net/xfrm_stat.
+type XfrmStat struct {
+ // All errors which are not matched by other
+ XfrmInError int
+ // No buffer is left
+ XfrmInBufferError int
+ // Header Error
+ XfrmInHdrError int
+ // No state found
+ // i.e. either inbound SPI, address, or IPSEC protocol at SA is wrong
+ XfrmInNoStates int
+ // Transformation protocol specific error
+ // e.g. SA Key is wrong
+ XfrmInStateProtoError int
+ // Transformation mode specific error
+ XfrmInStateModeError int
+ // Sequence error
+ // e.g. sequence number is out of window
+ XfrmInStateSeqError int
+ // State is expired
+ XfrmInStateExpired int
+ // State has mismatch option
+ // e.g. UDP encapsulation type is mismatched
+ XfrmInStateMismatch int
+ // State is invalid
+ XfrmInStateInvalid int
+ // No matching template for states
+ // e.g. Inbound SAs are correct but SP rule is wrong
+ XfrmInTmplMismatch int
+ // No policy is found for states
+ // e.g. Inbound SAs are correct but no SP is found
+ XfrmInNoPols int
+ // Policy discards
+ XfrmInPolBlock int
+ // Policy error
+ XfrmInPolError int
+ // All errors which are not matched by others
+ XfrmOutError int
+ // Bundle generation error
+ XfrmOutBundleGenError int
+ // Bundle check error
+ XfrmOutBundleCheckError int
+ // No state was found
+ XfrmOutNoStates int
+ // Transformation protocol specific error
+ XfrmOutStateProtoError int
+ // Transportation mode specific error
+ XfrmOutStateModeError int
+ // Sequence error
+ // i.e sequence number overflow
+ XfrmOutStateSeqError int
+ // State is expired
+ XfrmOutStateExpired int
+ // Policy discads
+ XfrmOutPolBlock int
+ // Policy is dead
+ XfrmOutPolDead int
+ // Policy Error
+ XfrmOutPolError int
+ XfrmFwdHdrError int
+ XfrmOutStateInvalid int
+ XfrmAcquireError int
+}
+
+// NewXfrmStat reads the xfrm_stat statistics.
+func NewXfrmStat() (XfrmStat, error) {
+ fs, err := NewFS(DefaultMountPoint)
+ if err != nil {
+ return XfrmStat{}, err
+ }
+
+ return fs.NewXfrmStat()
+}
+
+// NewXfrmStat reads the xfrm_stat statistics from the 'proc' filesystem.
+func (fs FS) NewXfrmStat() (XfrmStat, error) {
+ file, err := os.Open(fs.Path("net/xfrm_stat"))
+ if err != nil {
+ return XfrmStat{}, err
+ }
+ defer file.Close()
+
+ var (
+ x = XfrmStat{}
+ s = bufio.NewScanner(file)
+ )
+
+ for s.Scan() {
+ fields := strings.Fields(s.Text())
+
+ if len(fields) != 2 {
+ return XfrmStat{}, fmt.Errorf(
+ "couldn't parse %s line %s", file.Name(), s.Text())
+ }
+
+ name := fields[0]
+ value, err := strconv.Atoi(fields[1])
+ if err != nil {
+ return XfrmStat{}, err
+ }
+
+ switch name {
+ case "XfrmInError":
+ x.XfrmInError = value
+ case "XfrmInBufferError":
+ x.XfrmInBufferError = value
+ case "XfrmInHdrError":
+ x.XfrmInHdrError = value
+ case "XfrmInNoStates":
+ x.XfrmInNoStates = value
+ case "XfrmInStateProtoError":
+ x.XfrmInStateProtoError = value
+ case "XfrmInStateModeError":
+ x.XfrmInStateModeError = value
+ case "XfrmInStateSeqError":
+ x.XfrmInStateSeqError = value
+ case "XfrmInStateExpired":
+ x.XfrmInStateExpired = value
+ case "XfrmInStateInvalid":
+ x.XfrmInStateInvalid = value
+ case "XfrmInTmplMismatch":
+ x.XfrmInTmplMismatch = value
+ case "XfrmInNoPols":
+ x.XfrmInNoPols = value
+ case "XfrmInPolBlock":
+ x.XfrmInPolBlock = value
+ case "XfrmInPolError":
+ x.XfrmInPolError = value
+ case "XfrmOutError":
+ x.XfrmOutError = value
+ case "XfrmInStateMismatch":
+ x.XfrmInStateMismatch = value
+ case "XfrmOutBundleGenError":
+ x.XfrmOutBundleGenError = value
+ case "XfrmOutBundleCheckError":
+ x.XfrmOutBundleCheckError = value
+ case "XfrmOutNoStates":
+ x.XfrmOutNoStates = value
+ case "XfrmOutStateProtoError":
+ x.XfrmOutStateProtoError = value
+ case "XfrmOutStateModeError":
+ x.XfrmOutStateModeError = value
+ case "XfrmOutStateSeqError":
+ x.XfrmOutStateSeqError = value
+ case "XfrmOutStateExpired":
+ x.XfrmOutStateExpired = value
+ case "XfrmOutPolBlock":
+ x.XfrmOutPolBlock = value
+ case "XfrmOutPolDead":
+ x.XfrmOutPolDead = value
+ case "XfrmOutPolError":
+ x.XfrmOutPolError = value
+ case "XfrmFwdHdrError":
+ x.XfrmFwdHdrError = value
+ case "XfrmOutStateInvalid":
+ x.XfrmOutStateInvalid = value
+ case "XfrmAcquireError":
+ x.XfrmAcquireError = value
+ }
+
+ }
+
+ return x, s.Err()
+}
diff --git a/vendor/github.com/prometheus/procfs/xfs/parse.go b/vendor/github.com/prometheus/procfs/xfs/parse.go
new file mode 100644
index 00000000..2bc0ef34
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/xfs/parse.go
@@ -0,0 +1,330 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package xfs
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/prometheus/procfs/internal/util"
+)
+
+// ParseStats parses a Stats from an input io.Reader, using the format
+// found in /proc/fs/xfs/stat.
+func ParseStats(r io.Reader) (*Stats, error) {
+ const (
+ // Fields parsed into stats structures.
+ fieldExtentAlloc = "extent_alloc"
+ fieldAbt = "abt"
+ fieldBlkMap = "blk_map"
+ fieldBmbt = "bmbt"
+ fieldDir = "dir"
+ fieldTrans = "trans"
+ fieldIg = "ig"
+ fieldLog = "log"
+ fieldRw = "rw"
+ fieldAttr = "attr"
+ fieldIcluster = "icluster"
+ fieldVnodes = "vnodes"
+ fieldBuf = "buf"
+ fieldXpc = "xpc"
+
+ // Unimplemented at this time due to lack of documentation.
+ fieldPushAil = "push_ail"
+ fieldXstrat = "xstrat"
+ fieldAbtb2 = "abtb2"
+ fieldAbtc2 = "abtc2"
+ fieldBmbt2 = "bmbt2"
+ fieldIbt2 = "ibt2"
+ fieldFibt2 = "fibt2"
+ fieldQm = "qm"
+ fieldDebug = "debug"
+ )
+
+ var xfss Stats
+
+ s := bufio.NewScanner(r)
+ for s.Scan() {
+ // Expect at least a string label and a single integer value, ex:
+ // - abt 0
+ // - rw 1 2
+ ss := strings.Fields(string(s.Bytes()))
+ if len(ss) < 2 {
+ continue
+ }
+ label := ss[0]
+
+ // Extended precision counters are uint64 values.
+ if label == fieldXpc {
+ us, err := util.ParseUint64s(ss[1:])
+ if err != nil {
+ return nil, err
+ }
+
+ xfss.ExtendedPrecision, err = extendedPrecisionStats(us)
+ if err != nil {
+ return nil, err
+ }
+
+ continue
+ }
+
+ // All other counters are uint32 values.
+ us, err := util.ParseUint32s(ss[1:])
+ if err != nil {
+ return nil, err
+ }
+
+ switch label {
+ case fieldExtentAlloc:
+ xfss.ExtentAllocation, err = extentAllocationStats(us)
+ case fieldAbt:
+ xfss.AllocationBTree, err = btreeStats(us)
+ case fieldBlkMap:
+ xfss.BlockMapping, err = blockMappingStats(us)
+ case fieldBmbt:
+ xfss.BlockMapBTree, err = btreeStats(us)
+ case fieldDir:
+ xfss.DirectoryOperation, err = directoryOperationStats(us)
+ case fieldTrans:
+ xfss.Transaction, err = transactionStats(us)
+ case fieldIg:
+ xfss.InodeOperation, err = inodeOperationStats(us)
+ case fieldLog:
+ xfss.LogOperation, err = logOperationStats(us)
+ case fieldRw:
+ xfss.ReadWrite, err = readWriteStats(us)
+ case fieldAttr:
+ xfss.AttributeOperation, err = attributeOperationStats(us)
+ case fieldIcluster:
+ xfss.InodeClustering, err = inodeClusteringStats(us)
+ case fieldVnodes:
+ xfss.Vnode, err = vnodeStats(us)
+ case fieldBuf:
+ xfss.Buffer, err = bufferStats(us)
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &xfss, s.Err()
+}
+
+// extentAllocationStats builds an ExtentAllocationStats from a slice of uint32s.
+func extentAllocationStats(us []uint32) (ExtentAllocationStats, error) {
+ if l := len(us); l != 4 {
+ return ExtentAllocationStats{}, fmt.Errorf("incorrect number of values for XFS extent allocation stats: %d", l)
+ }
+
+ return ExtentAllocationStats{
+ ExtentsAllocated: us[0],
+ BlocksAllocated: us[1],
+ ExtentsFreed: us[2],
+ BlocksFreed: us[3],
+ }, nil
+}
+
+// btreeStats builds a BTreeStats from a slice of uint32s.
+func btreeStats(us []uint32) (BTreeStats, error) {
+ if l := len(us); l != 4 {
+ return BTreeStats{}, fmt.Errorf("incorrect number of values for XFS btree stats: %d", l)
+ }
+
+ return BTreeStats{
+ Lookups: us[0],
+ Compares: us[1],
+ RecordsInserted: us[2],
+ RecordsDeleted: us[3],
+ }, nil
+}
+
+// BlockMappingStat builds a BlockMappingStats from a slice of uint32s.
+func blockMappingStats(us []uint32) (BlockMappingStats, error) {
+ if l := len(us); l != 7 {
+ return BlockMappingStats{}, fmt.Errorf("incorrect number of values for XFS block mapping stats: %d", l)
+ }
+
+ return BlockMappingStats{
+ Reads: us[0],
+ Writes: us[1],
+ Unmaps: us[2],
+ ExtentListInsertions: us[3],
+ ExtentListDeletions: us[4],
+ ExtentListLookups: us[5],
+ ExtentListCompares: us[6],
+ }, nil
+}
+
+// DirectoryOperationStats builds a DirectoryOperationStats from a slice of uint32s.
+func directoryOperationStats(us []uint32) (DirectoryOperationStats, error) {
+ if l := len(us); l != 4 {
+ return DirectoryOperationStats{}, fmt.Errorf("incorrect number of values for XFS directory operation stats: %d", l)
+ }
+
+ return DirectoryOperationStats{
+ Lookups: us[0],
+ Creates: us[1],
+ Removes: us[2],
+ Getdents: us[3],
+ }, nil
+}
+
+// TransactionStats builds a TransactionStats from a slice of uint32s.
+func transactionStats(us []uint32) (TransactionStats, error) {
+ if l := len(us); l != 3 {
+ return TransactionStats{}, fmt.Errorf("incorrect number of values for XFS transaction stats: %d", l)
+ }
+
+ return TransactionStats{
+ Sync: us[0],
+ Async: us[1],
+ Empty: us[2],
+ }, nil
+}
+
+// InodeOperationStats builds an InodeOperationStats from a slice of uint32s.
+func inodeOperationStats(us []uint32) (InodeOperationStats, error) {
+ if l := len(us); l != 7 {
+ return InodeOperationStats{}, fmt.Errorf("incorrect number of values for XFS inode operation stats: %d", l)
+ }
+
+ return InodeOperationStats{
+ Attempts: us[0],
+ Found: us[1],
+ Recycle: us[2],
+ Missed: us[3],
+ Duplicate: us[4],
+ Reclaims: us[5],
+ AttributeChange: us[6],
+ }, nil
+}
+
+// LogOperationStats builds a LogOperationStats from a slice of uint32s.
+func logOperationStats(us []uint32) (LogOperationStats, error) {
+ if l := len(us); l != 5 {
+ return LogOperationStats{}, fmt.Errorf("incorrect number of values for XFS log operation stats: %d", l)
+ }
+
+ return LogOperationStats{
+ Writes: us[0],
+ Blocks: us[1],
+ NoInternalBuffers: us[2],
+ Force: us[3],
+ ForceSleep: us[4],
+ }, nil
+}
+
+// ReadWriteStats builds a ReadWriteStats from a slice of uint32s.
+func readWriteStats(us []uint32) (ReadWriteStats, error) {
+ if l := len(us); l != 2 {
+ return ReadWriteStats{}, fmt.Errorf("incorrect number of values for XFS read write stats: %d", l)
+ }
+
+ return ReadWriteStats{
+ Read: us[0],
+ Write: us[1],
+ }, nil
+}
+
+// AttributeOperationStats builds an AttributeOperationStats from a slice of uint32s.
+func attributeOperationStats(us []uint32) (AttributeOperationStats, error) {
+ if l := len(us); l != 4 {
+ return AttributeOperationStats{}, fmt.Errorf("incorrect number of values for XFS attribute operation stats: %d", l)
+ }
+
+ return AttributeOperationStats{
+ Get: us[0],
+ Set: us[1],
+ Remove: us[2],
+ List: us[3],
+ }, nil
+}
+
+// InodeClusteringStats builds an InodeClusteringStats from a slice of uint32s.
+func inodeClusteringStats(us []uint32) (InodeClusteringStats, error) {
+ if l := len(us); l != 3 {
+ return InodeClusteringStats{}, fmt.Errorf("incorrect number of values for XFS inode clustering stats: %d", l)
+ }
+
+ return InodeClusteringStats{
+ Iflush: us[0],
+ Flush: us[1],
+ FlushInode: us[2],
+ }, nil
+}
+
+// VnodeStats builds a VnodeStats from a slice of uint32s.
+func vnodeStats(us []uint32) (VnodeStats, error) {
+ // The attribute "Free" appears to not be available on older XFS
+ // stats versions. Therefore, 7 or 8 elements may appear in
+ // this slice.
+ l := len(us)
+ if l != 7 && l != 8 {
+ return VnodeStats{}, fmt.Errorf("incorrect number of values for XFS vnode stats: %d", l)
+ }
+
+ s := VnodeStats{
+ Active: us[0],
+ Allocate: us[1],
+ Get: us[2],
+ Hold: us[3],
+ Release: us[4],
+ Reclaim: us[5],
+ Remove: us[6],
+ }
+
+ // Skip adding free, unless it is present. The zero value will
+ // be used in place of an actual count.
+ if l == 7 {
+ return s, nil
+ }
+
+ s.Free = us[7]
+ return s, nil
+}
+
+// BufferStats builds a BufferStats from a slice of uint32s.
+func bufferStats(us []uint32) (BufferStats, error) {
+ if l := len(us); l != 9 {
+ return BufferStats{}, fmt.Errorf("incorrect number of values for XFS buffer stats: %d", l)
+ }
+
+ return BufferStats{
+ Get: us[0],
+ Create: us[1],
+ GetLocked: us[2],
+ GetLockedWaited: us[3],
+ BusyLocked: us[4],
+ MissLocked: us[5],
+ PageRetries: us[6],
+ PageFound: us[7],
+ GetRead: us[8],
+ }, nil
+}
+
+// ExtendedPrecisionStats builds an ExtendedPrecisionStats from a slice of uint32s.
+func extendedPrecisionStats(us []uint64) (ExtendedPrecisionStats, error) {
+ if l := len(us); l != 3 {
+ return ExtendedPrecisionStats{}, fmt.Errorf("incorrect number of values for XFS extended precision stats: %d", l)
+ }
+
+ return ExtendedPrecisionStats{
+ FlushBytes: us[0],
+ WriteBytes: us[1],
+ ReadBytes: us[2],
+ }, nil
+}
diff --git a/vendor/github.com/prometheus/procfs/xfs/xfs.go b/vendor/github.com/prometheus/procfs/xfs/xfs.go
new file mode 100644
index 00000000..d86794b7
--- /dev/null
+++ b/vendor/github.com/prometheus/procfs/xfs/xfs.go
@@ -0,0 +1,163 @@
+// Copyright 2017 The Prometheus Authors
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package xfs provides access to statistics exposed by the XFS filesystem.
+package xfs
+
+// Stats contains XFS filesystem runtime statistics, parsed from
+// /proc/fs/xfs/stat.
+//
+// The names and meanings of each statistic were taken from
+// http://xfs.org/index.php/Runtime_Stats and xfs_stats.h in the Linux
+// kernel source. Most counters are uint32s (same data types used in
+// xfs_stats.h), but some of the "extended precision stats" are uint64s.
+type Stats struct {
+ // The name of the filesystem used to source these statistics.
+ // If empty, this indicates aggregated statistics for all XFS
+ // filesystems on the host.
+ Name string
+
+ ExtentAllocation ExtentAllocationStats
+ AllocationBTree BTreeStats
+ BlockMapping BlockMappingStats
+ BlockMapBTree BTreeStats
+ DirectoryOperation DirectoryOperationStats
+ Transaction TransactionStats
+ InodeOperation InodeOperationStats
+ LogOperation LogOperationStats
+ ReadWrite ReadWriteStats
+ AttributeOperation AttributeOperationStats
+ InodeClustering InodeClusteringStats
+ Vnode VnodeStats
+ Buffer BufferStats
+ ExtendedPrecision ExtendedPrecisionStats
+}
+
+// ExtentAllocationStats contains statistics regarding XFS extent allocations.
+type ExtentAllocationStats struct {
+ ExtentsAllocated uint32
+ BlocksAllocated uint32
+ ExtentsFreed uint32
+ BlocksFreed uint32
+}
+
+// BTreeStats contains statistics regarding an XFS internal B-tree.
+type BTreeStats struct {
+ Lookups uint32
+ Compares uint32
+ RecordsInserted uint32
+ RecordsDeleted uint32
+}
+
+// BlockMappingStats contains statistics regarding XFS block maps.
+type BlockMappingStats struct {
+ Reads uint32
+ Writes uint32
+ Unmaps uint32
+ ExtentListInsertions uint32
+ ExtentListDeletions uint32
+ ExtentListLookups uint32
+ ExtentListCompares uint32
+}
+
+// DirectoryOperationStats contains statistics regarding XFS directory entries.
+type DirectoryOperationStats struct {
+ Lookups uint32
+ Creates uint32
+ Removes uint32
+ Getdents uint32
+}
+
+// TransactionStats contains statistics regarding XFS metadata transactions.
+type TransactionStats struct {
+ Sync uint32
+ Async uint32
+ Empty uint32
+}
+
+// InodeOperationStats contains statistics regarding XFS inode operations.
+type InodeOperationStats struct {
+ Attempts uint32
+ Found uint32
+ Recycle uint32
+ Missed uint32
+ Duplicate uint32
+ Reclaims uint32
+ AttributeChange uint32
+}
+
+// LogOperationStats contains statistics regarding the XFS log buffer.
+type LogOperationStats struct {
+ Writes uint32
+ Blocks uint32
+ NoInternalBuffers uint32
+ Force uint32
+ ForceSleep uint32
+}
+
+// ReadWriteStats contains statistics regarding the number of read and write
+// system calls for XFS filesystems.
+type ReadWriteStats struct {
+ Read uint32
+ Write uint32
+}
+
+// AttributeOperationStats contains statistics regarding manipulation of
+// XFS extended file attributes.
+type AttributeOperationStats struct {
+ Get uint32
+ Set uint32
+ Remove uint32
+ List uint32
+}
+
+// InodeClusteringStats contains statistics regarding XFS inode clustering
+// operations.
+type InodeClusteringStats struct {
+ Iflush uint32
+ Flush uint32
+ FlushInode uint32
+}
+
+// VnodeStats contains statistics regarding XFS vnode operations.
+type VnodeStats struct {
+ Active uint32
+ Allocate uint32
+ Get uint32
+ Hold uint32
+ Release uint32
+ Reclaim uint32
+ Remove uint32
+ Free uint32
+}
+
+// BufferStats contains statistics regarding XFS read/write I/O buffers.
+type BufferStats struct {
+ Get uint32
+ Create uint32
+ GetLocked uint32
+ GetLockedWaited uint32
+ BusyLocked uint32
+ MissLocked uint32
+ PageRetries uint32
+ PageFound uint32
+ GetRead uint32
+}
+
+// ExtendedPrecisionStats contains high precision counters used to track the
+// total number of bytes read, written, or flushed, during XFS operations.
+type ExtendedPrecisionStats struct {
+ FlushBytes uint64
+ WriteBytes uint64
+ ReadBytes uint64
+}
diff --git a/vendor/github.com/ugorji/go/LICENSE b/vendor/github.com/ugorji/go/LICENSE
new file mode 100644
index 00000000..95a0f054
--- /dev/null
+++ b/vendor/github.com/ugorji/go/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2012-2015 Ugorji Nwoke.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/ugorji/go/codec/0doc.go b/vendor/github.com/ugorji/go/codec/0doc.go
new file mode 100644
index 00000000..b61a8180
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/0doc.go
@@ -0,0 +1,264 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+/*
+Package codec provides a
+High Performance, Feature-Rich Idiomatic Go 1.4+ codec/encoding library
+for binc, msgpack, cbor, json.
+
+Supported Serialization formats are:
+
+ - msgpack: https://github.com/msgpack/msgpack
+ - binc: http://github.com/ugorji/binc
+ - cbor: http://cbor.io http://tools.ietf.org/html/rfc7049
+ - json: http://json.org http://tools.ietf.org/html/rfc7159
+ - simple:
+
+To install:
+
+ go get github.com/ugorji/go/codec
+
+This package will carefully use 'unsafe' for performance reasons in specific places.
+You can build without unsafe use by passing the safe or appengine tag
+i.e. 'go install -tags=safe ...'. Note that unsafe is only supported for the last 3
+go sdk versions e.g. current go release is go 1.9, so we support unsafe use only from
+go 1.7+ . This is because supporting unsafe requires knowledge of implementation details.
+
+For detailed usage information, read the primer at http://ugorji.net/blog/go-codec-primer .
+
+The idiomatic Go support is as seen in other encoding packages in
+the standard library (ie json, xml, gob, etc).
+
+Rich Feature Set includes:
+
+ - Simple but extremely powerful and feature-rich API
+ - Support for go1.4 and above, while selectively using newer APIs for later releases
+ - Excellent code coverage ( > 90% )
+ - Very High Performance.
+ Our extensive benchmarks show us outperforming Gob, Json, Bson, etc by 2-4X.
+ - Careful selected use of 'unsafe' for targeted performance gains.
+ 100% mode exists where 'unsafe' is not used at all.
+ - Lock-free (sans mutex) concurrency for scaling to 100's of cores
+ - Coerce types where appropriate
+ e.g. decode an int in the stream into a float, decode numbers from formatted strings, etc
+ - Corner Cases:
+ Overflows, nil maps/slices, nil values in streams are handled correctly
+ - Standard field renaming via tags
+ - Support for omitting empty fields during an encoding
+ - Encoding from any value and decoding into pointer to any value
+ (struct, slice, map, primitives, pointers, interface{}, etc)
+ - Extensions to support efficient encoding/decoding of any named types
+ - Support encoding.(Binary|Text)(M|Unm)arshaler interfaces
+ - Support IsZero() bool to determine if a value is a zero value.
+ Analogous to time.Time.IsZero() bool.
+ - Decoding without a schema (into a interface{}).
+ Includes Options to configure what specific map or slice type to use
+ when decoding an encoded list or map into a nil interface{}
+ - Mapping a non-interface type to an interface, so we can decode appropriately
+ into any interface type with a correctly configured non-interface value.
+ - Encode a struct as an array, and decode struct from an array in the data stream
+ - Option to encode struct keys as numbers (instead of strings)
+ (to support structured streams with fields encoded as numeric codes)
+ - Comprehensive support for anonymous fields
+ - Fast (no-reflection) encoding/decoding of common maps and slices
+ - Code-generation for faster performance.
+ - Support binary (e.g. messagepack, cbor) and text (e.g. json) formats
+ - Support indefinite-length formats to enable true streaming
+ (for formats which support it e.g. json, cbor)
+ - Support canonical encoding, where a value is ALWAYS encoded as same sequence of bytes.
+ This mostly applies to maps, where iteration order is non-deterministic.
+ - NIL in data stream decoded as zero value
+ - Never silently skip data when decoding.
+ User decides whether to return an error or silently skip data when keys or indexes
+ in the data stream do not map to fields in the struct.
+ - Detect and error when encoding a cyclic reference (instead of stack overflow shutdown)
+ - Encode/Decode from/to chan types (for iterative streaming support)
+ - Drop-in replacement for encoding/json. `json:` key in struct tag supported.
+ - Provides a RPC Server and Client Codec for net/rpc communication protocol.
+ - Handle unique idiosyncrasies of codecs e.g.
+ - For messagepack, configure how ambiguities in handling raw bytes are resolved
+ - For messagepack, provide rpc server/client codec to support
+ msgpack-rpc protocol defined at:
+ https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
+
+Extension Support
+
+Users can register a function to handle the encoding or decoding of
+their custom types.
+
+There are no restrictions on what the custom type can be. Some examples:
+
+ type BisSet []int
+ type BitSet64 uint64
+ type UUID string
+ type MyStructWithUnexportedFields struct { a int; b bool; c []int; }
+ type GifImage struct { ... }
+
+As an illustration, MyStructWithUnexportedFields would normally be
+encoded as an empty map because it has no exported fields, while UUID
+would be encoded as a string. However, with extension support, you can
+encode any of these however you like.
+
+Custom Encoding and Decoding
+
+This package maintains symmetry in the encoding and decoding halfs.
+We determine how to encode or decode by walking this decision tree
+
+ - is type a codec.Selfer?
+ - is there an extension registered for the type?
+ - is format binary, and is type a encoding.BinaryMarshaler and BinaryUnmarshaler?
+ - is format specifically json, and is type a encoding/json.Marshaler and Unmarshaler?
+ - is format text-based, and type an encoding.TextMarshaler?
+ - else we use a pair of functions based on the "kind" of the type e.g. map, slice, int64, etc
+
+This symmetry is important to reduce chances of issues happening because the
+encoding and decoding sides are out of sync e.g. decoded via very specific
+encoding.TextUnmarshaler but encoded via kind-specific generalized mode.
+
+Consequently, if a type only defines one-half of the symmetry
+(e.g. it implements UnmarshalJSON() but not MarshalJSON() ),
+then that type doesn't satisfy the check and we will continue walking down the
+decision tree.
+
+RPC
+
+RPC Client and Server Codecs are implemented, so the codecs can be used
+with the standard net/rpc package.
+
+Usage
+
+The Handle is SAFE for concurrent READ, but NOT SAFE for concurrent modification.
+
+The Encoder and Decoder are NOT safe for concurrent use.
+
+Consequently, the usage model is basically:
+
+ - Create and initialize the Handle before any use.
+ Once created, DO NOT modify it.
+ - Multiple Encoders or Decoders can now use the Handle concurrently.
+ They only read information off the Handle (never write).
+ - However, each Encoder or Decoder MUST not be used concurrently
+ - To re-use an Encoder/Decoder, call Reset(...) on it first.
+ This allows you use state maintained on the Encoder/Decoder.
+
+Sample usage model:
+
+ // create and configure Handle
+ var (
+ bh codec.BincHandle
+ mh codec.MsgpackHandle
+ ch codec.CborHandle
+ )
+
+ mh.MapType = reflect.TypeOf(map[string]interface{}(nil))
+
+ // configure extensions
+ // e.g. for msgpack, define functions and enable Time support for tag 1
+ // mh.SetExt(reflect.TypeOf(time.Time{}), 1, myExt)
+
+ // create and use decoder/encoder
+ var (
+ r io.Reader
+ w io.Writer
+ b []byte
+ h = &bh // or mh to use msgpack
+ )
+
+ dec = codec.NewDecoder(r, h)
+ dec = codec.NewDecoderBytes(b, h)
+ err = dec.Decode(&v)
+
+ enc = codec.NewEncoder(w, h)
+ enc = codec.NewEncoderBytes(&b, h)
+ err = enc.Encode(v)
+
+ //RPC Server
+ go func() {
+ for {
+ conn, err := listener.Accept()
+ rpcCodec := codec.GoRpc.ServerCodec(conn, h)
+ //OR rpcCodec := codec.MsgpackSpecRpc.ServerCodec(conn, h)
+ rpc.ServeCodec(rpcCodec)
+ }
+ }()
+
+ //RPC Communication (client side)
+ conn, err = net.Dial("tcp", "localhost:5555")
+ rpcCodec := codec.GoRpc.ClientCodec(conn, h)
+ //OR rpcCodec := codec.MsgpackSpecRpc.ClientCodec(conn, h)
+ client := rpc.NewClientWithCodec(rpcCodec)
+
+Running Tests
+
+To run tests, use the following:
+
+ go test
+
+To run the full suite of tests, use the following:
+
+ go test -tags alltests -run Suite
+
+You can run the tag 'safe' to run tests or build in safe mode. e.g.
+
+ go test -tags safe -run Json
+ go test -tags "alltests safe" -run Suite
+
+Running Benchmarks
+
+Please see http://github.com/ugorji/go-codec-bench .
+
+Caveats
+
+Struct fields matching the following are ignored during encoding and decoding
+ - struct tag value set to -
+ - func, complex numbers, unsafe pointers
+ - unexported and not embedded
+ - unexported and embedded and not struct kind
+ - unexported and embedded pointers (from go1.10)
+
+Every other field in a struct will be encoded/decoded.
+
+Embedded fields are encoded as if they exist in the top-level struct,
+with some caveats. See Encode documentation.
+
+*/
+package codec
+
+// TODO:
+// - For Go 1.11, when mid-stack inlining is enabled,
+// we should use committed functions for writeXXX and readXXX calls.
+// This involves uncommenting the methods for decReaderSwitch and encWriterSwitch
+// and using those (decReaderSwitch and encWriterSwitch) in all handles
+// instead of encWriter and decReader.
+// The benefit is that, for the (En|De)coder over []byte, the encWriter/decReader
+// will be inlined, giving a performance bump for that typical case.
+// However, it will only be inlined if mid-stack inlining is enabled,
+// as we call panic to raise errors, and panic currently prevents inlining.
+//
+// PUNTED:
+// - To make Handle comparable, make extHandle in BasicHandle a non-embedded pointer,
+// and use overlay methods on *BasicHandle to call through to extHandle after initializing
+// the "xh *extHandle" to point to a real slice.
+//
+// BEFORE EACH RELEASE:
+// - Look through and fix padding for each type, to eliminate false sharing
+// - critical shared objects that are read many times
+// TypeInfos
+// - pooled objects:
+// decNaked, decNakedContainers, codecFner, typeInfoLoadArray,
+// - small objects allocated independently, that we read/use much across threads:
+// codecFn, typeInfo
+// - Objects allocated independently and used a lot
+// Decoder, Encoder,
+// xxxHandle, xxxEncDriver, xxxDecDriver (xxx = json, msgpack, cbor, binc, simple)
+// - In all above, arrange values modified together to be close to each other.
+//
+// For all of these, either ensure that they occupy full cache lines,
+// or ensure that the things just past the cache line boundary are hardly read/written
+// e.g. JsonHandle.RawBytesExt - which is copied into json(En|De)cDriver at init
+//
+// Occupying full cache lines means they occupy 8*N words (where N is an integer).
+// Check this out by running: ./run.sh -z
+// - look at those tagged ****, meaning they are not occupying full cache lines
+// - look at those tagged <<<<, meaning they are larger than 32 words (something to watch)
+// - Run "golint -min_confidence 0.81"
diff --git a/vendor/github.com/ugorji/go/codec/binc.go b/vendor/github.com/ugorji/go/codec/binc.go
new file mode 100644
index 00000000..a3c96fe7
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/binc.go
@@ -0,0 +1,1168 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "math"
+ "reflect"
+ "time"
+)
+
+const bincDoPrune = true // No longer needed. Needed before as C lib did not support pruning.
+
+// vd as low 4 bits (there are 16 slots)
+const (
+ bincVdSpecial byte = iota
+ bincVdPosInt
+ bincVdNegInt
+ bincVdFloat
+
+ bincVdString
+ bincVdByteArray
+ bincVdArray
+ bincVdMap
+
+ bincVdTimestamp
+ bincVdSmallInt
+ bincVdUnicodeOther
+ bincVdSymbol
+
+ bincVdDecimal
+ _ // open slot
+ _ // open slot
+ bincVdCustomExt = 0x0f
+)
+
+const (
+ bincSpNil byte = iota
+ bincSpFalse
+ bincSpTrue
+ bincSpNan
+ bincSpPosInf
+ bincSpNegInf
+ bincSpZeroFloat
+ bincSpZero
+ bincSpNegOne
+)
+
+const (
+ bincFlBin16 byte = iota
+ bincFlBin32
+ _ // bincFlBin32e
+ bincFlBin64
+ _ // bincFlBin64e
+ // others not currently supported
+)
+
+func bincdesc(vd, vs byte) string {
+ switch vd {
+ case bincVdSpecial:
+ switch vs {
+ case bincSpNil:
+ return "nil"
+ case bincSpFalse:
+ return "false"
+ case bincSpTrue:
+ return "true"
+ case bincSpNan, bincSpPosInf, bincSpNegInf, bincSpZeroFloat:
+ return "float"
+ case bincSpZero:
+ return "uint"
+ case bincSpNegOne:
+ return "int"
+ default:
+ return "unknown"
+ }
+ case bincVdSmallInt, bincVdPosInt:
+ return "uint"
+ case bincVdNegInt:
+ return "int"
+ case bincVdFloat:
+ return "float"
+ case bincVdSymbol:
+ return "string"
+ case bincVdString:
+ return "string"
+ case bincVdByteArray:
+ return "bytes"
+ case bincVdTimestamp:
+ return "time"
+ case bincVdCustomExt:
+ return "ext"
+ case bincVdArray:
+ return "array"
+ case bincVdMap:
+ return "map"
+ default:
+ return "unknown"
+ }
+}
+
+type bincEncDriver struct {
+ e *Encoder
+ h *BincHandle
+ w encWriter
+ m map[string]uint16 // symbols
+ b [16]byte // scratch, used for encoding numbers - bigendian style
+ s uint16 // symbols sequencer
+ // c containerState
+ encDriverTrackContainerWriter
+ noBuiltInTypes
+ // encNoSeparator
+}
+
+func (e *bincEncDriver) EncodeNil() {
+ e.w.writen1(bincVdSpecial<<4 | bincSpNil)
+}
+
+func (e *bincEncDriver) EncodeTime(t time.Time) {
+ if t.IsZero() {
+ e.EncodeNil()
+ } else {
+ bs := bincEncodeTime(t)
+ e.w.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
+ e.w.writeb(bs)
+ }
+}
+
+func (e *bincEncDriver) EncodeBool(b bool) {
+ if b {
+ e.w.writen1(bincVdSpecial<<4 | bincSpTrue)
+ } else {
+ e.w.writen1(bincVdSpecial<<4 | bincSpFalse)
+ }
+}
+
+func (e *bincEncDriver) EncodeFloat32(f float32) {
+ if f == 0 {
+ e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
+ return
+ }
+ e.w.writen1(bincVdFloat<<4 | bincFlBin32)
+ bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
+}
+
+func (e *bincEncDriver) EncodeFloat64(f float64) {
+ if f == 0 {
+ e.w.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
+ return
+ }
+ bigen.PutUint64(e.b[:8], math.Float64bits(f))
+ if bincDoPrune {
+ i := 7
+ for ; i >= 0 && (e.b[i] == 0); i-- {
+ }
+ i++
+ if i <= 6 {
+ e.w.writen1(bincVdFloat<<4 | 0x8 | bincFlBin64)
+ e.w.writen1(byte(i))
+ e.w.writeb(e.b[:i])
+ return
+ }
+ }
+ e.w.writen1(bincVdFloat<<4 | bincFlBin64)
+ e.w.writeb(e.b[:8])
+}
+
+func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8) {
+ if lim == 4 {
+ bigen.PutUint32(e.b[:lim], uint32(v))
+ } else {
+ bigen.PutUint64(e.b[:lim], v)
+ }
+ if bincDoPrune {
+ i := pruneSignExt(e.b[:lim], pos)
+ e.w.writen1(bd | lim - 1 - byte(i))
+ e.w.writeb(e.b[i:lim])
+ } else {
+ e.w.writen1(bd | lim - 1)
+ e.w.writeb(e.b[:lim])
+ }
+}
+
+func (e *bincEncDriver) EncodeInt(v int64) {
+ const nbd byte = bincVdNegInt << 4
+ if v >= 0 {
+ e.encUint(bincVdPosInt<<4, true, uint64(v))
+ } else if v == -1 {
+ e.w.writen1(bincVdSpecial<<4 | bincSpNegOne)
+ } else {
+ e.encUint(bincVdNegInt<<4, false, uint64(-v))
+ }
+}
+
+func (e *bincEncDriver) EncodeUint(v uint64) {
+ e.encUint(bincVdPosInt<<4, true, v)
+}
+
+func (e *bincEncDriver) encUint(bd byte, pos bool, v uint64) {
+ if v == 0 {
+ e.w.writen1(bincVdSpecial<<4 | bincSpZero)
+ } else if pos && v >= 1 && v <= 16 {
+ e.w.writen1(bincVdSmallInt<<4 | byte(v-1))
+ } else if v <= math.MaxUint8 {
+ e.w.writen2(bd|0x0, byte(v))
+ } else if v <= math.MaxUint16 {
+ e.w.writen1(bd | 0x01)
+ bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v))
+ } else if v <= math.MaxUint32 {
+ e.encIntegerPrune(bd, pos, v, 4)
+ } else {
+ e.encIntegerPrune(bd, pos, v, 8)
+ }
+}
+
+func (e *bincEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, _ *Encoder) {
+ bs := ext.WriteExt(rv)
+ if bs == nil {
+ e.EncodeNil()
+ return
+ }
+ e.encodeExtPreamble(uint8(xtag), len(bs))
+ e.w.writeb(bs)
+}
+
+func (e *bincEncDriver) EncodeRawExt(re *RawExt, _ *Encoder) {
+ e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
+ e.w.writeb(re.Data)
+}
+
+func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
+ e.encLen(bincVdCustomExt<<4, uint64(length))
+ e.w.writen1(xtag)
+}
+
+func (e *bincEncDriver) WriteArrayStart(length int) {
+ e.encLen(bincVdArray<<4, uint64(length))
+ e.c = containerArrayStart
+}
+
+func (e *bincEncDriver) WriteMapStart(length int) {
+ e.encLen(bincVdMap<<4, uint64(length))
+ e.c = containerMapStart
+}
+
+func (e *bincEncDriver) EncodeString(c charEncoding, v string) {
+ if e.c == containerMapKey && c == cUTF8 && (e.h.AsSymbols == 0 || e.h.AsSymbols == 1) {
+ e.EncodeSymbol(v)
+ return
+ }
+ l := uint64(len(v))
+ e.encBytesLen(c, l)
+ if l > 0 {
+ e.w.writestr(v)
+ }
+}
+
+func (e *bincEncDriver) EncodeSymbol(v string) {
+ // if WriteSymbolsNoRefs {
+ // e.encodeString(cUTF8, v)
+ // return
+ // }
+
+ //symbols only offer benefit when string length > 1.
+ //This is because strings with length 1 take only 2 bytes to store
+ //(bd with embedded length, and single byte for string val).
+
+ l := len(v)
+ if l == 0 {
+ e.encBytesLen(cUTF8, 0)
+ return
+ } else if l == 1 {
+ e.encBytesLen(cUTF8, 1)
+ e.w.writen1(v[0])
+ return
+ }
+ if e.m == nil {
+ e.m = make(map[string]uint16, 16)
+ }
+ ui, ok := e.m[v]
+ if ok {
+ if ui <= math.MaxUint8 {
+ e.w.writen2(bincVdSymbol<<4, byte(ui))
+ } else {
+ e.w.writen1(bincVdSymbol<<4 | 0x8)
+ bigenHelper{e.b[:2], e.w}.writeUint16(ui)
+ }
+ } else {
+ e.s++
+ ui = e.s
+ //ui = uint16(atomic.AddUint32(&e.s, 1))
+ e.m[v] = ui
+ var lenprec uint8
+ if l <= math.MaxUint8 {
+ // lenprec = 0
+ } else if l <= math.MaxUint16 {
+ lenprec = 1
+ } else if int64(l) <= math.MaxUint32 {
+ lenprec = 2
+ } else {
+ lenprec = 3
+ }
+ if ui <= math.MaxUint8 {
+ e.w.writen2(bincVdSymbol<<4|0x0|0x4|lenprec, byte(ui))
+ } else {
+ e.w.writen1(bincVdSymbol<<4 | 0x8 | 0x4 | lenprec)
+ bigenHelper{e.b[:2], e.w}.writeUint16(ui)
+ }
+ if lenprec == 0 {
+ e.w.writen1(byte(l))
+ } else if lenprec == 1 {
+ bigenHelper{e.b[:2], e.w}.writeUint16(uint16(l))
+ } else if lenprec == 2 {
+ bigenHelper{e.b[:4], e.w}.writeUint32(uint32(l))
+ } else {
+ bigenHelper{e.b[:8], e.w}.writeUint64(uint64(l))
+ }
+ e.w.writestr(v)
+ }
+}
+
+func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+ if v == nil {
+ e.EncodeNil()
+ return
+ }
+ l := uint64(len(v))
+ e.encBytesLen(c, l)
+ if l > 0 {
+ e.w.writeb(v)
+ }
+}
+
+func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
+ //TODO: support bincUnicodeOther (for now, just use string or bytearray)
+ if c == cRAW {
+ e.encLen(bincVdByteArray<<4, length)
+ } else {
+ e.encLen(bincVdString<<4, length)
+ }
+}
+
+func (e *bincEncDriver) encLen(bd byte, l uint64) {
+ if l < 12 {
+ e.w.writen1(bd | uint8(l+4))
+ } else {
+ e.encLenNumber(bd, l)
+ }
+}
+
+func (e *bincEncDriver) encLenNumber(bd byte, v uint64) {
+ if v <= math.MaxUint8 {
+ e.w.writen2(bd, byte(v))
+ } else if v <= math.MaxUint16 {
+ e.w.writen1(bd | 0x01)
+ bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v))
+ } else if v <= math.MaxUint32 {
+ e.w.writen1(bd | 0x02)
+ bigenHelper{e.b[:4], e.w}.writeUint32(uint32(v))
+ } else {
+ e.w.writen1(bd | 0x03)
+ bigenHelper{e.b[:8], e.w}.writeUint64(uint64(v))
+ }
+}
+
+//------------------------------------
+
+type bincDecSymbol struct {
+ s string
+ b []byte
+ i uint16
+}
+
+type bincDecDriver struct {
+ decDriverNoopContainerReader
+ noBuiltInTypes
+
+ d *Decoder
+ h *BincHandle
+ r decReader
+ br bool // bytes reader
+ bdRead bool
+ bd byte
+ vd byte
+ vs byte
+ _ [3]byte // padding
+ // linear searching on this slice is ok,
+ // because we typically expect < 32 symbols in each stream.
+ s []bincDecSymbol
+
+ // noStreamingCodec
+ // decNoSeparator
+
+ b [8 * 8]byte // scratch
+}
+
+func (d *bincDecDriver) readNextBd() {
+ d.bd = d.r.readn1()
+ d.vd = d.bd >> 4
+ d.vs = d.bd & 0x0f
+ d.bdRead = true
+}
+
+func (d *bincDecDriver) uncacheRead() {
+ if d.bdRead {
+ d.r.unreadn1()
+ d.bdRead = false
+ }
+}
+
+func (d *bincDecDriver) ContainerType() (vt valueType) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.vd == bincVdSpecial && d.vs == bincSpNil {
+ return valueTypeNil
+ } else if d.vd == bincVdByteArray {
+ return valueTypeBytes
+ } else if d.vd == bincVdString {
+ return valueTypeString
+ } else if d.vd == bincVdArray {
+ return valueTypeArray
+ } else if d.vd == bincVdMap {
+ return valueTypeMap
+ }
+ // else {
+ // d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+ // }
+ return valueTypeUnset
+}
+
+func (d *bincDecDriver) TryDecodeAsNil() bool {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == bincVdSpecial<<4|bincSpNil {
+ d.bdRead = false
+ return true
+ }
+ return false
+}
+
+func (d *bincDecDriver) DecodeTime() (t time.Time) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == bincVdSpecial<<4|bincSpNil {
+ d.bdRead = false
+ return
+ }
+ if d.vd != bincVdTimestamp {
+ d.d.errorf("cannot decode time - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ t, err := bincDecodeTime(d.r.readx(int(d.vs)))
+ if err != nil {
+ panic(err)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
+ if vs&0x8 == 0 {
+ d.r.readb(d.b[0:defaultLen])
+ } else {
+ l := d.r.readn1()
+ if l > 8 {
+ d.d.errorf("cannot read float - at most 8 bytes used to represent float - received %v bytes", l)
+ return
+ }
+ for i := l; i < 8; i++ {
+ d.b[i] = 0
+ }
+ d.r.readb(d.b[0:l])
+ }
+}
+
+func (d *bincDecDriver) decFloat() (f float64) {
+ //if true { f = math.Float64frombits(bigen.Uint64(d.r.readx(8))); break; }
+ if x := d.vs & 0x7; x == bincFlBin32 {
+ d.decFloatPre(d.vs, 4)
+ f = float64(math.Float32frombits(bigen.Uint32(d.b[0:4])))
+ } else if x == bincFlBin64 {
+ d.decFloatPre(d.vs, 8)
+ f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
+ } else {
+ d.d.errorf("read float - only float32 and float64 are supported - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ return
+}
+
+func (d *bincDecDriver) decUint() (v uint64) {
+ // need to inline the code (interface conversion and type assertion expensive)
+ switch d.vs {
+ case 0:
+ v = uint64(d.r.readn1())
+ case 1:
+ d.r.readb(d.b[6:8])
+ v = uint64(bigen.Uint16(d.b[6:8]))
+ case 2:
+ d.b[4] = 0
+ d.r.readb(d.b[5:8])
+ v = uint64(bigen.Uint32(d.b[4:8]))
+ case 3:
+ d.r.readb(d.b[4:8])
+ v = uint64(bigen.Uint32(d.b[4:8]))
+ case 4, 5, 6:
+ lim := int(7 - d.vs)
+ d.r.readb(d.b[lim:8])
+ for i := 0; i < lim; i++ {
+ d.b[i] = 0
+ }
+ v = uint64(bigen.Uint64(d.b[:8]))
+ case 7:
+ d.r.readb(d.b[:8])
+ v = uint64(bigen.Uint64(d.b[:8]))
+ default:
+ d.d.errorf("unsigned integers with greater than 64 bits of precision not supported")
+ return
+ }
+ return
+}
+
+func (d *bincDecDriver) decCheckInteger() (ui uint64, neg bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ vd, vs := d.vd, d.vs
+ if vd == bincVdPosInt {
+ ui = d.decUint()
+ } else if vd == bincVdNegInt {
+ ui = d.decUint()
+ neg = true
+ } else if vd == bincVdSmallInt {
+ ui = uint64(d.vs) + 1
+ } else if vd == bincVdSpecial {
+ if vs == bincSpZero {
+ //i = 0
+ } else if vs == bincSpNegOne {
+ neg = true
+ ui = 1
+ } else {
+ d.d.errorf("integer decode fails - invalid special value from descriptor %x-%x/%s",
+ d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ } else {
+ d.d.errorf("integer can only be decoded from int/uint. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd)
+ return
+ }
+ return
+}
+
+func (d *bincDecDriver) DecodeInt64() (i int64) {
+ ui, neg := d.decCheckInteger()
+ i = chkOvf.SignedIntV(ui)
+ if neg {
+ i = -i
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) DecodeUint64() (ui uint64) {
+ ui, neg := d.decCheckInteger()
+ if neg {
+ d.d.errorf("assigning negative signed value to unsigned integer type")
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) DecodeFloat64() (f float64) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ vd, vs := d.vd, d.vs
+ if vd == bincVdSpecial {
+ d.bdRead = false
+ if vs == bincSpNan {
+ return math.NaN()
+ } else if vs == bincSpPosInf {
+ return math.Inf(1)
+ } else if vs == bincSpZeroFloat || vs == bincSpZero {
+ return
+ } else if vs == bincSpNegInf {
+ return math.Inf(-1)
+ } else {
+ d.d.errorf("float - invalid special value from descriptor %x-%x/%s",
+ d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ } else if vd == bincVdFloat {
+ f = d.decFloat()
+ } else {
+ f = float64(d.DecodeInt64())
+ }
+ d.bdRead = false
+ return
+}
+
+// bool can be decoded from bool only (single byte).
+func (d *bincDecDriver) DecodeBool() (b bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if bd := d.bd; bd == (bincVdSpecial | bincSpFalse) {
+ // b = false
+ } else if bd == (bincVdSpecial | bincSpTrue) {
+ b = true
+ } else {
+ d.d.errorf("bool - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) ReadMapStart() (length int) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.vd != bincVdMap {
+ d.d.errorf("map - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ length = d.decLen()
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) ReadArrayStart() (length int) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.vd != bincVdArray {
+ d.d.errorf("array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ length = d.decLen()
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) decLen() int {
+ if d.vs > 3 {
+ return int(d.vs - 4)
+ }
+ return int(d.decLenNumber())
+}
+
+func (d *bincDecDriver) decLenNumber() (v uint64) {
+ if x := d.vs; x == 0 {
+ v = uint64(d.r.readn1())
+ } else if x == 1 {
+ d.r.readb(d.b[6:8])
+ v = uint64(bigen.Uint16(d.b[6:8]))
+ } else if x == 2 {
+ d.r.readb(d.b[4:8])
+ v = uint64(bigen.Uint32(d.b[4:8]))
+ } else {
+ d.r.readb(d.b[:8])
+ v = bigen.Uint64(d.b[:8])
+ }
+ return
+}
+
+func (d *bincDecDriver) decStringAndBytes(bs []byte, withString, zerocopy bool) (
+ bs2 []byte, s string) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == bincVdSpecial<<4|bincSpNil {
+ d.bdRead = false
+ return
+ }
+ var slen = -1
+ // var ok bool
+ switch d.vd {
+ case bincVdString, bincVdByteArray:
+ slen = d.decLen()
+ if zerocopy {
+ if d.br {
+ bs2 = d.r.readx(slen)
+ } else if len(bs) == 0 {
+ bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, d.b[:])
+ } else {
+ bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
+ }
+ } else {
+ bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, bs)
+ }
+ if withString {
+ s = string(bs2)
+ }
+ case bincVdSymbol:
+ // zerocopy doesn't apply for symbols,
+ // as the values must be stored in a table for later use.
+ //
+ //from vs: extract numSymbolBytes, containsStringVal, strLenPrecision,
+ //extract symbol
+ //if containsStringVal, read it and put in map
+ //else look in map for string value
+ var symbol uint16
+ vs := d.vs
+ if vs&0x8 == 0 {
+ symbol = uint16(d.r.readn1())
+ } else {
+ symbol = uint16(bigen.Uint16(d.r.readx(2)))
+ }
+ if d.s == nil {
+ d.s = make([]bincDecSymbol, 0, 16)
+ }
+
+ if vs&0x4 == 0 {
+ for i := range d.s {
+ j := &d.s[i]
+ if j.i == symbol {
+ bs2 = j.b
+ if withString {
+ if j.s == "" && bs2 != nil {
+ j.s = string(bs2)
+ }
+ s = j.s
+ }
+ break
+ }
+ }
+ } else {
+ switch vs & 0x3 {
+ case 0:
+ slen = int(d.r.readn1())
+ case 1:
+ slen = int(bigen.Uint16(d.r.readx(2)))
+ case 2:
+ slen = int(bigen.Uint32(d.r.readx(4)))
+ case 3:
+ slen = int(bigen.Uint64(d.r.readx(8)))
+ }
+ // since using symbols, do not store any part of
+ // the parameter bs in the map, as it might be a shared buffer.
+ // bs2 = decByteSlice(d.r, slen, bs)
+ bs2 = decByteSlice(d.r, slen, d.d.h.MaxInitLen, nil)
+ if withString {
+ s = string(bs2)
+ }
+ d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
+ }
+ default:
+ d.d.errorf("string/bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) DecodeString() (s string) {
+ // DecodeBytes does not accommodate symbols, whose impl stores string version in map.
+ // Use decStringAndBytes directly.
+ // return string(d.DecodeBytes(d.b[:], true, true))
+ _, s = d.decStringAndBytes(d.b[:], true, true)
+ return
+}
+
+func (d *bincDecDriver) DecodeStringAsBytes() (s []byte) {
+ s, _ = d.decStringAndBytes(d.b[:], false, true)
+ return
+}
+
+func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == bincVdSpecial<<4|bincSpNil {
+ d.bdRead = false
+ return nil
+ }
+ // check if an "array" of uint8's (see ContainerType for how to infer if an array)
+ if d.vd == bincVdArray {
+ bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+ return
+ }
+ var clen int
+ if d.vd == bincVdString || d.vd == bincVdByteArray {
+ clen = d.decLen()
+ } else {
+ d.d.errorf("bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ d.bdRead = false
+ if zerocopy {
+ if d.br {
+ return d.r.readx(clen)
+ } else if len(bs) == 0 {
+ bs = d.b[:]
+ }
+ }
+ return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
+}
+
+func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
+ if xtag > 0xff {
+ d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
+ return
+ }
+ realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
+ realxtag = uint64(realxtag1)
+ if ext == nil {
+ re := rv.(*RawExt)
+ re.Tag = realxtag
+ re.Data = detachZeroCopyBytes(d.br, re.Data, xbs)
+ } else {
+ ext.ReadExt(rv, xbs)
+ }
+ return
+}
+
+func (d *bincDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.vd == bincVdCustomExt {
+ l := d.decLen()
+ xtag = d.r.readn1()
+ if verifyTag && xtag != tag {
+ d.d.errorf("wrong extension tag - got %b, expecting: %v", xtag, tag)
+ return
+ }
+ xbs = d.r.readx(l)
+ } else if d.vd == bincVdByteArray {
+ xbs = d.DecodeBytes(nil, true)
+ } else {
+ d.d.errorf("ext - expecting extensions or byte array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *bincDecDriver) DecodeNaked() {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+
+ n := d.d.n
+ var decodeFurther bool
+
+ switch d.vd {
+ case bincVdSpecial:
+ switch d.vs {
+ case bincSpNil:
+ n.v = valueTypeNil
+ case bincSpFalse:
+ n.v = valueTypeBool
+ n.b = false
+ case bincSpTrue:
+ n.v = valueTypeBool
+ n.b = true
+ case bincSpNan:
+ n.v = valueTypeFloat
+ n.f = math.NaN()
+ case bincSpPosInf:
+ n.v = valueTypeFloat
+ n.f = math.Inf(1)
+ case bincSpNegInf:
+ n.v = valueTypeFloat
+ n.f = math.Inf(-1)
+ case bincSpZeroFloat:
+ n.v = valueTypeFloat
+ n.f = float64(0)
+ case bincSpZero:
+ n.v = valueTypeUint
+ n.u = uint64(0) // int8(0)
+ case bincSpNegOne:
+ n.v = valueTypeInt
+ n.i = int64(-1) // int8(-1)
+ default:
+ d.d.errorf("cannot infer value - unrecognized special value from descriptor %x-%x/%s", d.vd, d.vs, bincdesc(d.vd, d.vs))
+ }
+ case bincVdSmallInt:
+ n.v = valueTypeUint
+ n.u = uint64(int8(d.vs)) + 1 // int8(d.vs) + 1
+ case bincVdPosInt:
+ n.v = valueTypeUint
+ n.u = d.decUint()
+ case bincVdNegInt:
+ n.v = valueTypeInt
+ n.i = -(int64(d.decUint()))
+ case bincVdFloat:
+ n.v = valueTypeFloat
+ n.f = d.decFloat()
+ case bincVdSymbol:
+ n.v = valueTypeSymbol
+ n.s = d.DecodeString()
+ case bincVdString:
+ n.v = valueTypeString
+ n.s = d.DecodeString()
+ case bincVdByteArray:
+ n.v = valueTypeBytes
+ n.l = d.DecodeBytes(nil, false)
+ case bincVdTimestamp:
+ n.v = valueTypeTime
+ tt, err := bincDecodeTime(d.r.readx(int(d.vs)))
+ if err != nil {
+ panic(err)
+ }
+ n.t = tt
+ case bincVdCustomExt:
+ n.v = valueTypeExt
+ l := d.decLen()
+ n.u = uint64(d.r.readn1())
+ n.l = d.r.readx(l)
+ case bincVdArray:
+ n.v = valueTypeArray
+ decodeFurther = true
+ case bincVdMap:
+ n.v = valueTypeMap
+ decodeFurther = true
+ default:
+ d.d.errorf("cannot infer value - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
+ }
+
+ if !decodeFurther {
+ d.bdRead = false
+ }
+ if n.v == valueTypeUint && d.h.SignedInteger {
+ n.v = valueTypeInt
+ n.i = int64(n.u)
+ }
+ return
+}
+
+//------------------------------------
+
+//BincHandle is a Handle for the Binc Schema-Free Encoding Format
+//defined at https://github.com/ugorji/binc .
+//
+//BincHandle currently supports all Binc features with the following EXCEPTIONS:
+// - only integers up to 64 bits of precision are supported.
+// big integers are unsupported.
+// - Only IEEE 754 binary32 and binary64 floats are supported (ie Go float32 and float64 types).
+// extended precision and decimal IEEE 754 floats are unsupported.
+// - Only UTF-8 strings supported.
+// Unicode_Other Binc types (UTF16, UTF32) are currently unsupported.
+//
+//Note that these EXCEPTIONS are temporary and full support is possible and may happen soon.
+type BincHandle struct {
+ BasicHandle
+ binaryEncodingType
+ noElemSeparators
+
+ // AsSymbols defines what should be encoded as symbols.
+ //
+ // Encoding as symbols can reduce the encoded size significantly.
+ //
+ // However, during decoding, each string to be encoded as a symbol must
+ // be checked to see if it has been seen before. Consequently, encoding time
+ // will increase if using symbols, because string comparisons has a clear cost.
+ //
+ // Values:
+ // - 0: default: library uses best judgement
+ // - 1: use symbols
+ // - 2: do not use symbols
+ AsSymbols uint8
+
+ // AsSymbols: may later on introduce more options ...
+ // - m: map keys
+ // - s: struct fields
+ // - n: none
+ // - a: all: same as m, s, ...
+
+ // _ [1]uint64 // padding
+}
+
+// Name returns the name of the handle: binc
+func (h *BincHandle) Name() string { return "binc" }
+
+// SetBytesExt sets an extension
+func (h *BincHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
+ return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
+}
+
+func (h *BincHandle) newEncDriver(e *Encoder) encDriver {
+ return &bincEncDriver{e: e, h: h, w: e.w}
+}
+
+func (h *BincHandle) newDecDriver(d *Decoder) decDriver {
+ return &bincDecDriver{d: d, h: h, r: d.r, br: d.bytes}
+}
+
+func (e *bincEncDriver) reset() {
+ e.w = e.e.w
+ e.s = 0
+ e.c = 0
+ e.m = nil
+}
+
+func (d *bincDecDriver) reset() {
+ d.r, d.br = d.d.r, d.d.bytes
+ d.s = nil
+ d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0
+}
+
+// var timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
+
+// EncodeTime encodes a time.Time as a []byte, including
+// information on the instant in time and UTC offset.
+//
+// Format Description
+//
+// A timestamp is composed of 3 components:
+//
+// - secs: signed integer representing seconds since unix epoch
+// - nsces: unsigned integer representing fractional seconds as a
+// nanosecond offset within secs, in the range 0 <= nsecs < 1e9
+// - tz: signed integer representing timezone offset in minutes east of UTC,
+// and a dst (daylight savings time) flag
+//
+// When encoding a timestamp, the first byte is the descriptor, which
+// defines which components are encoded and how many bytes are used to
+// encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it
+// is not encoded in the byte array explicitly*.
+//
+// Descriptor 8 bits are of the form `A B C DDD EE`:
+// A: Is secs component encoded? 1 = true
+// B: Is nsecs component encoded? 1 = true
+// C: Is tz component encoded? 1 = true
+// DDD: Number of extra bytes for secs (range 0-7).
+// If A = 1, secs encoded in DDD+1 bytes.
+// If A = 0, secs is not encoded, and is assumed to be 0.
+// If A = 1, then we need at least 1 byte to encode secs.
+// DDD says the number of extra bytes beyond that 1.
+// E.g. if DDD=0, then secs is represented in 1 byte.
+// if DDD=2, then secs is represented in 3 bytes.
+// EE: Number of extra bytes for nsecs (range 0-3).
+// If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above)
+//
+// Following the descriptor bytes, subsequent bytes are:
+//
+// secs component encoded in `DDD + 1` bytes (if A == 1)
+// nsecs component encoded in `EE + 1` bytes (if B == 1)
+// tz component encoded in 2 bytes (if C == 1)
+//
+// secs and nsecs components are integers encoded in a BigEndian
+// 2-complement encoding format.
+//
+// tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to
+// Least significant bit 0 are described below:
+//
+// Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes).
+// Bit 15 = have\_dst: set to 1 if we set the dst flag.
+// Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not.
+// Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format.
+//
+func bincEncodeTime(t time.Time) []byte {
+ //t := rv.Interface().(time.Time)
+ tsecs, tnsecs := t.Unix(), t.Nanosecond()
+ var (
+ bd byte
+ btmp [8]byte
+ bs [16]byte
+ i int = 1
+ )
+ l := t.Location()
+ if l == time.UTC {
+ l = nil
+ }
+ if tsecs != 0 {
+ bd = bd | 0x80
+ bigen.PutUint64(btmp[:], uint64(tsecs))
+ f := pruneSignExt(btmp[:], tsecs >= 0)
+ bd = bd | (byte(7-f) << 2)
+ copy(bs[i:], btmp[f:])
+ i = i + (8 - f)
+ }
+ if tnsecs != 0 {
+ bd = bd | 0x40
+ bigen.PutUint32(btmp[:4], uint32(tnsecs))
+ f := pruneSignExt(btmp[:4], true)
+ bd = bd | byte(3-f)
+ copy(bs[i:], btmp[f:4])
+ i = i + (4 - f)
+ }
+ if l != nil {
+ bd = bd | 0x20
+ // Note that Go Libs do not give access to dst flag.
+ _, zoneOffset := t.Zone()
+ //zoneName, zoneOffset := t.Zone()
+ zoneOffset /= 60
+ z := uint16(zoneOffset)
+ bigen.PutUint16(btmp[:2], z)
+ // clear dst flags
+ bs[i] = btmp[0] & 0x3f
+ bs[i+1] = btmp[1]
+ i = i + 2
+ }
+ bs[0] = bd
+ return bs[0:i]
+}
+
+// bincDecodeTime decodes a []byte into a time.Time.
+func bincDecodeTime(bs []byte) (tt time.Time, err error) {
+ bd := bs[0]
+ var (
+ tsec int64
+ tnsec uint32
+ tz uint16
+ i byte = 1
+ i2 byte
+ n byte
+ )
+ if bd&(1<<7) != 0 {
+ var btmp [8]byte
+ n = ((bd >> 2) & 0x7) + 1
+ i2 = i + n
+ copy(btmp[8-n:], bs[i:i2])
+ //if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it)
+ if bs[i]&(1<<7) != 0 {
+ copy(btmp[0:8-n], bsAll0xff)
+ //for j,k := byte(0), 8-n; j < k; j++ { btmp[j] = 0xff }
+ }
+ i = i2
+ tsec = int64(bigen.Uint64(btmp[:]))
+ }
+ if bd&(1<<6) != 0 {
+ var btmp [4]byte
+ n = (bd & 0x3) + 1
+ i2 = i + n
+ copy(btmp[4-n:], bs[i:i2])
+ i = i2
+ tnsec = bigen.Uint32(btmp[:])
+ }
+ if bd&(1<<5) == 0 {
+ tt = time.Unix(tsec, int64(tnsec)).UTC()
+ return
+ }
+ // In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name.
+ // However, we need name here, so it can be shown when time is printed.
+ // Zone name is in form: UTC-08:00.
+ // Note that Go Libs do not give access to dst flag, so we ignore dst bits
+
+ i2 = i + 2
+ tz = bigen.Uint16(bs[i:i2])
+ // i = i2
+ // sign extend sign bit into top 2 MSB (which were dst bits):
+ if tz&(1<<13) == 0 { // positive
+ tz = tz & 0x3fff //clear 2 MSBs: dst bits
+ } else { // negative
+ tz = tz | 0xc000 //set 2 MSBs: dst bits
+ }
+ tzint := int16(tz)
+ if tzint == 0 {
+ tt = time.Unix(tsec, int64(tnsec)).UTC()
+ } else {
+ // For Go Time, do not use a descriptive timezone.
+ // It's unnecessary, and makes it harder to do a reflect.DeepEqual.
+ // The Offset already tells what the offset should be, if not on UTC and unknown zone name.
+ // var zoneName = timeLocUTCName(tzint)
+ tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60))
+ }
+ return
+}
+
+var _ decDriver = (*bincDecDriver)(nil)
+var _ encDriver = (*bincEncDriver)(nil)
diff --git a/vendor/github.com/ugorji/go/codec/cbor.go b/vendor/github.com/ugorji/go/codec/cbor.go
new file mode 100644
index 00000000..7633c04a
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/cbor.go
@@ -0,0 +1,756 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "math"
+ "reflect"
+ "time"
+)
+
+const (
+ cborMajorUint byte = iota
+ cborMajorNegInt
+ cborMajorBytes
+ cborMajorText
+ cborMajorArray
+ cborMajorMap
+ cborMajorTag
+ cborMajorOther
+)
+
+const (
+ cborBdFalse byte = 0xf4 + iota
+ cborBdTrue
+ cborBdNil
+ cborBdUndefined
+ cborBdExt
+ cborBdFloat16
+ cborBdFloat32
+ cborBdFloat64
+)
+
+const (
+ cborBdIndefiniteBytes byte = 0x5f
+ cborBdIndefiniteString = 0x7f
+ cborBdIndefiniteArray = 0x9f
+ cborBdIndefiniteMap = 0xbf
+ cborBdBreak = 0xff
+)
+
+// These define some in-stream descriptors for
+// manual encoding e.g. when doing explicit indefinite-length
+const (
+ CborStreamBytes byte = 0x5f
+ CborStreamString = 0x7f
+ CborStreamArray = 0x9f
+ CborStreamMap = 0xbf
+ CborStreamBreak = 0xff
+)
+
+const (
+ cborBaseUint byte = 0x00
+ cborBaseNegInt = 0x20
+ cborBaseBytes = 0x40
+ cborBaseString = 0x60
+ cborBaseArray = 0x80
+ cborBaseMap = 0xa0
+ cborBaseTag = 0xc0
+ cborBaseSimple = 0xe0
+)
+
+func cbordesc(bd byte) string {
+ switch bd {
+ case cborBdNil:
+ return "nil"
+ case cborBdFalse:
+ return "false"
+ case cborBdTrue:
+ return "true"
+ case cborBdFloat16, cborBdFloat32, cborBdFloat64:
+ return "float"
+ case cborBdIndefiniteBytes:
+ return "bytes*"
+ case cborBdIndefiniteString:
+ return "string*"
+ case cborBdIndefiniteArray:
+ return "array*"
+ case cborBdIndefiniteMap:
+ return "map*"
+ default:
+ switch {
+ case bd >= cborBaseUint && bd < cborBaseNegInt:
+ return "(u)int"
+ case bd >= cborBaseNegInt && bd < cborBaseBytes:
+ return "int"
+ case bd >= cborBaseBytes && bd < cborBaseString:
+ return "bytes"
+ case bd >= cborBaseString && bd < cborBaseArray:
+ return "string"
+ case bd >= cborBaseArray && bd < cborBaseMap:
+ return "array"
+ case bd >= cborBaseMap && bd < cborBaseTag:
+ return "map"
+ case bd >= cborBaseTag && bd < cborBaseSimple:
+ return "ext"
+ default:
+ return "unknown"
+ }
+ }
+}
+
+// -------------------
+
+type cborEncDriver struct {
+ noBuiltInTypes
+ encDriverNoopContainerWriter
+ // encNoSeparator
+ e *Encoder
+ w encWriter
+ h *CborHandle
+ x [8]byte
+ _ [3]uint64 // padding
+}
+
+func (e *cborEncDriver) EncodeNil() {
+ e.w.writen1(cborBdNil)
+}
+
+func (e *cborEncDriver) EncodeBool(b bool) {
+ if b {
+ e.w.writen1(cborBdTrue)
+ } else {
+ e.w.writen1(cborBdFalse)
+ }
+}
+
+func (e *cborEncDriver) EncodeFloat32(f float32) {
+ e.w.writen1(cborBdFloat32)
+ bigenHelper{e.x[:4], e.w}.writeUint32(math.Float32bits(f))
+}
+
+func (e *cborEncDriver) EncodeFloat64(f float64) {
+ e.w.writen1(cborBdFloat64)
+ bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
+}
+
+func (e *cborEncDriver) encUint(v uint64, bd byte) {
+ if v <= 0x17 {
+ e.w.writen1(byte(v) + bd)
+ } else if v <= math.MaxUint8 {
+ e.w.writen2(bd+0x18, uint8(v))
+ } else if v <= math.MaxUint16 {
+ e.w.writen1(bd + 0x19)
+ bigenHelper{e.x[:2], e.w}.writeUint16(uint16(v))
+ } else if v <= math.MaxUint32 {
+ e.w.writen1(bd + 0x1a)
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(v))
+ } else { // if v <= math.MaxUint64 {
+ e.w.writen1(bd + 0x1b)
+ bigenHelper{e.x[:8], e.w}.writeUint64(v)
+ }
+}
+
+func (e *cborEncDriver) EncodeInt(v int64) {
+ if v < 0 {
+ e.encUint(uint64(-1-v), cborBaseNegInt)
+ } else {
+ e.encUint(uint64(v), cborBaseUint)
+ }
+}
+
+func (e *cborEncDriver) EncodeUint(v uint64) {
+ e.encUint(v, cborBaseUint)
+}
+
+func (e *cborEncDriver) encLen(bd byte, length int) {
+ e.encUint(uint64(length), bd)
+}
+
+func (e *cborEncDriver) EncodeTime(t time.Time) {
+ if t.IsZero() {
+ e.EncodeNil()
+ } else if e.h.TimeRFC3339 {
+ e.encUint(0, cborBaseTag)
+ e.EncodeString(cUTF8, t.Format(time.RFC3339Nano))
+ } else {
+ e.encUint(1, cborBaseTag)
+ t = t.UTC().Round(time.Microsecond)
+ sec, nsec := t.Unix(), uint64(t.Nanosecond())
+ if nsec == 0 {
+ e.EncodeInt(sec)
+ } else {
+ e.EncodeFloat64(float64(sec) + float64(nsec)/1e9)
+ }
+ }
+}
+
+func (e *cborEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
+ e.encUint(uint64(xtag), cborBaseTag)
+ if v := ext.ConvertExt(rv); v == nil {
+ e.EncodeNil()
+ } else {
+ en.encode(v)
+ }
+}
+
+func (e *cborEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
+ e.encUint(uint64(re.Tag), cborBaseTag)
+ if false && re.Data != nil {
+ en.encode(re.Data)
+ } else if re.Value != nil {
+ en.encode(re.Value)
+ } else {
+ e.EncodeNil()
+ }
+}
+
+func (e *cborEncDriver) WriteArrayStart(length int) {
+ if e.h.IndefiniteLength {
+ e.w.writen1(cborBdIndefiniteArray)
+ } else {
+ e.encLen(cborBaseArray, length)
+ }
+}
+
+func (e *cborEncDriver) WriteMapStart(length int) {
+ if e.h.IndefiniteLength {
+ e.w.writen1(cborBdIndefiniteMap)
+ } else {
+ e.encLen(cborBaseMap, length)
+ }
+}
+
+func (e *cborEncDriver) WriteMapEnd() {
+ if e.h.IndefiniteLength {
+ e.w.writen1(cborBdBreak)
+ }
+}
+
+func (e *cborEncDriver) WriteArrayEnd() {
+ if e.h.IndefiniteLength {
+ e.w.writen1(cborBdBreak)
+ }
+}
+
+func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
+ e.encStringBytesS(cborBaseString, v)
+}
+
+func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+ if v == nil {
+ e.EncodeNil()
+ } else if c == cRAW {
+ e.encStringBytesS(cborBaseBytes, stringView(v))
+ } else {
+ e.encStringBytesS(cborBaseString, stringView(v))
+ }
+}
+
+func (e *cborEncDriver) encStringBytesS(bb byte, v string) {
+ if e.h.IndefiniteLength {
+ if bb == cborBaseBytes {
+ e.w.writen1(cborBdIndefiniteBytes)
+ } else {
+ e.w.writen1(cborBdIndefiniteString)
+ }
+ blen := len(v) / 4
+ if blen == 0 {
+ blen = 64
+ } else if blen > 1024 {
+ blen = 1024
+ }
+ for i := 0; i < len(v); {
+ var v2 string
+ i2 := i + blen
+ if i2 < len(v) {
+ v2 = v[i:i2]
+ } else {
+ v2 = v[i:]
+ }
+ e.encLen(bb, len(v2))
+ e.w.writestr(v2)
+ i = i2
+ }
+ e.w.writen1(cborBdBreak)
+ } else {
+ e.encLen(bb, len(v))
+ e.w.writestr(v)
+ }
+}
+
+// ----------------------
+
+type cborDecDriver struct {
+ d *Decoder
+ h *CborHandle
+ r decReader
+ // b [scratchByteArrayLen]byte
+ br bool // bytes reader
+ bdRead bool
+ bd byte
+ noBuiltInTypes
+ // decNoSeparator
+ decDriverNoopContainerReader
+ _ [3]uint64 // padding
+}
+
+func (d *cborDecDriver) readNextBd() {
+ d.bd = d.r.readn1()
+ d.bdRead = true
+}
+
+func (d *cborDecDriver) uncacheRead() {
+ if d.bdRead {
+ d.r.unreadn1()
+ d.bdRead = false
+ }
+}
+
+func (d *cborDecDriver) ContainerType() (vt valueType) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == cborBdNil {
+ return valueTypeNil
+ } else if d.bd == cborBdIndefiniteBytes || (d.bd >= cborBaseBytes && d.bd < cborBaseString) {
+ return valueTypeBytes
+ } else if d.bd == cborBdIndefiniteString || (d.bd >= cborBaseString && d.bd < cborBaseArray) {
+ return valueTypeString
+ } else if d.bd == cborBdIndefiniteArray || (d.bd >= cborBaseArray && d.bd < cborBaseMap) {
+ return valueTypeArray
+ } else if d.bd == cborBdIndefiniteMap || (d.bd >= cborBaseMap && d.bd < cborBaseTag) {
+ return valueTypeMap
+ }
+ // else {
+ // d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+ // }
+ return valueTypeUnset
+}
+
+func (d *cborDecDriver) TryDecodeAsNil() bool {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ // treat Nil and Undefined as nil values
+ if d.bd == cborBdNil || d.bd == cborBdUndefined {
+ d.bdRead = false
+ return true
+ }
+ return false
+}
+
+func (d *cborDecDriver) CheckBreak() bool {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == cborBdBreak {
+ d.bdRead = false
+ return true
+ }
+ return false
+}
+
+func (d *cborDecDriver) decUint() (ui uint64) {
+ v := d.bd & 0x1f
+ if v <= 0x17 {
+ ui = uint64(v)
+ } else {
+ if v == 0x18 {
+ ui = uint64(d.r.readn1())
+ } else if v == 0x19 {
+ ui = uint64(bigen.Uint16(d.r.readx(2)))
+ } else if v == 0x1a {
+ ui = uint64(bigen.Uint32(d.r.readx(4)))
+ } else if v == 0x1b {
+ ui = uint64(bigen.Uint64(d.r.readx(8)))
+ } else {
+ d.d.errorf("invalid descriptor decoding uint: %x/%s", d.bd, cbordesc(d.bd))
+ return
+ }
+ }
+ return
+}
+
+func (d *cborDecDriver) decCheckInteger() (neg bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ major := d.bd >> 5
+ if major == cborMajorUint {
+ } else if major == cborMajorNegInt {
+ neg = true
+ } else {
+ d.d.errorf("not an integer - invalid major %v from descriptor %x/%s", major, d.bd, cbordesc(d.bd))
+ return
+ }
+ return
+}
+
+func (d *cborDecDriver) DecodeInt64() (i int64) {
+ neg := d.decCheckInteger()
+ ui := d.decUint()
+ // check if this number can be converted to an int without overflow
+ if neg {
+ i = -(chkOvf.SignedIntV(ui + 1))
+ } else {
+ i = chkOvf.SignedIntV(ui)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *cborDecDriver) DecodeUint64() (ui uint64) {
+ if d.decCheckInteger() {
+ d.d.errorf("assigning negative signed value to unsigned type")
+ return
+ }
+ ui = d.decUint()
+ d.bdRead = false
+ return
+}
+
+func (d *cborDecDriver) DecodeFloat64() (f float64) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if bd := d.bd; bd == cborBdFloat16 {
+ f = float64(math.Float32frombits(halfFloatToFloatBits(bigen.Uint16(d.r.readx(2)))))
+ } else if bd == cborBdFloat32 {
+ f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+ } else if bd == cborBdFloat64 {
+ f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+ } else if bd >= cborBaseUint && bd < cborBaseBytes {
+ f = float64(d.DecodeInt64())
+ } else {
+ d.d.errorf("float only valid from float16/32/64 - invalid descriptor %x/%s", bd, cbordesc(bd))
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+// bool can be decoded from bool only (single byte).
+func (d *cborDecDriver) DecodeBool() (b bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if bd := d.bd; bd == cborBdTrue {
+ b = true
+ } else if bd == cborBdFalse {
+ } else {
+ d.d.errorf("not bool - %s %x/%s", msgBadDesc, d.bd, cbordesc(d.bd))
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *cborDecDriver) ReadMapStart() (length int) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ d.bdRead = false
+ if d.bd == cborBdIndefiniteMap {
+ return -1
+ }
+ return d.decLen()
+}
+
+func (d *cborDecDriver) ReadArrayStart() (length int) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ d.bdRead = false
+ if d.bd == cborBdIndefiniteArray {
+ return -1
+ }
+ return d.decLen()
+}
+
+func (d *cborDecDriver) decLen() int {
+ return int(d.decUint())
+}
+
+func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
+ d.bdRead = false
+ for {
+ if d.CheckBreak() {
+ break
+ }
+ if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorText {
+ d.d.errorf("expect bytes/string major type in indefinite string/bytes;"+
+ " got major %v from descriptor %x/%x", major, d.bd, cbordesc(d.bd))
+ return nil
+ }
+ n := d.decLen()
+ oldLen := len(bs)
+ newLen := oldLen + n
+ if newLen > cap(bs) {
+ bs2 := make([]byte, newLen, 2*cap(bs)+n)
+ copy(bs2, bs)
+ bs = bs2
+ } else {
+ bs = bs[:newLen]
+ }
+ d.r.readb(bs[oldLen:newLen])
+ // bs = append(bs, d.r.readn()...)
+ d.bdRead = false
+ }
+ d.bdRead = false
+ return bs
+}
+
+func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == cborBdNil || d.bd == cborBdUndefined {
+ d.bdRead = false
+ return nil
+ }
+ if d.bd == cborBdIndefiniteBytes || d.bd == cborBdIndefiniteString {
+ d.bdRead = false
+ if bs == nil {
+ if zerocopy {
+ return d.decAppendIndefiniteBytes(d.d.b[:0])
+ }
+ return d.decAppendIndefiniteBytes(zeroByteSlice)
+ }
+ return d.decAppendIndefiniteBytes(bs[:0])
+ }
+ // check if an "array" of uint8's (see ContainerType for how to infer if an array)
+ if d.bd == cborBdIndefiniteArray || (d.bd >= cborBaseArray && d.bd < cborBaseMap) {
+ bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+ return
+ }
+ clen := d.decLen()
+ d.bdRead = false
+ if zerocopy {
+ if d.br {
+ return d.r.readx(clen)
+ } else if len(bs) == 0 {
+ bs = d.d.b[:]
+ }
+ }
+ return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
+}
+
+func (d *cborDecDriver) DecodeString() (s string) {
+ return string(d.DecodeBytes(d.d.b[:], true))
+}
+
+func (d *cborDecDriver) DecodeStringAsBytes() (s []byte) {
+ return d.DecodeBytes(d.d.b[:], true)
+}
+
+func (d *cborDecDriver) DecodeTime() (t time.Time) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == cborBdNil || d.bd == cborBdUndefined {
+ d.bdRead = false
+ return
+ }
+ xtag := d.decUint()
+ d.bdRead = false
+ return d.decodeTime(xtag)
+}
+
+func (d *cborDecDriver) decodeTime(xtag uint64) (t time.Time) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ switch xtag {
+ case 0:
+ var err error
+ if t, err = time.Parse(time.RFC3339, stringView(d.DecodeStringAsBytes())); err != nil {
+ d.d.errorv(err)
+ }
+ case 1:
+ // decode an int64 or a float, and infer time.Time from there.
+ // for floats, round to microseconds, as that is what is guaranteed to fit well.
+ switch {
+ case d.bd == cborBdFloat16, d.bd == cborBdFloat32:
+ f1, f2 := math.Modf(d.DecodeFloat64())
+ t = time.Unix(int64(f1), int64(f2*1e9))
+ case d.bd == cborBdFloat64:
+ f1, f2 := math.Modf(d.DecodeFloat64())
+ t = time.Unix(int64(f1), int64(f2*1e9))
+ case d.bd >= cborBaseUint && d.bd < cborBaseNegInt,
+ d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
+ t = time.Unix(d.DecodeInt64(), 0)
+ default:
+ d.d.errorf("time.Time can only be decoded from a number (or RFC3339 string)")
+ }
+ default:
+ d.d.errorf("invalid tag for time.Time - expecting 0 or 1, got 0x%x", xtag)
+ }
+ t = t.UTC().Round(time.Microsecond)
+ return
+}
+
+func (d *cborDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ u := d.decUint()
+ d.bdRead = false
+ realxtag = u
+ if ext == nil {
+ re := rv.(*RawExt)
+ re.Tag = realxtag
+ d.d.decode(&re.Value)
+ } else if xtag != realxtag {
+ d.d.errorf("Wrong extension tag. Got %b. Expecting: %v", realxtag, xtag)
+ return
+ } else {
+ var v interface{}
+ d.d.decode(&v)
+ ext.UpdateExt(rv, v)
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *cborDecDriver) DecodeNaked() {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+
+ n := d.d.n
+ var decodeFurther bool
+
+ switch d.bd {
+ case cborBdNil:
+ n.v = valueTypeNil
+ case cborBdFalse:
+ n.v = valueTypeBool
+ n.b = false
+ case cborBdTrue:
+ n.v = valueTypeBool
+ n.b = true
+ case cborBdFloat16, cborBdFloat32, cborBdFloat64:
+ n.v = valueTypeFloat
+ n.f = d.DecodeFloat64()
+ case cborBdIndefiniteBytes:
+ n.v = valueTypeBytes
+ n.l = d.DecodeBytes(nil, false)
+ case cborBdIndefiniteString:
+ n.v = valueTypeString
+ n.s = d.DecodeString()
+ case cborBdIndefiniteArray:
+ n.v = valueTypeArray
+ decodeFurther = true
+ case cborBdIndefiniteMap:
+ n.v = valueTypeMap
+ decodeFurther = true
+ default:
+ switch {
+ case d.bd >= cborBaseUint && d.bd < cborBaseNegInt:
+ if d.h.SignedInteger {
+ n.v = valueTypeInt
+ n.i = d.DecodeInt64()
+ } else {
+ n.v = valueTypeUint
+ n.u = d.DecodeUint64()
+ }
+ case d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
+ n.v = valueTypeInt
+ n.i = d.DecodeInt64()
+ case d.bd >= cborBaseBytes && d.bd < cborBaseString:
+ n.v = valueTypeBytes
+ n.l = d.DecodeBytes(nil, false)
+ case d.bd >= cborBaseString && d.bd < cborBaseArray:
+ n.v = valueTypeString
+ n.s = d.DecodeString()
+ case d.bd >= cborBaseArray && d.bd < cborBaseMap:
+ n.v = valueTypeArray
+ decodeFurther = true
+ case d.bd >= cborBaseMap && d.bd < cborBaseTag:
+ n.v = valueTypeMap
+ decodeFurther = true
+ case d.bd >= cborBaseTag && d.bd < cborBaseSimple:
+ n.v = valueTypeExt
+ n.u = d.decUint()
+ n.l = nil
+ if n.u == 0 || n.u == 1 {
+ d.bdRead = false
+ n.v = valueTypeTime
+ n.t = d.decodeTime(n.u)
+ }
+ // d.bdRead = false
+ // d.d.decode(&re.Value) // handled by decode itself.
+ // decodeFurther = true
+ default:
+ d.d.errorf("decodeNaked: Unrecognized d.bd: 0x%x", d.bd)
+ return
+ }
+ }
+
+ if !decodeFurther {
+ d.bdRead = false
+ }
+ return
+}
+
+// -------------------------
+
+// CborHandle is a Handle for the CBOR encoding format,
+// defined at http://tools.ietf.org/html/rfc7049 and documented further at http://cbor.io .
+//
+// CBOR is comprehensively supported, including support for:
+// - indefinite-length arrays/maps/bytes/strings
+// - (extension) tags in range 0..0xffff (0 .. 65535)
+// - half, single and double-precision floats
+// - all numbers (1, 2, 4 and 8-byte signed and unsigned integers)
+// - nil, true, false, ...
+// - arrays and maps, bytes and text strings
+//
+// None of the optional extensions (with tags) defined in the spec are supported out-of-the-box.
+// Users can implement them as needed (using SetExt), including spec-documented ones:
+// - timestamp, BigNum, BigFloat, Decimals,
+// - Encoded Text (e.g. URL, regexp, base64, MIME Message), etc.
+type CborHandle struct {
+ binaryEncodingType
+ noElemSeparators
+ BasicHandle
+
+ // IndefiniteLength=true, means that we encode using indefinitelength
+ IndefiniteLength bool
+
+ // TimeRFC3339 says to encode time.Time using RFC3339 format.
+ // If unset, we encode time.Time using seconds past epoch.
+ TimeRFC3339 bool
+
+ // _ [1]uint64 // padding
+}
+
+// Name returns the name of the handle: cbor
+func (h *CborHandle) Name() string { return "cbor" }
+
+// SetInterfaceExt sets an extension
+func (h *CborHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
+ return h.SetExt(rt, tag, &extWrapper{bytesExtFailer{}, ext})
+}
+
+func (h *CborHandle) newEncDriver(e *Encoder) encDriver {
+ return &cborEncDriver{e: e, w: e.w, h: h}
+}
+
+func (h *CborHandle) newDecDriver(d *Decoder) decDriver {
+ return &cborDecDriver{d: d, h: h, r: d.r, br: d.bytes}
+}
+
+func (e *cborEncDriver) reset() {
+ e.w = e.e.w
+}
+
+func (d *cborDecDriver) reset() {
+ d.r, d.br = d.d.r, d.d.bytes
+ d.bd, d.bdRead = 0, false
+}
+
+var _ decDriver = (*cborDecDriver)(nil)
+var _ encDriver = (*cborEncDriver)(nil)
diff --git a/vendor/github.com/ugorji/go/codec/decode.go b/vendor/github.com/ugorji/go/codec/decode.go
new file mode 100644
index 00000000..1c0817aa
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/decode.go
@@ -0,0 +1,2552 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strconv"
+ "sync"
+ "time"
+)
+
+// Some tagging information for error messages.
+const (
+ msgBadDesc = "unrecognized descriptor byte"
+ msgDecCannotExpandArr = "cannot expand go array from %v to stream length: %v"
+)
+
+const decDefSliceCap = 8
+const decDefChanCap = 64 // should be large, as cap cannot be expanded
+const decScratchByteArrayLen = cacheLineSize - 8
+
+var (
+ errstrOnlyMapOrArrayCanDecodeIntoStruct = "only encoded map or array can be decoded into a struct"
+ errstrCannotDecodeIntoNil = "cannot decode into nil"
+
+ errmsgExpandSliceOverflow = "expand slice: slice overflow"
+ errmsgExpandSliceCannotChange = "expand slice: cannot change"
+
+ errDecoderNotInitialized = errors.New("Decoder not initialized")
+
+ errDecUnreadByteNothingToRead = errors.New("cannot unread - nothing has been read")
+ errDecUnreadByteLastByteNotRead = errors.New("cannot unread - last byte has not been read")
+ errDecUnreadByteUnknown = errors.New("cannot unread - reason unknown")
+)
+
+// decReader abstracts the reading source, allowing implementations that can
+// read from an io.Reader or directly off a byte slice with zero-copying.
+type decReader interface {
+ unreadn1()
+
+ // readx will use the implementation scratch buffer if possible i.e. n < len(scratchbuf), OR
+ // just return a view of the []byte being decoded from.
+ // Ensure you call detachZeroCopyBytes later if this needs to be sent outside codec control.
+ readx(n int) []byte
+ readb([]byte)
+ readn1() uint8
+ numread() int // number of bytes read
+ track()
+ stopTrack() []byte
+
+ // skip will skip any byte that matches, and return the first non-matching byte
+ skip(accept *bitset256) (token byte)
+ // readTo will read any byte that matches, stopping once no-longer matching.
+ readTo(in []byte, accept *bitset256) (out []byte)
+ // readUntil will read, only stopping once it matches the 'stop' byte.
+ readUntil(in []byte, stop byte) (out []byte)
+}
+
+type decDriver interface {
+ // this will check if the next token is a break.
+ CheckBreak() bool
+ // Note: TryDecodeAsNil should be careful not to share any temporary []byte with
+ // the rest of the decDriver. This is because sometimes, we optimize by holding onto
+ // a transient []byte, and ensuring the only other call we make to the decDriver
+ // during that time is maybe a TryDecodeAsNil() call.
+ TryDecodeAsNil() bool
+ // vt is one of: Bytes, String, Nil, Slice or Map. Return unSet if not known.
+ ContainerType() (vt valueType)
+ // IsBuiltinType(rt uintptr) bool
+
+ // DecodeNaked will decode primitives (number, bool, string, []byte) and RawExt.
+ // For maps and arrays, it will not do the decoding in-band, but will signal
+ // the decoder, so that is done later, by setting the decNaked.valueType field.
+ //
+ // Note: Numbers are decoded as int64, uint64, float64 only (no smaller sized number types).
+ // for extensions, DecodeNaked must read the tag and the []byte if it exists.
+ // if the []byte is not read, then kInterfaceNaked will treat it as a Handle
+ // that stores the subsequent value in-band, and complete reading the RawExt.
+ //
+ // extensions should also use readx to decode them, for efficiency.
+ // kInterface will extract the detached byte slice if it has to pass it outside its realm.
+ DecodeNaked()
+
+ // Deprecated: use DecodeInt64 and DecodeUint64 instead
+ // DecodeInt(bitsize uint8) (i int64)
+ // DecodeUint(bitsize uint8) (ui uint64)
+
+ DecodeInt64() (i int64)
+ DecodeUint64() (ui uint64)
+
+ DecodeFloat64() (f float64)
+ DecodeBool() (b bool)
+ // DecodeString can also decode symbols.
+ // It looks redundant as DecodeBytes is available.
+ // However, some codecs (e.g. binc) support symbols and can
+ // return a pre-stored string value, meaning that it can bypass
+ // the cost of []byte->string conversion.
+ DecodeString() (s string)
+ DecodeStringAsBytes() (v []byte)
+
+ // DecodeBytes may be called directly, without going through reflection.
+ // Consequently, it must be designed to handle possible nil.
+ DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
+ // DecodeBytes(bs []byte, isstring, zerocopy bool) (bsOut []byte)
+
+ // decodeExt will decode into a *RawExt or into an extension.
+ DecodeExt(v interface{}, xtag uint64, ext Ext) (realxtag uint64)
+ // decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte)
+
+ DecodeTime() (t time.Time)
+
+ ReadArrayStart() int
+ ReadArrayElem()
+ ReadArrayEnd()
+ ReadMapStart() int
+ ReadMapElemKey()
+ ReadMapElemValue()
+ ReadMapEnd()
+
+ reset()
+ uncacheRead()
+}
+
+type decDriverNoopContainerReader struct{}
+
+func (x decDriverNoopContainerReader) ReadArrayStart() (v int) { return }
+func (x decDriverNoopContainerReader) ReadArrayElem() {}
+func (x decDriverNoopContainerReader) ReadArrayEnd() {}
+func (x decDriverNoopContainerReader) ReadMapStart() (v int) { return }
+func (x decDriverNoopContainerReader) ReadMapElemKey() {}
+func (x decDriverNoopContainerReader) ReadMapElemValue() {}
+func (x decDriverNoopContainerReader) ReadMapEnd() {}
+func (x decDriverNoopContainerReader) CheckBreak() (v bool) { return }
+
+// func (x decNoSeparator) uncacheRead() {}
+
+// DecodeOptions captures configuration options during decode.
+type DecodeOptions struct {
+ // MapType specifies type to use during schema-less decoding of a map in the stream.
+ // If nil (unset), we default to map[string]interface{} iff json handle and MapStringAsKey=true,
+ // else map[interface{}]interface{}.
+ MapType reflect.Type
+
+ // SliceType specifies type to use during schema-less decoding of an array in the stream.
+ // If nil (unset), we default to []interface{} for all formats.
+ SliceType reflect.Type
+
+ // MaxInitLen defines the maxinum initial length that we "make" a collection
+ // (string, slice, map, chan). If 0 or negative, we default to a sensible value
+ // based on the size of an element in the collection.
+ //
+ // For example, when decoding, a stream may say that it has 2^64 elements.
+ // We should not auto-matically provision a slice of that size, to prevent Out-Of-Memory crash.
+ // Instead, we provision up to MaxInitLen, fill that up, and start appending after that.
+ MaxInitLen int
+
+ // ReaderBufferSize is the size of the buffer used when reading.
+ //
+ // if > 0, we use a smart buffer internally for performance purposes.
+ ReaderBufferSize int
+
+ // If ErrorIfNoField, return an error when decoding a map
+ // from a codec stream into a struct, and no matching struct field is found.
+ ErrorIfNoField bool
+
+ // If ErrorIfNoArrayExpand, return an error when decoding a slice/array that cannot be expanded.
+ // For example, the stream contains an array of 8 items, but you are decoding into a [4]T array,
+ // or you are decoding into a slice of length 4 which is non-addressable (and so cannot be set).
+ ErrorIfNoArrayExpand bool
+
+ // If SignedInteger, use the int64 during schema-less decoding of unsigned values (not uint64).
+ SignedInteger bool
+
+ // MapValueReset controls how we decode into a map value.
+ //
+ // By default, we MAY retrieve the mapping for a key, and then decode into that.
+ // However, especially with big maps, that retrieval may be expensive and unnecessary
+ // if the stream already contains all that is necessary to recreate the value.
+ //
+ // If true, we will never retrieve the previous mapping,
+ // but rather decode into a new value and set that in the map.
+ //
+ // If false, we will retrieve the previous mapping if necessary e.g.
+ // the previous mapping is a pointer, or is a struct or array with pre-set state,
+ // or is an interface.
+ MapValueReset bool
+
+ // SliceElementReset: on decoding a slice, reset the element to a zero value first.
+ //
+ // concern: if the slice already contained some garbage, we will decode into that garbage.
+ SliceElementReset bool
+
+ // InterfaceReset controls how we decode into an interface.
+ //
+ // By default, when we see a field that is an interface{...},
+ // or a map with interface{...} value, we will attempt decoding into the
+ // "contained" value.
+ //
+ // However, this prevents us from reading a string into an interface{}
+ // that formerly contained a number.
+ //
+ // If true, we will decode into a new "blank" value, and set that in the interface.
+ // If false, we will decode into whatever is contained in the interface.
+ InterfaceReset bool
+
+ // InternString controls interning of strings during decoding.
+ //
+ // Some handles, e.g. json, typically will read map keys as strings.
+ // If the set of keys are finite, it may help reduce allocation to
+ // look them up from a map (than to allocate them afresh).
+ //
+ // Note: Handles will be smart when using the intern functionality.
+ // Every string should not be interned.
+ // An excellent use-case for interning is struct field names,
+ // or map keys where key type is string.
+ InternString bool
+
+ // PreferArrayOverSlice controls whether to decode to an array or a slice.
+ //
+ // This only impacts decoding into a nil interface{}.
+ // Consequently, it has no effect on codecgen.
+ //
+ // *Note*: This only applies if using go1.5 and above,
+ // as it requires reflect.ArrayOf support which was absent before go1.5.
+ PreferArrayOverSlice bool
+
+ // DeleteOnNilMapValue controls how to decode a nil value in the stream.
+ //
+ // If true, we will delete the mapping of the key.
+ // Else, just set the mapping to the zero value of the type.
+ DeleteOnNilMapValue bool
+}
+
+// ------------------------------------
+
+type bufioDecReader struct {
+ buf []byte
+ r io.Reader
+
+ c int // cursor
+ n int // num read
+ err error
+
+ tr []byte
+ trb bool
+ b [4]byte
+}
+
+func (z *bufioDecReader) reset(r io.Reader) {
+ z.r, z.c, z.n, z.err, z.trb = r, 0, 0, nil, false
+ if z.tr != nil {
+ z.tr = z.tr[:0]
+ }
+}
+
+func (z *bufioDecReader) Read(p []byte) (n int, err error) {
+ if z.err != nil {
+ return 0, z.err
+ }
+ p0 := p
+ n = copy(p, z.buf[z.c:])
+ z.c += n
+ if z.c == len(z.buf) {
+ z.c = 0
+ }
+ z.n += n
+ if len(p) == n {
+ if z.c == 0 {
+ z.buf = z.buf[:1]
+ z.buf[0] = p[len(p)-1]
+ z.c = 1
+ }
+ if z.trb {
+ z.tr = append(z.tr, p0[:n]...)
+ }
+ return
+ }
+ p = p[n:]
+ var n2 int
+ // if we are here, then z.buf is all read
+ if len(p) > len(z.buf) {
+ n2, err = decReadFull(z.r, p)
+ n += n2
+ z.n += n2
+ z.err = err
+ // don't return EOF if some bytes were read. keep for next time.
+ if n > 0 && err == io.EOF {
+ err = nil
+ }
+ // always keep last byte in z.buf
+ z.buf = z.buf[:1]
+ z.buf[0] = p[len(p)-1]
+ z.c = 1
+ if z.trb {
+ z.tr = append(z.tr, p0[:n]...)
+ }
+ return
+ }
+ // z.c is now 0, and len(p) <= len(z.buf)
+ for len(p) > 0 && z.err == nil {
+ // println("len(p) loop starting ... ")
+ z.c = 0
+ z.buf = z.buf[0:cap(z.buf)]
+ n2, err = z.r.Read(z.buf)
+ if n2 > 0 {
+ if err == io.EOF {
+ err = nil
+ }
+ z.buf = z.buf[:n2]
+ n2 = copy(p, z.buf)
+ z.c = n2
+ n += n2
+ z.n += n2
+ p = p[n2:]
+ }
+ z.err = err
+ // println("... len(p) loop done")
+ }
+ if z.c == 0 {
+ z.buf = z.buf[:1]
+ z.buf[0] = p[len(p)-1]
+ z.c = 1
+ }
+ if z.trb {
+ z.tr = append(z.tr, p0[:n]...)
+ }
+ return
+}
+
+func (z *bufioDecReader) ReadByte() (b byte, err error) {
+ z.b[0] = 0
+ _, err = z.Read(z.b[:1])
+ b = z.b[0]
+ return
+}
+
+func (z *bufioDecReader) UnreadByte() (err error) {
+ if z.err != nil {
+ return z.err
+ }
+ if z.c > 0 {
+ z.c--
+ z.n--
+ if z.trb {
+ z.tr = z.tr[:len(z.tr)-1]
+ }
+ return
+ }
+ return errDecUnreadByteNothingToRead
+}
+
+func (z *bufioDecReader) numread() int {
+ return z.n
+}
+
+func (z *bufioDecReader) readx(n int) (bs []byte) {
+ if n <= 0 || z.err != nil {
+ return
+ }
+ if z.c+n <= len(z.buf) {
+ bs = z.buf[z.c : z.c+n]
+ z.n += n
+ z.c += n
+ if z.trb {
+ z.tr = append(z.tr, bs...)
+ }
+ return
+ }
+ bs = make([]byte, n)
+ _, err := z.Read(bs)
+ if err != nil {
+ panic(err)
+ }
+ return
+}
+
+func (z *bufioDecReader) readb(bs []byte) {
+ _, err := z.Read(bs)
+ if err != nil {
+ panic(err)
+ }
+}
+
+// func (z *bufioDecReader) readn1eof() (b uint8, eof bool) {
+// b, err := z.ReadByte()
+// if err != nil {
+// if err == io.EOF {
+// eof = true
+// } else {
+// panic(err)
+// }
+// }
+// return
+// }
+
+func (z *bufioDecReader) readn1() (b uint8) {
+ b, err := z.ReadByte()
+ if err != nil {
+ panic(err)
+ }
+ return
+}
+
+func (z *bufioDecReader) search(in []byte, accept *bitset256, stop, flag uint8) (token byte, out []byte) {
+ // flag: 1 (skip), 2 (readTo), 4 (readUntil)
+ if flag == 4 {
+ for i := z.c; i < len(z.buf); i++ {
+ if z.buf[i] == stop {
+ token = z.buf[i]
+ z.n = z.n + (i - z.c) - 1
+ i++
+ out = z.buf[z.c:i]
+ if z.trb {
+ z.tr = append(z.tr, z.buf[z.c:i]...)
+ }
+ z.c = i
+ return
+ }
+ }
+ } else {
+ for i := z.c; i < len(z.buf); i++ {
+ if !accept.isset(z.buf[i]) {
+ token = z.buf[i]
+ z.n = z.n + (i - z.c) - 1
+ if flag == 1 {
+ i++
+ } else {
+ out = z.buf[z.c:i]
+ }
+ if z.trb {
+ z.tr = append(z.tr, z.buf[z.c:i]...)
+ }
+ z.c = i
+ return
+ }
+ }
+ }
+ z.n += len(z.buf) - z.c
+ if flag != 1 {
+ out = append(in, z.buf[z.c:]...)
+ }
+ if z.trb {
+ z.tr = append(z.tr, z.buf[z.c:]...)
+ }
+ var n2 int
+ if z.err != nil {
+ return
+ }
+ for {
+ z.c = 0
+ z.buf = z.buf[0:cap(z.buf)]
+ n2, z.err = z.r.Read(z.buf)
+ if n2 > 0 && z.err != nil {
+ z.err = nil
+ }
+ z.buf = z.buf[:n2]
+ if flag == 4 {
+ for i := 0; i < n2; i++ {
+ if z.buf[i] == stop {
+ token = z.buf[i]
+ z.n += i - 1
+ i++
+ out = append(out, z.buf[z.c:i]...)
+ if z.trb {
+ z.tr = append(z.tr, z.buf[z.c:i]...)
+ }
+ z.c = i
+ return
+ }
+ }
+ } else {
+ for i := 0; i < n2; i++ {
+ if !accept.isset(z.buf[i]) {
+ token = z.buf[i]
+ z.n += i - 1
+ if flag == 1 {
+ i++
+ }
+ if flag != 1 {
+ out = append(out, z.buf[z.c:i]...)
+ }
+ if z.trb {
+ z.tr = append(z.tr, z.buf[z.c:i]...)
+ }
+ z.c = i
+ return
+ }
+ }
+ }
+ if flag != 1 {
+ out = append(out, z.buf[:n2]...)
+ }
+ z.n += n2
+ if z.err != nil {
+ return
+ }
+ if z.trb {
+ z.tr = append(z.tr, z.buf[:n2]...)
+ }
+ }
+}
+
+func (z *bufioDecReader) skip(accept *bitset256) (token byte) {
+ token, _ = z.search(nil, accept, 0, 1)
+ return
+}
+
+func (z *bufioDecReader) readTo(in []byte, accept *bitset256) (out []byte) {
+ _, out = z.search(in, accept, 0, 2)
+ return
+}
+
+func (z *bufioDecReader) readUntil(in []byte, stop byte) (out []byte) {
+ _, out = z.search(in, nil, stop, 4)
+ return
+}
+
+func (z *bufioDecReader) unreadn1() {
+ err := z.UnreadByte()
+ if err != nil {
+ panic(err)
+ }
+}
+
+func (z *bufioDecReader) track() {
+ if z.tr != nil {
+ z.tr = z.tr[:0]
+ }
+ z.trb = true
+}
+
+func (z *bufioDecReader) stopTrack() (bs []byte) {
+ z.trb = false
+ return z.tr
+}
+
+// ioDecReader is a decReader that reads off an io.Reader.
+//
+// It also has a fallback implementation of ByteScanner if needed.
+type ioDecReader struct {
+ r io.Reader // the reader passed in
+
+ rr io.Reader
+ br io.ByteScanner
+
+ l byte // last byte
+ ls byte // last byte status. 0: init-canDoNothing, 1: canRead, 2: canUnread
+ trb bool // tracking bytes turned on
+ _ bool
+ b [4]byte // tiny buffer for reading single bytes
+
+ x [scratchByteArrayLen]byte // for: get struct field name, swallow valueTypeBytes, etc
+ n int // num read
+ tr []byte // tracking bytes read
+}
+
+func (z *ioDecReader) reset(r io.Reader) {
+ z.r = r
+ z.rr = r
+ z.l, z.ls, z.n, z.trb = 0, 0, 0, false
+ if z.tr != nil {
+ z.tr = z.tr[:0]
+ }
+ var ok bool
+ if z.br, ok = r.(io.ByteScanner); !ok {
+ z.br = z
+ z.rr = z
+ }
+}
+
+func (z *ioDecReader) Read(p []byte) (n int, err error) {
+ if len(p) == 0 {
+ return
+ }
+ var firstByte bool
+ if z.ls == 1 {
+ z.ls = 2
+ p[0] = z.l
+ if len(p) == 1 {
+ n = 1
+ return
+ }
+ firstByte = true
+ p = p[1:]
+ }
+ n, err = z.r.Read(p)
+ if n > 0 {
+ if err == io.EOF && n == len(p) {
+ err = nil // read was successful, so postpone EOF (till next time)
+ }
+ z.l = p[n-1]
+ z.ls = 2
+ }
+ if firstByte {
+ n++
+ }
+ return
+}
+
+func (z *ioDecReader) ReadByte() (c byte, err error) {
+ n, err := z.Read(z.b[:1])
+ if n == 1 {
+ c = z.b[0]
+ if err == io.EOF {
+ err = nil // read was successful, so postpone EOF (till next time)
+ }
+ }
+ return
+}
+
+func (z *ioDecReader) UnreadByte() (err error) {
+ switch z.ls {
+ case 2:
+ z.ls = 1
+ case 0:
+ err = errDecUnreadByteNothingToRead
+ case 1:
+ err = errDecUnreadByteLastByteNotRead
+ default:
+ err = errDecUnreadByteUnknown
+ }
+ return
+}
+
+func (z *ioDecReader) numread() int {
+ return z.n
+}
+
+func (z *ioDecReader) readx(n int) (bs []byte) {
+ if n <= 0 {
+ return
+ }
+ if n < len(z.x) {
+ bs = z.x[:n]
+ } else {
+ bs = make([]byte, n)
+ }
+ if _, err := decReadFull(z.rr, bs); err != nil {
+ panic(err)
+ }
+ z.n += len(bs)
+ if z.trb {
+ z.tr = append(z.tr, bs...)
+ }
+ return
+}
+
+func (z *ioDecReader) readb(bs []byte) {
+ // if len(bs) == 0 {
+ // return
+ // }
+ if _, err := decReadFull(z.rr, bs); err != nil {
+ panic(err)
+ }
+ z.n += len(bs)
+ if z.trb {
+ z.tr = append(z.tr, bs...)
+ }
+}
+
+func (z *ioDecReader) readn1eof() (b uint8, eof bool) {
+ b, err := z.br.ReadByte()
+ if err == nil {
+ z.n++
+ if z.trb {
+ z.tr = append(z.tr, b)
+ }
+ } else if err == io.EOF {
+ eof = true
+ } else {
+ panic(err)
+ }
+ return
+}
+
+func (z *ioDecReader) readn1() (b uint8) {
+ var err error
+ if b, err = z.br.ReadByte(); err == nil {
+ z.n++
+ if z.trb {
+ z.tr = append(z.tr, b)
+ }
+ return
+ }
+ panic(err)
+}
+
+func (z *ioDecReader) skip(accept *bitset256) (token byte) {
+ for {
+ var eof bool
+ token, eof = z.readn1eof()
+ if eof {
+ return
+ }
+ if accept.isset(token) {
+ continue
+ }
+ return
+ }
+}
+
+func (z *ioDecReader) readTo(in []byte, accept *bitset256) (out []byte) {
+ out = in
+ for {
+ token, eof := z.readn1eof()
+ if eof {
+ return
+ }
+ if accept.isset(token) {
+ out = append(out, token)
+ } else {
+ z.unreadn1()
+ return
+ }
+ }
+}
+
+func (z *ioDecReader) readUntil(in []byte, stop byte) (out []byte) {
+ out = in
+ for {
+ token, eof := z.readn1eof()
+ if eof {
+ panic(io.EOF)
+ }
+ out = append(out, token)
+ if token == stop {
+ return
+ }
+ }
+}
+
+func (z *ioDecReader) unreadn1() {
+ err := z.br.UnreadByte()
+ if err != nil {
+ panic(err)
+ }
+ z.n--
+ if z.trb {
+ if l := len(z.tr) - 1; l >= 0 {
+ z.tr = z.tr[:l]
+ }
+ }
+}
+
+func (z *ioDecReader) track() {
+ if z.tr != nil {
+ z.tr = z.tr[:0]
+ }
+ z.trb = true
+}
+
+func (z *ioDecReader) stopTrack() (bs []byte) {
+ z.trb = false
+ return z.tr
+}
+
+// ------------------------------------
+
+var errBytesDecReaderCannotUnread = errors.New("cannot unread last byte read")
+
+// bytesDecReader is a decReader that reads off a byte slice with zero copying
+type bytesDecReader struct {
+ b []byte // data
+ c int // cursor
+ a int // available
+ t int // track start
+}
+
+func (z *bytesDecReader) reset(in []byte) {
+ z.b = in
+ z.a = len(in)
+ z.c = 0
+ z.t = 0
+}
+
+func (z *bytesDecReader) numread() int {
+ return z.c
+}
+
+func (z *bytesDecReader) unreadn1() {
+ if z.c == 0 || len(z.b) == 0 {
+ panic(errBytesDecReaderCannotUnread)
+ }
+ z.c--
+ z.a++
+ return
+}
+
+func (z *bytesDecReader) readx(n int) (bs []byte) {
+ // slicing from a non-constant start position is more expensive,
+ // as more computation is required to decipher the pointer start position.
+ // However, we do it only once, and it's better than reslicing both z.b and return value.
+
+ if n <= 0 {
+ } else if z.a == 0 {
+ panic(io.EOF)
+ } else if n > z.a {
+ panic(io.ErrUnexpectedEOF)
+ } else {
+ c0 := z.c
+ z.c = c0 + n
+ z.a = z.a - n
+ bs = z.b[c0:z.c]
+ }
+ return
+}
+
+func (z *bytesDecReader) readb(bs []byte) {
+ copy(bs, z.readx(len(bs)))
+}
+
+func (z *bytesDecReader) readn1() (v uint8) {
+ if z.a == 0 {
+ panic(io.EOF)
+ }
+ v = z.b[z.c]
+ z.c++
+ z.a--
+ return
+}
+
+// func (z *bytesDecReader) readn1eof() (v uint8, eof bool) {
+// if z.a == 0 {
+// eof = true
+// return
+// }
+// v = z.b[z.c]
+// z.c++
+// z.a--
+// return
+// }
+
+func (z *bytesDecReader) skip(accept *bitset256) (token byte) {
+ if z.a == 0 {
+ return
+ }
+ blen := len(z.b)
+ for i := z.c; i < blen; i++ {
+ if !accept.isset(z.b[i]) {
+ token = z.b[i]
+ i++
+ z.a -= (i - z.c)
+ z.c = i
+ return
+ }
+ }
+ z.a, z.c = 0, blen
+ return
+}
+
+func (z *bytesDecReader) readTo(_ []byte, accept *bitset256) (out []byte) {
+ if z.a == 0 {
+ return
+ }
+ blen := len(z.b)
+ for i := z.c; i < blen; i++ {
+ if !accept.isset(z.b[i]) {
+ out = z.b[z.c:i]
+ z.a -= (i - z.c)
+ z.c = i
+ return
+ }
+ }
+ out = z.b[z.c:]
+ z.a, z.c = 0, blen
+ return
+}
+
+func (z *bytesDecReader) readUntil(_ []byte, stop byte) (out []byte) {
+ if z.a == 0 {
+ panic(io.EOF)
+ }
+ blen := len(z.b)
+ for i := z.c; i < blen; i++ {
+ if z.b[i] == stop {
+ i++
+ out = z.b[z.c:i]
+ z.a -= (i - z.c)
+ z.c = i
+ return
+ }
+ }
+ z.a, z.c = 0, blen
+ panic(io.EOF)
+}
+
+func (z *bytesDecReader) track() {
+ z.t = z.c
+}
+
+func (z *bytesDecReader) stopTrack() (bs []byte) {
+ return z.b[z.t:z.c]
+}
+
+// ----------------------------------------
+
+// func (d *Decoder) builtin(f *codecFnInfo, rv reflect.Value) {
+// d.d.DecodeBuiltin(f.ti.rtid, rv2i(rv))
+// }
+
+func (d *Decoder) rawExt(f *codecFnInfo, rv reflect.Value) {
+ d.d.DecodeExt(rv2i(rv), 0, nil)
+}
+
+func (d *Decoder) ext(f *codecFnInfo, rv reflect.Value) {
+ d.d.DecodeExt(rv2i(rv), f.xfTag, f.xfFn)
+}
+
+func (d *Decoder) selferUnmarshal(f *codecFnInfo, rv reflect.Value) {
+ rv2i(rv).(Selfer).CodecDecodeSelf(d)
+}
+
+func (d *Decoder) binaryUnmarshal(f *codecFnInfo, rv reflect.Value) {
+ bm := rv2i(rv).(encoding.BinaryUnmarshaler)
+ xbs := d.d.DecodeBytes(nil, true)
+ if fnerr := bm.UnmarshalBinary(xbs); fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+func (d *Decoder) textUnmarshal(f *codecFnInfo, rv reflect.Value) {
+ tm := rv2i(rv).(encoding.TextUnmarshaler)
+ fnerr := tm.UnmarshalText(d.d.DecodeStringAsBytes())
+ if fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+func (d *Decoder) jsonUnmarshal(f *codecFnInfo, rv reflect.Value) {
+ tm := rv2i(rv).(jsonUnmarshaler)
+ // bs := d.d.DecodeBytes(d.b[:], true, true)
+ // grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself.
+ fnerr := tm.UnmarshalJSON(d.nextValueBytes())
+ if fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+func (d *Decoder) kErr(f *codecFnInfo, rv reflect.Value) {
+ d.errorf("no decoding function defined for kind %v", rv.Kind())
+}
+
+// var kIntfCtr uint64
+
+func (d *Decoder) kInterfaceNaked(f *codecFnInfo) (rvn reflect.Value) {
+ // nil interface:
+ // use some hieristics to decode it appropriately
+ // based on the detected next value in the stream.
+ n := d.naked()
+ d.d.DecodeNaked()
+ if n.v == valueTypeNil {
+ return
+ }
+ // We cannot decode non-nil stream value into nil interface with methods (e.g. io.Reader).
+ if f.ti.numMeth > 0 {
+ d.errorf("cannot decode non-nil codec value into nil %v (%v methods)", f.ti.rt, f.ti.numMeth)
+ return
+ }
+ // var useRvn bool
+ switch n.v {
+ case valueTypeMap:
+ // if json, default to a map type with string keys
+ mtid := d.mtid
+ if mtid == 0 {
+ if d.jsms {
+ mtid = mapStrIntfTypId
+ } else {
+ mtid = mapIntfIntfTypId
+ }
+ }
+ if mtid == mapIntfIntfTypId {
+ n.initContainers()
+ if n.lm < arrayCacheLen {
+ n.ma[n.lm] = nil
+ rvn = n.rma[n.lm]
+ n.lm++
+ d.decode(&n.ma[n.lm-1])
+ n.lm--
+ } else {
+ var v2 map[interface{}]interface{}
+ d.decode(&v2)
+ rvn = reflect.ValueOf(&v2).Elem()
+ }
+ } else if mtid == mapStrIntfTypId { // for json performance
+ n.initContainers()
+ if n.ln < arrayCacheLen {
+ n.na[n.ln] = nil
+ rvn = n.rna[n.ln]
+ n.ln++
+ d.decode(&n.na[n.ln-1])
+ n.ln--
+ } else {
+ var v2 map[string]interface{}
+ d.decode(&v2)
+ rvn = reflect.ValueOf(&v2).Elem()
+ }
+ } else {
+ if d.mtr {
+ rvn = reflect.New(d.h.MapType)
+ d.decode(rv2i(rvn))
+ rvn = rvn.Elem()
+ } else {
+ rvn = reflect.New(d.h.MapType).Elem()
+ d.decodeValue(rvn, nil, true)
+ }
+ }
+ case valueTypeArray:
+ if d.stid == 0 || d.stid == intfSliceTypId {
+ n.initContainers()
+ if n.ls < arrayCacheLen {
+ n.sa[n.ls] = nil
+ rvn = n.rsa[n.ls]
+ n.ls++
+ d.decode(&n.sa[n.ls-1])
+ n.ls--
+ } else {
+ var v2 []interface{}
+ d.decode(&v2)
+ rvn = reflect.ValueOf(&v2).Elem()
+ }
+ if reflectArrayOfSupported && d.stid == 0 && d.h.PreferArrayOverSlice {
+ rvn2 := reflect.New(reflectArrayOf(rvn.Len(), intfTyp)).Elem()
+ reflect.Copy(rvn2, rvn)
+ rvn = rvn2
+ }
+ } else {
+ if d.str {
+ rvn = reflect.New(d.h.SliceType)
+ d.decode(rv2i(rvn))
+ rvn = rvn.Elem()
+ } else {
+ rvn = reflect.New(d.h.SliceType).Elem()
+ d.decodeValue(rvn, nil, true)
+ }
+ }
+ case valueTypeExt:
+ var v interface{}
+ tag, bytes := n.u, n.l // calling decode below might taint the values
+ if bytes == nil {
+ n.initContainers()
+ if n.li < arrayCacheLen {
+ n.ia[n.li] = nil
+ n.li++
+ d.decode(&n.ia[n.li-1])
+ // v = *(&n.ia[l])
+ n.li--
+ v = n.ia[n.li]
+ n.ia[n.li] = nil
+ } else {
+ d.decode(&v)
+ }
+ }
+ bfn := d.h.getExtForTag(tag)
+ if bfn == nil {
+ var re RawExt
+ re.Tag = tag
+ re.Data = detachZeroCopyBytes(d.bytes, nil, bytes)
+ re.Value = v
+ rvn = reflect.ValueOf(&re).Elem()
+ } else {
+ rvnA := reflect.New(bfn.rt)
+ if bytes != nil {
+ bfn.ext.ReadExt(rv2i(rvnA), bytes)
+ } else {
+ bfn.ext.UpdateExt(rv2i(rvnA), v)
+ }
+ rvn = rvnA.Elem()
+ }
+ case valueTypeNil:
+ // no-op
+ case valueTypeInt:
+ rvn = n.ri
+ case valueTypeUint:
+ rvn = n.ru
+ case valueTypeFloat:
+ rvn = n.rf
+ case valueTypeBool:
+ rvn = n.rb
+ case valueTypeString, valueTypeSymbol:
+ rvn = n.rs
+ case valueTypeBytes:
+ rvn = n.rl
+ case valueTypeTime:
+ rvn = n.rt
+ default:
+ panicv.errorf("kInterfaceNaked: unexpected valueType: %d", n.v)
+ }
+ return
+}
+
+func (d *Decoder) kInterface(f *codecFnInfo, rv reflect.Value) {
+ // Note:
+ // A consequence of how kInterface works, is that
+ // if an interface already contains something, we try
+ // to decode into what was there before.
+ // We do not replace with a generic value (as got from decodeNaked).
+
+ // every interface passed here MUST be settable.
+ var rvn reflect.Value
+ if rv.IsNil() || d.h.InterfaceReset {
+ // check if mapping to a type: if so, initialize it and move on
+ rvn = d.h.intf2impl(f.ti.rtid)
+ if rvn.IsValid() {
+ rv.Set(rvn)
+ } else {
+ rvn = d.kInterfaceNaked(f)
+ if rvn.IsValid() {
+ rv.Set(rvn)
+ } else if d.h.InterfaceReset {
+ // reset to zero value based on current type in there.
+ rv.Set(reflect.Zero(rv.Elem().Type()))
+ }
+ return
+ }
+ } else {
+ // now we have a non-nil interface value, meaning it contains a type
+ rvn = rv.Elem()
+ }
+ if d.d.TryDecodeAsNil() {
+ rv.Set(reflect.Zero(rvn.Type()))
+ return
+ }
+
+ // Note: interface{} is settable, but underlying type may not be.
+ // Consequently, we MAY have to create a decodable value out of the underlying value,
+ // decode into it, and reset the interface itself.
+ // fmt.Printf(">>>> kInterface: rvn type: %v, rv type: %v\n", rvn.Type(), rv.Type())
+
+ rvn2, canDecode := isDecodeable(rvn)
+ if canDecode {
+ d.decodeValue(rvn2, nil, true)
+ return
+ }
+
+ rvn2 = reflect.New(rvn.Type()).Elem()
+ rvn2.Set(rvn)
+ d.decodeValue(rvn2, nil, true)
+ rv.Set(rvn2)
+}
+
+func decStructFieldKey(dd decDriver, keyType valueType, b *[decScratchByteArrayLen]byte) (rvkencname []byte) {
+ // use if-else-if, not switch (which compiles to binary-search)
+ // since keyType is typically valueTypeString, branch prediction is pretty good.
+
+ if keyType == valueTypeString {
+ rvkencname = dd.DecodeStringAsBytes()
+ } else if keyType == valueTypeInt {
+ rvkencname = strconv.AppendInt(b[:0], dd.DecodeInt64(), 10)
+ } else if keyType == valueTypeUint {
+ rvkencname = strconv.AppendUint(b[:0], dd.DecodeUint64(), 10)
+ } else if keyType == valueTypeFloat {
+ rvkencname = strconv.AppendFloat(b[:0], dd.DecodeFloat64(), 'f', -1, 64)
+ } else {
+ rvkencname = dd.DecodeStringAsBytes()
+ }
+ return rvkencname
+}
+
+func (d *Decoder) kStruct(f *codecFnInfo, rv reflect.Value) {
+ fti := f.ti
+ dd := d.d
+ elemsep := d.esep
+ sfn := structFieldNode{v: rv, update: true}
+ ctyp := dd.ContainerType()
+ if ctyp == valueTypeMap {
+ containerLen := dd.ReadMapStart()
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return
+ }
+ tisfi := fti.sfiSort
+ hasLen := containerLen >= 0
+
+ var rvkencname []byte
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if elemsep {
+ dd.ReadMapElemKey()
+ }
+ rvkencname = decStructFieldKey(dd, fti.keyType, &d.b)
+ if elemsep {
+ dd.ReadMapElemValue()
+ }
+ if k := fti.indexForEncName(rvkencname); k > -1 {
+ si := tisfi[k]
+ if dd.TryDecodeAsNil() {
+ si.setToZeroValue(rv)
+ } else {
+ d.decodeValue(sfn.field(si), nil, true)
+ }
+ } else {
+ d.structFieldNotFound(-1, stringView(rvkencname))
+ }
+ // keepAlive4StringView(rvkencnameB) // not needed, as reference is outside loop
+ }
+ dd.ReadMapEnd()
+ } else if ctyp == valueTypeArray {
+ containerLen := dd.ReadArrayStart()
+ if containerLen == 0 {
+ dd.ReadArrayEnd()
+ return
+ }
+ // Not much gain from doing it two ways for array.
+ // Arrays are not used as much for structs.
+ hasLen := containerLen >= 0
+ for j, si := range fti.sfiSrc {
+ if (hasLen && j == containerLen) || (!hasLen && dd.CheckBreak()) {
+ break
+ }
+ if elemsep {
+ dd.ReadArrayElem()
+ }
+ if dd.TryDecodeAsNil() {
+ si.setToZeroValue(rv)
+ } else {
+ d.decodeValue(sfn.field(si), nil, true)
+ }
+ }
+ if containerLen > len(fti.sfiSrc) {
+ // read remaining values and throw away
+ for j := len(fti.sfiSrc); j < containerLen; j++ {
+ if elemsep {
+ dd.ReadArrayElem()
+ }
+ d.structFieldNotFound(j, "")
+ }
+ }
+ dd.ReadArrayEnd()
+ } else {
+ d.errorstr(errstrOnlyMapOrArrayCanDecodeIntoStruct)
+ return
+ }
+}
+
+func (d *Decoder) kSlice(f *codecFnInfo, rv reflect.Value) {
+ // A slice can be set from a map or array in stream.
+ // This way, the order can be kept (as order is lost with map).
+ ti := f.ti
+ if f.seq == seqTypeChan && ti.chandir&uint8(reflect.SendDir) == 0 {
+ d.errorf("receive-only channel cannot be decoded")
+ }
+ dd := d.d
+ rtelem0 := ti.elem
+ ctyp := dd.ContainerType()
+ if ctyp == valueTypeBytes || ctyp == valueTypeString {
+ // you can only decode bytes or string in the stream into a slice or array of bytes
+ if !(ti.rtid == uint8SliceTypId || rtelem0.Kind() == reflect.Uint8) {
+ d.errorf("bytes/string in stream must decode into slice/array of bytes, not %v", ti.rt)
+ }
+ if f.seq == seqTypeChan {
+ bs2 := dd.DecodeBytes(nil, true)
+ irv := rv2i(rv)
+ ch, ok := irv.(chan<- byte)
+ if !ok {
+ ch = irv.(chan byte)
+ }
+ for _, b := range bs2 {
+ ch <- b
+ }
+ } else {
+ rvbs := rv.Bytes()
+ bs2 := dd.DecodeBytes(rvbs, false)
+ // if rvbs == nil && bs2 != nil || rvbs != nil && bs2 == nil || len(bs2) != len(rvbs) {
+ if !(len(bs2) > 0 && len(bs2) == len(rvbs) && &bs2[0] == &rvbs[0]) {
+ if rv.CanSet() {
+ rv.SetBytes(bs2)
+ } else if len(rvbs) > 0 && len(bs2) > 0 {
+ copy(rvbs, bs2)
+ }
+ }
+ }
+ return
+ }
+
+ // array := f.seq == seqTypeChan
+
+ slh, containerLenS := d.decSliceHelperStart() // only expects valueType(Array|Map)
+
+ // an array can never return a nil slice. so no need to check f.array here.
+ if containerLenS == 0 {
+ if rv.CanSet() {
+ if f.seq == seqTypeSlice {
+ if rv.IsNil() {
+ rv.Set(reflect.MakeSlice(ti.rt, 0, 0))
+ } else {
+ rv.SetLen(0)
+ }
+ } else if f.seq == seqTypeChan {
+ if rv.IsNil() {
+ rv.Set(reflect.MakeChan(ti.rt, 0))
+ }
+ }
+ }
+ slh.End()
+ return
+ }
+
+ rtelem0Size := int(rtelem0.Size())
+ rtElem0Kind := rtelem0.Kind()
+ rtelem0Mut := !isImmutableKind(rtElem0Kind)
+ rtelem := rtelem0
+ rtelemkind := rtelem.Kind()
+ for rtelemkind == reflect.Ptr {
+ rtelem = rtelem.Elem()
+ rtelemkind = rtelem.Kind()
+ }
+
+ var fn *codecFn
+
+ var rvCanset = rv.CanSet()
+ var rvChanged bool
+ var rv0 = rv
+ var rv9 reflect.Value
+
+ rvlen := rv.Len()
+ rvcap := rv.Cap()
+ hasLen := containerLenS > 0
+ if hasLen && f.seq == seqTypeSlice {
+ if containerLenS > rvcap {
+ oldRvlenGtZero := rvlen > 0
+ rvlen = decInferLen(containerLenS, d.h.MaxInitLen, int(rtelem0.Size()))
+ if rvlen <= rvcap {
+ if rvCanset {
+ rv.SetLen(rvlen)
+ }
+ } else if rvCanset {
+ rv = reflect.MakeSlice(ti.rt, rvlen, rvlen)
+ rvcap = rvlen
+ rvChanged = true
+ } else {
+ d.errorf("cannot decode into non-settable slice")
+ }
+ if rvChanged && oldRvlenGtZero && !isImmutableKind(rtelem0.Kind()) {
+ reflect.Copy(rv, rv0) // only copy up to length NOT cap i.e. rv0.Slice(0, rvcap)
+ }
+ } else if containerLenS != rvlen {
+ rvlen = containerLenS
+ if rvCanset {
+ rv.SetLen(rvlen)
+ }
+ // else {
+ // rv = rv.Slice(0, rvlen)
+ // rvChanged = true
+ // d.errorf("cannot decode into non-settable slice")
+ // }
+ }
+ }
+
+ // consider creating new element once, and just decoding into it.
+ var rtelem0Zero reflect.Value
+ var rtelem0ZeroValid bool
+ var decodeAsNil bool
+ var j int
+ d.cfer()
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && (f.seq == seqTypeSlice || f.seq == seqTypeChan) && rv.IsNil() {
+ if hasLen {
+ rvlen = decInferLen(containerLenS, d.h.MaxInitLen, rtelem0Size)
+ } else if f.seq == seqTypeSlice {
+ rvlen = decDefSliceCap
+ } else {
+ rvlen = decDefChanCap
+ }
+ if rvCanset {
+ if f.seq == seqTypeSlice {
+ rv = reflect.MakeSlice(ti.rt, rvlen, rvlen)
+ rvChanged = true
+ } else { // chan
+ // xdebugf(">>>>>> haslen = %v, make chan of type '%v' with length: %v", hasLen, ti.rt, rvlen)
+ rv = reflect.MakeChan(ti.rt, rvlen)
+ rvChanged = true
+ }
+ } else {
+ d.errorf("cannot decode into non-settable slice")
+ }
+ }
+ slh.ElemContainerState(j)
+ decodeAsNil = dd.TryDecodeAsNil()
+ if f.seq == seqTypeChan {
+ if decodeAsNil {
+ rv.Send(reflect.Zero(rtelem0))
+ continue
+ }
+ if rtelem0Mut || !rv9.IsValid() { // || (rtElem0Kind == reflect.Ptr && rv9.IsNil()) {
+ rv9 = reflect.New(rtelem0).Elem()
+ }
+ if fn == nil {
+ fn = d.cf.get(rtelem, true, true)
+ }
+ d.decodeValue(rv9, fn, true)
+ // xdebugf(">>>> rv9 sent on %v during decode: %v, with len=%v, cap=%v", rv.Type(), rv9, rv.Len(), rv.Cap())
+ rv.Send(rv9)
+ } else {
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= rvlen {
+ if f.seq == seqTypeArray {
+ d.arrayCannotExpand(rvlen, j+1)
+ decodeIntoBlank = true
+ } else { // if f.seq == seqTypeSlice
+ // rv = reflect.Append(rv, reflect.Zero(rtelem0)) // append logic + varargs
+ var rvcap2 int
+ var rvErrmsg2 string
+ rv9, rvcap2, rvChanged, rvErrmsg2 =
+ expandSliceRV(rv, ti.rt, rvCanset, rtelem0Size, 1, rvlen, rvcap)
+ if rvErrmsg2 != "" {
+ d.errorf(rvErrmsg2)
+ }
+ rvlen++
+ if rvChanged {
+ rv = rv9
+ rvcap = rvcap2
+ }
+ }
+ }
+ if decodeIntoBlank {
+ if !decodeAsNil {
+ d.swallow()
+ }
+ } else {
+ rv9 = rv.Index(j)
+ if d.h.SliceElementReset || decodeAsNil {
+ if !rtelem0ZeroValid {
+ rtelem0ZeroValid = true
+ rtelem0Zero = reflect.Zero(rtelem0)
+ }
+ rv9.Set(rtelem0Zero)
+ }
+ if decodeAsNil {
+ continue
+ }
+
+ if fn == nil {
+ fn = d.cf.get(rtelem, true, true)
+ }
+ d.decodeValue(rv9, fn, true)
+ }
+ }
+ }
+ if f.seq == seqTypeSlice {
+ if j < rvlen {
+ if rv.CanSet() {
+ rv.SetLen(j)
+ } else if rvCanset {
+ rv = rv.Slice(0, j)
+ rvChanged = true
+ } // else { d.errorf("kSlice: cannot change non-settable slice") }
+ rvlen = j
+ } else if j == 0 && rv.IsNil() {
+ if rvCanset {
+ rv = reflect.MakeSlice(ti.rt, 0, 0)
+ rvChanged = true
+ } // else { d.errorf("kSlice: cannot change non-settable slice") }
+ }
+ }
+ slh.End()
+
+ if rvChanged { // infers rvCanset=true, so it can be reset
+ rv0.Set(rv)
+ }
+}
+
+// func (d *Decoder) kArray(f *codecFnInfo, rv reflect.Value) {
+// // d.decodeValueFn(rv.Slice(0, rv.Len()))
+// f.kSlice(rv.Slice(0, rv.Len()))
+// }
+
+func (d *Decoder) kMap(f *codecFnInfo, rv reflect.Value) {
+ dd := d.d
+ containerLen := dd.ReadMapStart()
+ elemsep := d.esep
+ ti := f.ti
+ if rv.IsNil() {
+ rv.Set(makeMapReflect(ti.rt, containerLen))
+ }
+
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return
+ }
+
+ ktype, vtype := ti.key, ti.elem
+ ktypeId := rt2id(ktype)
+ vtypeKind := vtype.Kind()
+
+ var keyFn, valFn *codecFn
+ var ktypeLo, vtypeLo reflect.Type
+
+ for ktypeLo = ktype; ktypeLo.Kind() == reflect.Ptr; ktypeLo = ktypeLo.Elem() {
+ }
+
+ for vtypeLo = vtype; vtypeLo.Kind() == reflect.Ptr; vtypeLo = vtypeLo.Elem() {
+ }
+
+ var mapGet, mapSet bool
+ rvvImmut := isImmutableKind(vtypeKind)
+ if !d.h.MapValueReset {
+ // if pointer, mapGet = true
+ // if interface, mapGet = true if !DecodeNakedAlways (else false)
+ // if builtin, mapGet = false
+ // else mapGet = true
+ if vtypeKind == reflect.Ptr {
+ mapGet = true
+ } else if vtypeKind == reflect.Interface {
+ if !d.h.InterfaceReset {
+ mapGet = true
+ }
+ } else if !rvvImmut {
+ mapGet = true
+ }
+ }
+
+ var rvk, rvkp, rvv, rvz reflect.Value
+ rvkMut := !isImmutableKind(ktype.Kind()) // if ktype is immutable, then re-use the same rvk.
+ ktypeIsString := ktypeId == stringTypId
+ ktypeIsIntf := ktypeId == intfTypId
+ hasLen := containerLen > 0
+ var kstrbs []byte
+ d.cfer()
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if rvkMut || !rvkp.IsValid() {
+ rvkp = reflect.New(ktype)
+ rvk = rvkp.Elem()
+ }
+ if elemsep {
+ dd.ReadMapElemKey()
+ }
+ if false && dd.TryDecodeAsNil() { // nil cannot be a map key, so disregard this block
+ // Previously, if a nil key, we just ignored the mapped value and continued.
+ // However, that makes the result of encoding and then decoding map[intf]intf{nil:nil}
+ // to be an empty map.
+ // Instead, we treat a nil key as the zero value of the type.
+ rvk.Set(reflect.Zero(ktype))
+ } else if ktypeIsString {
+ kstrbs = dd.DecodeStringAsBytes()
+ rvk.SetString(stringView(kstrbs))
+ // NOTE: if doing an insert, you MUST use a real string (not stringview)
+ } else {
+ if keyFn == nil {
+ keyFn = d.cf.get(ktypeLo, true, true)
+ }
+ d.decodeValue(rvk, keyFn, true)
+ }
+ // special case if a byte array.
+ if ktypeIsIntf {
+ if rvk2 := rvk.Elem(); rvk2.IsValid() {
+ if rvk2.Type() == uint8SliceTyp {
+ rvk = reflect.ValueOf(d.string(rvk2.Bytes()))
+ } else {
+ rvk = rvk2
+ }
+ }
+ }
+
+ if elemsep {
+ dd.ReadMapElemValue()
+ }
+
+ // Brittle, but OK per TryDecodeAsNil() contract.
+ // i.e. TryDecodeAsNil never shares slices with other decDriver procedures
+ if dd.TryDecodeAsNil() {
+ if ktypeIsString {
+ rvk.SetString(d.string(kstrbs))
+ }
+ if d.h.DeleteOnNilMapValue {
+ rv.SetMapIndex(rvk, reflect.Value{})
+ } else {
+ rv.SetMapIndex(rvk, reflect.Zero(vtype))
+ }
+ continue
+ }
+
+ mapSet = true // set to false if u do a get, and its a non-nil pointer
+ if mapGet {
+ // mapGet true only in case where kind=Ptr|Interface or kind is otherwise mutable.
+ rvv = rv.MapIndex(rvk)
+ if !rvv.IsValid() {
+ rvv = reflect.New(vtype).Elem()
+ } else if vtypeKind == reflect.Ptr {
+ if rvv.IsNil() {
+ rvv = reflect.New(vtype).Elem()
+ } else {
+ mapSet = false
+ }
+ } else if vtypeKind == reflect.Interface {
+ // not addressable, and thus not settable.
+ // e MUST create a settable/addressable variant
+ rvv2 := reflect.New(rvv.Type()).Elem()
+ if !rvv.IsNil() {
+ rvv2.Set(rvv)
+ }
+ rvv = rvv2
+ }
+ // else it is ~mutable, and we can just decode into it directly
+ } else if rvvImmut {
+ if !rvz.IsValid() {
+ rvz = reflect.New(vtype).Elem()
+ }
+ rvv = rvz
+ } else {
+ rvv = reflect.New(vtype).Elem()
+ }
+
+ // We MUST be done with the stringview of the key, before decoding the value
+ // so that we don't bastardize the reused byte array.
+ if mapSet && ktypeIsString {
+ rvk.SetString(d.string(kstrbs))
+ }
+ if valFn == nil {
+ valFn = d.cf.get(vtypeLo, true, true)
+ }
+ d.decodeValue(rvv, valFn, true)
+ // d.decodeValueFn(rvv, valFn)
+ if mapSet {
+ rv.SetMapIndex(rvk, rvv)
+ }
+ // if ktypeIsString {
+ // // keepAlive4StringView(kstrbs) // not needed, as reference is outside loop
+ // }
+ }
+
+ dd.ReadMapEnd()
+}
+
+// decNaked is used to keep track of the primitives decoded.
+// Without it, we would have to decode each primitive and wrap it
+// in an interface{}, causing an allocation.
+// In this model, the primitives are decoded in a "pseudo-atomic" fashion,
+// so we can rest assured that no other decoding happens while these
+// primitives are being decoded.
+//
+// maps and arrays are not handled by this mechanism.
+// However, RawExt is, and we accommodate for extensions that decode
+// RawExt from DecodeNaked, but need to decode the value subsequently.
+// kInterfaceNaked and swallow, which call DecodeNaked, handle this caveat.
+//
+// However, decNaked also keeps some arrays of default maps and slices
+// used in DecodeNaked. This way, we can get a pointer to it
+// without causing a new heap allocation.
+//
+// kInterfaceNaked will ensure that there is no allocation for the common
+// uses.
+
+type decNakedContainers struct {
+ // array/stacks for reducing allocation
+ // keep arrays at the bottom? Chance is that they are not used much.
+ ia [arrayCacheLen]interface{}
+ ma [arrayCacheLen]map[interface{}]interface{}
+ na [arrayCacheLen]map[string]interface{}
+ sa [arrayCacheLen][]interface{}
+
+ // ria [arrayCacheLen]reflect.Value // not needed, as we decode directly into &ia[n]
+ rma, rna, rsa [arrayCacheLen]reflect.Value // reflect.Value mapping to above
+}
+
+func (n *decNakedContainers) init() {
+ for i := 0; i < arrayCacheLen; i++ {
+ // n.ria[i] = reflect.ValueOf(&(n.ia[i])).Elem()
+ n.rma[i] = reflect.ValueOf(&(n.ma[i])).Elem()
+ n.rna[i] = reflect.ValueOf(&(n.na[i])).Elem()
+ n.rsa[i] = reflect.ValueOf(&(n.sa[i])).Elem()
+ }
+}
+
+type decNaked struct {
+ // r RawExt // used for RawExt, uint, []byte.
+
+ // primitives below
+ u uint64
+ i int64
+ f float64
+ l []byte
+ s string
+
+ // ---- cpu cache line boundary?
+ t time.Time
+ b bool
+
+ // state
+ v valueType
+ li, lm, ln, ls int8
+ inited bool
+
+ *decNakedContainers
+
+ ru, ri, rf, rl, rs, rb, rt reflect.Value // mapping to the primitives above
+
+ // _ [6]uint64 // padding // no padding - rt goes into next cache line
+}
+
+func (n *decNaked) init() {
+ if n.inited {
+ return
+ }
+ n.ru = reflect.ValueOf(&n.u).Elem()
+ n.ri = reflect.ValueOf(&n.i).Elem()
+ n.rf = reflect.ValueOf(&n.f).Elem()
+ n.rl = reflect.ValueOf(&n.l).Elem()
+ n.rs = reflect.ValueOf(&n.s).Elem()
+ n.rt = reflect.ValueOf(&n.t).Elem()
+ n.rb = reflect.ValueOf(&n.b).Elem()
+
+ n.inited = true
+ // n.rr[] = reflect.ValueOf(&n.)
+}
+
+func (n *decNaked) initContainers() {
+ if n.decNakedContainers == nil {
+ n.decNakedContainers = new(decNakedContainers)
+ n.decNakedContainers.init()
+ }
+}
+
+func (n *decNaked) reset() {
+ if n == nil {
+ return
+ }
+ n.li, n.lm, n.ln, n.ls = 0, 0, 0, 0
+}
+
+type rtid2rv struct {
+ rtid uintptr
+ rv reflect.Value
+}
+
+// --------------
+
+type decReaderSwitch struct {
+ rb bytesDecReader
+ // ---- cpu cache line boundary?
+ ri *ioDecReader
+ mtr, str bool // whether maptype or slicetype are known types
+
+ be bool // is binary encoding
+ bytes bool // is bytes reader
+ js bool // is json handle
+ jsms bool // is json handle, and MapKeyAsString
+ esep bool // has elem separators
+}
+
+// TODO: Uncomment after mid-stack inlining enabled in go 1.11
+//
+// func (z *decReaderSwitch) unreadn1() {
+// if z.bytes {
+// z.rb.unreadn1()
+// } else {
+// z.ri.unreadn1()
+// }
+// }
+// func (z *decReaderSwitch) readx(n int) []byte {
+// if z.bytes {
+// return z.rb.readx(n)
+// }
+// return z.ri.readx(n)
+// }
+// func (z *decReaderSwitch) readb(s []byte) {
+// if z.bytes {
+// z.rb.readb(s)
+// } else {
+// z.ri.readb(s)
+// }
+// }
+// func (z *decReaderSwitch) readn1() uint8 {
+// if z.bytes {
+// return z.rb.readn1()
+// }
+// return z.ri.readn1()
+// }
+// func (z *decReaderSwitch) numread() int {
+// if z.bytes {
+// return z.rb.numread()
+// }
+// return z.ri.numread()
+// }
+// func (z *decReaderSwitch) track() {
+// if z.bytes {
+// z.rb.track()
+// } else {
+// z.ri.track()
+// }
+// }
+// func (z *decReaderSwitch) stopTrack() []byte {
+// if z.bytes {
+// return z.rb.stopTrack()
+// }
+// return z.ri.stopTrack()
+// }
+// func (z *decReaderSwitch) skip(accept *bitset256) (token byte) {
+// if z.bytes {
+// return z.rb.skip(accept)
+// }
+// return z.ri.skip(accept)
+// }
+// func (z *decReaderSwitch) readTo(in []byte, accept *bitset256) (out []byte) {
+// if z.bytes {
+// return z.rb.readTo(in, accept)
+// }
+// return z.ri.readTo(in, accept)
+// }
+// func (z *decReaderSwitch) readUntil(in []byte, stop byte) (out []byte) {
+// if z.bytes {
+// return z.rb.readUntil(in, stop)
+// }
+// return z.ri.readUntil(in, stop)
+// }
+
+// A Decoder reads and decodes an object from an input stream in the codec format.
+type Decoder struct {
+ panicHdl
+ // hopefully, reduce derefencing cost by laying the decReader inside the Decoder.
+ // Try to put things that go together to fit within a cache line (8 words).
+
+ d decDriver
+ // NOTE: Decoder shouldn't call it's read methods,
+ // as the handler MAY need to do some coordination.
+ r decReader
+ h *BasicHandle
+ bi *bufioDecReader
+ // cache the mapTypeId and sliceTypeId for faster comparisons
+ mtid uintptr
+ stid uintptr
+
+ // ---- cpu cache line boundary?
+ decReaderSwitch
+
+ // ---- cpu cache line boundary?
+ codecFnPooler
+ // cr containerStateRecv
+ n *decNaked
+ nsp *sync.Pool
+ err error
+
+ // ---- cpu cache line boundary?
+ b [decScratchByteArrayLen]byte // scratch buffer, used by Decoder and xxxEncDrivers
+ is map[string]string // used for interning strings
+
+ // padding - false sharing help // modify 232 if Decoder struct changes.
+ // _ [cacheLineSize - 232%cacheLineSize]byte
+}
+
+// NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader.
+//
+// For efficiency, Users are encouraged to pass in a memory buffered reader
+// (eg bufio.Reader, bytes.Buffer).
+func NewDecoder(r io.Reader, h Handle) *Decoder {
+ d := newDecoder(h)
+ d.Reset(r)
+ return d
+}
+
+// NewDecoderBytes returns a Decoder which efficiently decodes directly
+// from a byte slice with zero copying.
+func NewDecoderBytes(in []byte, h Handle) *Decoder {
+ d := newDecoder(h)
+ d.ResetBytes(in)
+ return d
+}
+
+var defaultDecNaked decNaked
+
+func newDecoder(h Handle) *Decoder {
+ d := &Decoder{h: h.getBasicHandle(), err: errDecoderNotInitialized}
+ d.hh = h
+ d.be = h.isBinary()
+ // NOTE: do not initialize d.n here. It is lazily initialized in d.naked()
+ var jh *JsonHandle
+ jh, d.js = h.(*JsonHandle)
+ if d.js {
+ d.jsms = jh.MapKeyAsString
+ }
+ d.esep = d.hh.hasElemSeparators()
+ if d.h.InternString {
+ d.is = make(map[string]string, 32)
+ }
+ d.d = h.newDecDriver(d)
+ // d.cr, _ = d.d.(containerStateRecv)
+ return d
+}
+
+func (d *Decoder) resetCommon() {
+ d.n.reset()
+ d.d.reset()
+ d.err = nil
+ // reset all things which were cached from the Handle, but could change
+ d.mtid, d.stid = 0, 0
+ d.mtr, d.str = false, false
+ if d.h.MapType != nil {
+ d.mtid = rt2id(d.h.MapType)
+ d.mtr = fastpathAV.index(d.mtid) != -1
+ }
+ if d.h.SliceType != nil {
+ d.stid = rt2id(d.h.SliceType)
+ d.str = fastpathAV.index(d.stid) != -1
+ }
+}
+
+// Reset the Decoder with a new Reader to decode from,
+// clearing all state from last run(s).
+func (d *Decoder) Reset(r io.Reader) {
+ if r == nil {
+ return
+ }
+ if d.bi == nil {
+ d.bi = new(bufioDecReader)
+ }
+ d.bytes = false
+ if d.h.ReaderBufferSize > 0 {
+ d.bi.buf = make([]byte, 0, d.h.ReaderBufferSize)
+ d.bi.reset(r)
+ d.r = d.bi
+ } else {
+ // d.ri.x = &d.b
+ // d.s = d.sa[:0]
+ if d.ri == nil {
+ d.ri = new(ioDecReader)
+ }
+ d.ri.reset(r)
+ d.r = d.ri
+ }
+ d.resetCommon()
+}
+
+// ResetBytes resets the Decoder with a new []byte to decode from,
+// clearing all state from last run(s).
+func (d *Decoder) ResetBytes(in []byte) {
+ if in == nil {
+ return
+ }
+ d.bytes = true
+ d.rb.reset(in)
+ d.r = &d.rb
+ d.resetCommon()
+}
+
+// naked must be called before each call to .DecodeNaked,
+// as they will use it.
+func (d *Decoder) naked() *decNaked {
+ if d.n == nil {
+ // consider one of:
+ // - get from sync.Pool (if GC is frequent, there's no value here)
+ // - new alloc (safest. only init'ed if it a naked decode will be done)
+ // - field in Decoder (makes the Decoder struct very big)
+ // To support using a decoder where a DecodeNaked is not needed,
+ // we prefer #1 or #2.
+ // d.n = new(decNaked) // &d.nv // new(decNaked) // grab from a sync.Pool
+ // d.n.init()
+ var v interface{}
+ d.nsp, v = pool.decNaked()
+ d.n = v.(*decNaked)
+ }
+ return d.n
+}
+
+// Decode decodes the stream from reader and stores the result in the
+// value pointed to by v. v cannot be a nil pointer. v can also be
+// a reflect.Value of a pointer.
+//
+// Note that a pointer to a nil interface is not a nil pointer.
+// If you do not know what type of stream it is, pass in a pointer to a nil interface.
+// We will decode and store a value in that nil interface.
+//
+// Sample usages:
+// // Decoding into a non-nil typed value
+// var f float32
+// err = codec.NewDecoder(r, handle).Decode(&f)
+//
+// // Decoding into nil interface
+// var v interface{}
+// dec := codec.NewDecoder(r, handle)
+// err = dec.Decode(&v)
+//
+// When decoding into a nil interface{}, we will decode into an appropriate value based
+// on the contents of the stream:
+// - Numbers are decoded as float64, int64 or uint64.
+// - Other values are decoded appropriately depending on the type:
+// bool, string, []byte, time.Time, etc
+// - Extensions are decoded as RawExt (if no ext function registered for the tag)
+// Configurations exist on the Handle to override defaults
+// (e.g. for MapType, SliceType and how to decode raw bytes).
+//
+// When decoding into a non-nil interface{} value, the mode of encoding is based on the
+// type of the value. When a value is seen:
+// - If an extension is registered for it, call that extension function
+// - If it implements BinaryUnmarshaler, call its UnmarshalBinary(data []byte) error
+// - Else decode it based on its reflect.Kind
+//
+// There are some special rules when decoding into containers (slice/array/map/struct).
+// Decode will typically use the stream contents to UPDATE the container.
+// - A map can be decoded from a stream map, by updating matching keys.
+// - A slice can be decoded from a stream array,
+// by updating the first n elements, where n is length of the stream.
+// - A slice can be decoded from a stream map, by decoding as if
+// it contains a sequence of key-value pairs.
+// - A struct can be decoded from a stream map, by updating matching fields.
+// - A struct can be decoded from a stream array,
+// by updating fields as they occur in the struct (by index).
+//
+// When decoding a stream map or array with length of 0 into a nil map or slice,
+// we reset the destination map or slice to a zero-length value.
+//
+// However, when decoding a stream nil, we reset the destination container
+// to its "zero" value (e.g. nil for slice/map, etc).
+//
+// Note: we allow nil values in the stream anywhere except for map keys.
+// A nil value in the encoded stream where a map key is expected is treated as an error.
+func (d *Decoder) Decode(v interface{}) (err error) {
+ defer d.deferred(&err)
+ d.MustDecode(v)
+ return
+}
+
+// MustDecode is like Decode, but panics if unable to Decode.
+// This provides insight to the code location that triggered the error.
+func (d *Decoder) MustDecode(v interface{}) {
+ // TODO: Top-level: ensure that v is a pointer and not nil.
+ if d.err != nil {
+ panic(d.err)
+ }
+ if d.d.TryDecodeAsNil() {
+ setZero(v)
+ } else {
+ d.decode(v)
+ }
+ d.alwaysAtEnd()
+ // xprintf(">>>>>>>> >>>>>>>> num decFns: %v\n", d.cf.sn)
+}
+
+func (d *Decoder) deferred(err1 *error) {
+ d.alwaysAtEnd()
+ if recoverPanicToErr {
+ if x := recover(); x != nil {
+ panicValToErr(d, x, err1)
+ panicValToErr(d, x, &d.err)
+ }
+ }
+}
+
+func (d *Decoder) alwaysAtEnd() {
+ if d.n != nil {
+ // if n != nil, then nsp != nil (they are always set together)
+ d.nsp.Put(d.n)
+ d.n, d.nsp = nil, nil
+ }
+ d.codecFnPooler.alwaysAtEnd()
+}
+
+// // this is not a smart swallow, as it allocates objects and does unnecessary work.
+// func (d *Decoder) swallowViaHammer() {
+// var blank interface{}
+// d.decodeValueNoFn(reflect.ValueOf(&blank).Elem())
+// }
+
+func (d *Decoder) swallow() {
+ // smarter decode that just swallows the content
+ dd := d.d
+ if dd.TryDecodeAsNil() {
+ return
+ }
+ elemsep := d.esep
+ switch dd.ContainerType() {
+ case valueTypeMap:
+ containerLen := dd.ReadMapStart()
+ hasLen := containerLen >= 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ // if clenGtEqualZero {if j >= containerLen {break} } else if dd.CheckBreak() {break}
+ if elemsep {
+ dd.ReadMapElemKey()
+ }
+ d.swallow()
+ if elemsep {
+ dd.ReadMapElemValue()
+ }
+ d.swallow()
+ }
+ dd.ReadMapEnd()
+ case valueTypeArray:
+ containerLen := dd.ReadArrayStart()
+ hasLen := containerLen >= 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if elemsep {
+ dd.ReadArrayElem()
+ }
+ d.swallow()
+ }
+ dd.ReadArrayEnd()
+ case valueTypeBytes:
+ dd.DecodeBytes(d.b[:], true)
+ case valueTypeString:
+ dd.DecodeStringAsBytes()
+ default:
+ // these are all primitives, which we can get from decodeNaked
+ // if RawExt using Value, complete the processing.
+ n := d.naked()
+ dd.DecodeNaked()
+ if n.v == valueTypeExt && n.l == nil {
+ n.initContainers()
+ if n.li < arrayCacheLen {
+ n.ia[n.li] = nil
+ n.li++
+ d.decode(&n.ia[n.li-1])
+ n.ia[n.li-1] = nil
+ n.li--
+ } else {
+ var v2 interface{}
+ d.decode(&v2)
+ }
+ }
+ }
+}
+
+func setZero(iv interface{}) {
+ if iv == nil || definitelyNil(iv) {
+ return
+ }
+ var canDecode bool
+ switch v := iv.(type) {
+ case *string:
+ *v = ""
+ case *bool:
+ *v = false
+ case *int:
+ *v = 0
+ case *int8:
+ *v = 0
+ case *int16:
+ *v = 0
+ case *int32:
+ *v = 0
+ case *int64:
+ *v = 0
+ case *uint:
+ *v = 0
+ case *uint8:
+ *v = 0
+ case *uint16:
+ *v = 0
+ case *uint32:
+ *v = 0
+ case *uint64:
+ *v = 0
+ case *float32:
+ *v = 0
+ case *float64:
+ *v = 0
+ case *[]uint8:
+ *v = nil
+ case *Raw:
+ *v = nil
+ case *time.Time:
+ *v = time.Time{}
+ case reflect.Value:
+ if v, canDecode = isDecodeable(v); canDecode && v.CanSet() {
+ v.Set(reflect.Zero(v.Type()))
+ } // TODO: else drain if chan, clear if map, set all to nil if slice???
+ default:
+ if !fastpathDecodeSetZeroTypeSwitch(iv) {
+ v := reflect.ValueOf(iv)
+ if v, canDecode = isDecodeable(v); canDecode && v.CanSet() {
+ v.Set(reflect.Zero(v.Type()))
+ } // TODO: else drain if chan, clear if map, set all to nil if slice???
+ }
+ }
+}
+
+func (d *Decoder) decode(iv interface{}) {
+ // check nil and interfaces explicitly,
+ // so that type switches just have a run of constant non-interface types.
+ if iv == nil {
+ d.errorstr(errstrCannotDecodeIntoNil)
+ return
+ }
+ if v, ok := iv.(Selfer); ok {
+ v.CodecDecodeSelf(d)
+ return
+ }
+
+ switch v := iv.(type) {
+ // case nil:
+ // case Selfer:
+
+ case reflect.Value:
+ v = d.ensureDecodeable(v)
+ d.decodeValue(v, nil, true)
+
+ case *string:
+ *v = d.d.DecodeString()
+ case *bool:
+ *v = d.d.DecodeBool()
+ case *int:
+ *v = int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
+ case *int8:
+ *v = int8(chkOvf.IntV(d.d.DecodeInt64(), 8))
+ case *int16:
+ *v = int16(chkOvf.IntV(d.d.DecodeInt64(), 16))
+ case *int32:
+ *v = int32(chkOvf.IntV(d.d.DecodeInt64(), 32))
+ case *int64:
+ *v = d.d.DecodeInt64()
+ case *uint:
+ *v = uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
+ case *uint8:
+ *v = uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))
+ case *uint16:
+ *v = uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))
+ case *uint32:
+ *v = uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))
+ case *uint64:
+ *v = d.d.DecodeUint64()
+ case *float32:
+ f64 := d.d.DecodeFloat64()
+ if chkOvf.Float32(f64) {
+ d.errorf("float32 overflow: %v", f64)
+ }
+ *v = float32(f64)
+ case *float64:
+ *v = d.d.DecodeFloat64()
+ case *[]uint8:
+ *v = d.d.DecodeBytes(*v, false)
+ case []uint8:
+ b := d.d.DecodeBytes(v, false)
+ if !(len(b) > 0 && len(b) == len(v) && &b[0] == &v[0]) {
+ copy(v, b)
+ }
+ case *time.Time:
+ *v = d.d.DecodeTime()
+ case *Raw:
+ *v = d.rawBytes()
+
+ case *interface{}:
+ d.decodeValue(reflect.ValueOf(iv).Elem(), nil, true)
+ // d.decodeValueNotNil(reflect.ValueOf(iv).Elem())
+
+ default:
+ if !fastpathDecodeTypeSwitch(iv, d) {
+ v := reflect.ValueOf(iv)
+ v = d.ensureDecodeable(v)
+ d.decodeValue(v, nil, false)
+ // d.decodeValueFallback(v)
+ }
+ }
+}
+
+func (d *Decoder) decodeValue(rv reflect.Value, fn *codecFn, chkAll bool) {
+ // If stream is not containing a nil value, then we can deref to the base
+ // non-pointer value, and decode into that.
+ var rvp reflect.Value
+ var rvpValid bool
+ if rv.Kind() == reflect.Ptr {
+ rvpValid = true
+ for {
+ if rv.IsNil() {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ rvp = rv
+ rv = rv.Elem()
+ if rv.Kind() != reflect.Ptr {
+ break
+ }
+ }
+ }
+
+ if fn == nil {
+ // always pass checkCodecSelfer=true, in case T or ****T is passed, where *T is a Selfer
+ fn = d.cfer().get(rv.Type(), chkAll, true) // chkAll, chkAll)
+ }
+ if fn.i.addrD {
+ if rvpValid {
+ fn.fd(d, &fn.i, rvp)
+ } else if rv.CanAddr() {
+ fn.fd(d, &fn.i, rv.Addr())
+ } else if !fn.i.addrF {
+ fn.fd(d, &fn.i, rv)
+ } else {
+ d.errorf("cannot decode into a non-pointer value")
+ }
+ } else {
+ fn.fd(d, &fn.i, rv)
+ }
+ // return rv
+}
+
+func (d *Decoder) structFieldNotFound(index int, rvkencname string) {
+ // NOTE: rvkencname may be a stringView, so don't pass it to another function.
+ if d.h.ErrorIfNoField {
+ if index >= 0 {
+ d.errorf("no matching struct field found when decoding stream array at index %v", index)
+ return
+ } else if rvkencname != "" {
+ d.errorf("no matching struct field found when decoding stream map with key " + rvkencname)
+ return
+ }
+ }
+ d.swallow()
+}
+
+func (d *Decoder) arrayCannotExpand(sliceLen, streamLen int) {
+ if d.h.ErrorIfNoArrayExpand {
+ d.errorf("cannot expand array len during decode from %v to %v", sliceLen, streamLen)
+ }
+}
+
+func isDecodeable(rv reflect.Value) (rv2 reflect.Value, canDecode bool) {
+ switch rv.Kind() {
+ case reflect.Array:
+ return rv, true
+ case reflect.Ptr:
+ if !rv.IsNil() {
+ return rv.Elem(), true
+ }
+ case reflect.Slice, reflect.Chan, reflect.Map:
+ if !rv.IsNil() {
+ return rv, true
+ }
+ }
+ return
+}
+
+func (d *Decoder) ensureDecodeable(rv reflect.Value) (rv2 reflect.Value) {
+ // decode can take any reflect.Value that is a inherently addressable i.e.
+ // - array
+ // - non-nil chan (we will SEND to it)
+ // - non-nil slice (we will set its elements)
+ // - non-nil map (we will put into it)
+ // - non-nil pointer (we can "update" it)
+ rv2, canDecode := isDecodeable(rv)
+ if canDecode {
+ return
+ }
+ if !rv.IsValid() {
+ d.errorstr(errstrCannotDecodeIntoNil)
+ return
+ }
+ if !rv.CanInterface() {
+ d.errorf("cannot decode into a value without an interface: %v", rv)
+ return
+ }
+ rvi := rv2i(rv)
+ rvk := rv.Kind()
+ d.errorf("cannot decode into value of kind: %v, type: %T, %v", rvk, rvi, rvi)
+ return
+}
+
+// Possibly get an interned version of a string
+//
+// This should mostly be used for map keys, where the key type is string.
+// This is because keys of a map/struct are typically reused across many objects.
+func (d *Decoder) string(v []byte) (s string) {
+ if d.is == nil {
+ return string(v) // don't return stringView, as we need a real string here.
+ }
+ s, ok := d.is[string(v)] // no allocation here, per go implementation
+ if !ok {
+ s = string(v) // new allocation here
+ d.is[s] = s
+ }
+ return s
+}
+
+// nextValueBytes returns the next value in the stream as a set of bytes.
+func (d *Decoder) nextValueBytes() (bs []byte) {
+ d.d.uncacheRead()
+ d.r.track()
+ d.swallow()
+ bs = d.r.stopTrack()
+ return
+}
+
+func (d *Decoder) rawBytes() []byte {
+ // ensure that this is not a view into the bytes
+ // i.e. make new copy always.
+ bs := d.nextValueBytes()
+ bs2 := make([]byte, len(bs))
+ copy(bs2, bs)
+ return bs2
+}
+
+func (d *Decoder) wrapErrstr(v interface{}, err *error) {
+ *err = fmt.Errorf("%s decode error [pos %d]: %v", d.hh.Name(), d.r.numread(), v)
+}
+
+// --------------------------------------------------
+
+// decSliceHelper assists when decoding into a slice, from a map or an array in the stream.
+// A slice can be set from a map or array in stream. This supports the MapBySlice interface.
+type decSliceHelper struct {
+ d *Decoder
+ // ct valueType
+ array bool
+}
+
+func (d *Decoder) decSliceHelperStart() (x decSliceHelper, clen int) {
+ dd := d.d
+ ctyp := dd.ContainerType()
+ switch ctyp {
+ case valueTypeArray:
+ x.array = true
+ clen = dd.ReadArrayStart()
+ case valueTypeMap:
+ clen = dd.ReadMapStart() * 2
+ default:
+ d.errorf("only encoded map or array can be decoded into a slice (%d)", ctyp)
+ }
+ // x.ct = ctyp
+ x.d = d
+ return
+}
+
+func (x decSliceHelper) End() {
+ if x.array {
+ x.d.d.ReadArrayEnd()
+ } else {
+ x.d.d.ReadMapEnd()
+ }
+}
+
+func (x decSliceHelper) ElemContainerState(index int) {
+ if x.array {
+ x.d.d.ReadArrayElem()
+ } else if index%2 == 0 {
+ x.d.d.ReadMapElemKey()
+ } else {
+ x.d.d.ReadMapElemValue()
+ }
+}
+
+func decByteSlice(r decReader, clen, maxInitLen int, bs []byte) (bsOut []byte) {
+ if clen == 0 {
+ return zeroByteSlice
+ }
+ if len(bs) == clen {
+ bsOut = bs
+ r.readb(bsOut)
+ } else if cap(bs) >= clen {
+ bsOut = bs[:clen]
+ r.readb(bsOut)
+ } else {
+ // bsOut = make([]byte, clen)
+ len2 := decInferLen(clen, maxInitLen, 1)
+ bsOut = make([]byte, len2)
+ r.readb(bsOut)
+ for len2 < clen {
+ len3 := decInferLen(clen-len2, maxInitLen, 1)
+ bs3 := bsOut
+ bsOut = make([]byte, len2+len3)
+ copy(bsOut, bs3)
+ r.readb(bsOut[len2:])
+ len2 += len3
+ }
+ }
+ return
+}
+
+func detachZeroCopyBytes(isBytesReader bool, dest []byte, in []byte) (out []byte) {
+ if xlen := len(in); xlen > 0 {
+ if isBytesReader || xlen <= scratchByteArrayLen {
+ if cap(dest) >= xlen {
+ out = dest[:xlen]
+ } else {
+ out = make([]byte, xlen)
+ }
+ copy(out, in)
+ return
+ }
+ }
+ return in
+}
+
+// decInferLen will infer a sensible length, given the following:
+// - clen: length wanted.
+// - maxlen: max length to be returned.
+// if <= 0, it is unset, and we infer it based on the unit size
+// - unit: number of bytes for each element of the collection
+func decInferLen(clen, maxlen, unit int) (rvlen int) {
+ // handle when maxlen is not set i.e. <= 0
+ if clen <= 0 {
+ return
+ }
+ if unit == 0 {
+ return clen
+ }
+ if maxlen <= 0 {
+ // no maxlen defined. Use maximum of 256K memory, with a floor of 4K items.
+ // maxlen = 256 * 1024 / unit
+ // if maxlen < (4 * 1024) {
+ // maxlen = 4 * 1024
+ // }
+ if unit < (256 / 4) {
+ maxlen = 256 * 1024 / unit
+ } else {
+ maxlen = 4 * 1024
+ }
+ }
+ if clen > maxlen {
+ rvlen = maxlen
+ } else {
+ rvlen = clen
+ }
+ return
+}
+
+func expandSliceRV(s reflect.Value, st reflect.Type, canChange bool, stElemSize, num, slen, scap int) (
+ s2 reflect.Value, scap2 int, changed bool, err string) {
+ l1 := slen + num // new slice length
+ if l1 < slen {
+ err = errmsgExpandSliceOverflow
+ return
+ }
+ if l1 <= scap {
+ if s.CanSet() {
+ s.SetLen(l1)
+ } else if canChange {
+ s2 = s.Slice(0, l1)
+ scap2 = scap
+ changed = true
+ } else {
+ err = errmsgExpandSliceCannotChange
+ return
+ }
+ return
+ }
+ if !canChange {
+ err = errmsgExpandSliceCannotChange
+ return
+ }
+ scap2 = growCap(scap, stElemSize, num)
+ s2 = reflect.MakeSlice(st, l1, scap2)
+ changed = true
+ reflect.Copy(s2, s)
+ return
+}
+
+func decReadFull(r io.Reader, bs []byte) (n int, err error) {
+ var nn int
+ for n < len(bs) && err == nil {
+ nn, err = r.Read(bs[n:])
+ if nn > 0 {
+ if err == io.EOF {
+ // leave EOF for next time
+ err = nil
+ }
+ n += nn
+ }
+ }
+
+ // do not do this - it serves no purpose
+ // if n != len(bs) && err == io.EOF { err = io.ErrUnexpectedEOF }
+ return
+}
diff --git a/vendor/github.com/ugorji/go/codec/encode.go b/vendor/github.com/ugorji/go/codec/encode.go
new file mode 100644
index 00000000..ef465294
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/encode.go
@@ -0,0 +1,1375 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "bufio"
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "sort"
+ "strconv"
+ "sync"
+ "time"
+)
+
+const defEncByteBufSize = 1 << 6 // 4:16, 6:64, 8:256, 10:1024
+
+var errEncoderNotInitialized = errors.New("Encoder not initialized")
+
+// encWriter abstracts writing to a byte array or to an io.Writer.
+type encWriter interface {
+ writeb([]byte)
+ writestr(string)
+ writen1(byte)
+ writen2(byte, byte)
+ atEndOfEncode()
+}
+
+// encDriver abstracts the actual codec (binc vs msgpack, etc)
+type encDriver interface {
+ EncodeNil()
+ EncodeInt(i int64)
+ EncodeUint(i uint64)
+ EncodeBool(b bool)
+ EncodeFloat32(f float32)
+ EncodeFloat64(f float64)
+ // encodeExtPreamble(xtag byte, length int)
+ EncodeRawExt(re *RawExt, e *Encoder)
+ EncodeExt(v interface{}, xtag uint64, ext Ext, e *Encoder)
+ EncodeString(c charEncoding, v string)
+ // EncodeSymbol(v string)
+ EncodeStringBytes(c charEncoding, v []byte)
+ EncodeTime(time.Time)
+ //encBignum(f *big.Int)
+ //encStringRunes(c charEncoding, v []rune)
+ WriteArrayStart(length int)
+ WriteArrayElem()
+ WriteArrayEnd()
+ WriteMapStart(length int)
+ WriteMapElemKey()
+ WriteMapElemValue()
+ WriteMapEnd()
+
+ reset()
+ atEndOfEncode()
+}
+
+type ioEncStringWriter interface {
+ WriteString(s string) (n int, err error)
+}
+
+type encDriverAsis interface {
+ EncodeAsis(v []byte)
+}
+
+type encDriverNoopContainerWriter struct{}
+
+func (encDriverNoopContainerWriter) WriteArrayStart(length int) {}
+func (encDriverNoopContainerWriter) WriteArrayElem() {}
+func (encDriverNoopContainerWriter) WriteArrayEnd() {}
+func (encDriverNoopContainerWriter) WriteMapStart(length int) {}
+func (encDriverNoopContainerWriter) WriteMapElemKey() {}
+func (encDriverNoopContainerWriter) WriteMapElemValue() {}
+func (encDriverNoopContainerWriter) WriteMapEnd() {}
+func (encDriverNoopContainerWriter) atEndOfEncode() {}
+
+type encDriverTrackContainerWriter struct {
+ c containerState
+}
+
+func (e *encDriverTrackContainerWriter) WriteArrayStart(length int) { e.c = containerArrayStart }
+func (e *encDriverTrackContainerWriter) WriteArrayElem() { e.c = containerArrayElem }
+func (e *encDriverTrackContainerWriter) WriteArrayEnd() { e.c = containerArrayEnd }
+func (e *encDriverTrackContainerWriter) WriteMapStart(length int) { e.c = containerMapStart }
+func (e *encDriverTrackContainerWriter) WriteMapElemKey() { e.c = containerMapKey }
+func (e *encDriverTrackContainerWriter) WriteMapElemValue() { e.c = containerMapValue }
+func (e *encDriverTrackContainerWriter) WriteMapEnd() { e.c = containerMapEnd }
+func (e *encDriverTrackContainerWriter) atEndOfEncode() {}
+
+// type ioEncWriterWriter interface {
+// WriteByte(c byte) error
+// WriteString(s string) (n int, err error)
+// Write(p []byte) (n int, err error)
+// }
+
+// EncodeOptions captures configuration options during encode.
+type EncodeOptions struct {
+ // WriterBufferSize is the size of the buffer used when writing.
+ //
+ // if > 0, we use a smart buffer internally for performance purposes.
+ WriterBufferSize int
+
+ // ChanRecvTimeout is the timeout used when selecting from a chan.
+ //
+ // Configuring this controls how we receive from a chan during the encoding process.
+ // - If ==0, we only consume the elements currently available in the chan.
+ // - if <0, we consume until the chan is closed.
+ // - If >0, we consume until this timeout.
+ ChanRecvTimeout time.Duration
+
+ // StructToArray specifies to encode a struct as an array, and not as a map
+ StructToArray bool
+
+ // Canonical representation means that encoding a value will always result in the same
+ // sequence of bytes.
+ //
+ // This only affects maps, as the iteration order for maps is random.
+ //
+ // The implementation MAY use the natural sort order for the map keys if possible:
+ //
+ // - If there is a natural sort order (ie for number, bool, string or []byte keys),
+ // then the map keys are first sorted in natural order and then written
+ // with corresponding map values to the strema.
+ // - If there is no natural sort order, then the map keys will first be
+ // encoded into []byte, and then sorted,
+ // before writing the sorted keys and the corresponding map values to the stream.
+ //
+ Canonical bool
+
+ // CheckCircularRef controls whether we check for circular references
+ // and error fast during an encode.
+ //
+ // If enabled, an error is received if a pointer to a struct
+ // references itself either directly or through one of its fields (iteratively).
+ //
+ // This is opt-in, as there may be a performance hit to checking circular references.
+ CheckCircularRef bool
+
+ // RecursiveEmptyCheck controls whether we descend into interfaces, structs and pointers
+ // when checking if a value is empty.
+ //
+ // Note that this may make OmitEmpty more expensive, as it incurs a lot more reflect calls.
+ RecursiveEmptyCheck bool
+
+ // Raw controls whether we encode Raw values.
+ // This is a "dangerous" option and must be explicitly set.
+ // If set, we blindly encode Raw values as-is, without checking
+ // if they are a correct representation of a value in that format.
+ // If unset, we error out.
+ Raw bool
+
+ // // AsSymbols defines what should be encoded as symbols.
+ // //
+ // // Encoding as symbols can reduce the encoded size significantly.
+ // //
+ // // However, during decoding, each string to be encoded as a symbol must
+ // // be checked to see if it has been seen before. Consequently, encoding time
+ // // will increase if using symbols, because string comparisons has a clear cost.
+ // //
+ // // Sample values:
+ // // AsSymbolNone
+ // // AsSymbolAll
+ // // AsSymbolMapStringKeys
+ // // AsSymbolMapStringKeysFlag | AsSymbolStructFieldNameFlag
+ // AsSymbols AsSymbolFlag
+}
+
+// ---------------------------------------------
+
+// ioEncWriter implements encWriter and can write to an io.Writer implementation
+type ioEncWriter struct {
+ w io.Writer
+ ww io.Writer
+ bw io.ByteWriter
+ sw ioEncStringWriter
+ fw ioFlusher
+ b [8]byte
+}
+
+func (z *ioEncWriter) WriteByte(b byte) (err error) {
+ z.b[0] = b
+ _, err = z.w.Write(z.b[:1])
+ return
+}
+
+func (z *ioEncWriter) WriteString(s string) (n int, err error) {
+ return z.w.Write(bytesView(s))
+}
+
+func (z *ioEncWriter) writeb(bs []byte) {
+ if _, err := z.ww.Write(bs); err != nil {
+ panic(err)
+ }
+}
+
+func (z *ioEncWriter) writestr(s string) {
+ if _, err := z.sw.WriteString(s); err != nil {
+ panic(err)
+ }
+}
+
+func (z *ioEncWriter) writen1(b byte) {
+ if err := z.bw.WriteByte(b); err != nil {
+ panic(err)
+ }
+}
+
+func (z *ioEncWriter) writen2(b1, b2 byte) {
+ var err error
+ if err = z.bw.WriteByte(b1); err == nil {
+ if err = z.bw.WriteByte(b2); err == nil {
+ return
+ }
+ }
+ panic(err)
+}
+
+// func (z *ioEncWriter) writen5(b1, b2, b3, b4, b5 byte) {
+// z.b[0], z.b[1], z.b[2], z.b[3], z.b[4] = b1, b2, b3, b4, b5
+// if _, err := z.ww.Write(z.b[:5]); err != nil {
+// panic(err)
+// }
+// }
+
+func (z *ioEncWriter) atEndOfEncode() {
+ if z.fw != nil {
+ if err := z.fw.Flush(); err != nil {
+ panic(err)
+ }
+ }
+}
+
+// ---------------------------------------------
+
+// bytesEncAppender implements encWriter and can write to an byte slice.
+type bytesEncAppender struct {
+ b []byte
+ out *[]byte
+}
+
+func (z *bytesEncAppender) writeb(s []byte) {
+ z.b = append(z.b, s...)
+}
+func (z *bytesEncAppender) writestr(s string) {
+ z.b = append(z.b, s...)
+}
+func (z *bytesEncAppender) writen1(b1 byte) {
+ z.b = append(z.b, b1)
+}
+func (z *bytesEncAppender) writen2(b1, b2 byte) {
+ z.b = append(z.b, b1, b2)
+}
+func (z *bytesEncAppender) atEndOfEncode() {
+ *(z.out) = z.b
+}
+func (z *bytesEncAppender) reset(in []byte, out *[]byte) {
+ z.b = in[:0]
+ z.out = out
+}
+
+// ---------------------------------------------
+
+func (e *Encoder) rawExt(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeRawExt(rv2i(rv).(*RawExt), e)
+}
+
+func (e *Encoder) ext(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeExt(rv2i(rv), f.xfTag, f.xfFn, e)
+}
+
+func (e *Encoder) selferMarshal(f *codecFnInfo, rv reflect.Value) {
+ rv2i(rv).(Selfer).CodecEncodeSelf(e)
+}
+
+func (e *Encoder) binaryMarshal(f *codecFnInfo, rv reflect.Value) {
+ bs, fnerr := rv2i(rv).(encoding.BinaryMarshaler).MarshalBinary()
+ e.marshal(bs, fnerr, false, cRAW)
+}
+
+func (e *Encoder) textMarshal(f *codecFnInfo, rv reflect.Value) {
+ bs, fnerr := rv2i(rv).(encoding.TextMarshaler).MarshalText()
+ e.marshal(bs, fnerr, false, cUTF8)
+}
+
+func (e *Encoder) jsonMarshal(f *codecFnInfo, rv reflect.Value) {
+ bs, fnerr := rv2i(rv).(jsonMarshaler).MarshalJSON()
+ e.marshal(bs, fnerr, true, cUTF8)
+}
+
+func (e *Encoder) raw(f *codecFnInfo, rv reflect.Value) {
+ e.rawBytes(rv2i(rv).(Raw))
+}
+
+func (e *Encoder) kInvalid(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeNil()
+}
+
+func (e *Encoder) kErr(f *codecFnInfo, rv reflect.Value) {
+ e.errorf("unsupported kind %s, for %#v", rv.Kind(), rv)
+}
+
+func (e *Encoder) kSlice(f *codecFnInfo, rv reflect.Value) {
+ ti := f.ti
+ ee := e.e
+ // array may be non-addressable, so we have to manage with care
+ // (don't call rv.Bytes, rv.Slice, etc).
+ // E.g. type struct S{B [2]byte};
+ // Encode(S{}) will bomb on "panic: slice of unaddressable array".
+ if f.seq != seqTypeArray {
+ if rv.IsNil() {
+ ee.EncodeNil()
+ return
+ }
+ // If in this method, then there was no extension function defined.
+ // So it's okay to treat as []byte.
+ if ti.rtid == uint8SliceTypId {
+ ee.EncodeStringBytes(cRAW, rv.Bytes())
+ return
+ }
+ }
+ if f.seq == seqTypeChan && ti.chandir&uint8(reflect.RecvDir) == 0 {
+ e.errorf("send-only channel cannot be encoded")
+ }
+ elemsep := e.esep
+ rtelem := ti.elem
+ rtelemIsByte := uint8TypId == rt2id(rtelem) // NOT rtelem.Kind() == reflect.Uint8
+ var l int
+ // if a slice, array or chan of bytes, treat specially
+ if rtelemIsByte {
+ switch f.seq {
+ case seqTypeSlice:
+ ee.EncodeStringBytes(cRAW, rv.Bytes())
+ case seqTypeArray:
+ l = rv.Len()
+ if rv.CanAddr() {
+ ee.EncodeStringBytes(cRAW, rv.Slice(0, l).Bytes())
+ } else {
+ var bs []byte
+ if l <= cap(e.b) {
+ bs = e.b[:l]
+ } else {
+ bs = make([]byte, l)
+ }
+ reflect.Copy(reflect.ValueOf(bs), rv)
+ ee.EncodeStringBytes(cRAW, bs)
+ }
+ case seqTypeChan:
+ // do not use range, so that the number of elements encoded
+ // does not change, and encoding does not hang waiting on someone to close chan.
+ // for b := range rv2i(rv).(<-chan byte) { bs = append(bs, b) }
+ // ch := rv2i(rv).(<-chan byte) // fix error - that this is a chan byte, not a <-chan byte.
+
+ if rv.IsNil() {
+ ee.EncodeNil()
+ break
+ }
+ bs := e.b[:0]
+ irv := rv2i(rv)
+ ch, ok := irv.(<-chan byte)
+ if !ok {
+ ch = irv.(chan byte)
+ }
+
+ L1:
+ switch timeout := e.h.ChanRecvTimeout; {
+ case timeout == 0: // only consume available
+ for {
+ select {
+ case b := <-ch:
+ bs = append(bs, b)
+ default:
+ break L1
+ }
+ }
+ case timeout > 0: // consume until timeout
+ tt := time.NewTimer(timeout)
+ for {
+ select {
+ case b := <-ch:
+ bs = append(bs, b)
+ case <-tt.C:
+ // close(tt.C)
+ break L1
+ }
+ }
+ default: // consume until close
+ for b := range ch {
+ bs = append(bs, b)
+ }
+ }
+
+ ee.EncodeStringBytes(cRAW, bs)
+ }
+ return
+ }
+
+ // if chan, consume chan into a slice, and work off that slice.
+ var rvcs reflect.Value
+ if f.seq == seqTypeChan {
+ rvcs = reflect.Zero(reflect.SliceOf(rtelem))
+ timeout := e.h.ChanRecvTimeout
+ if timeout < 0 { // consume until close
+ for {
+ recv, recvOk := rv.Recv()
+ if !recvOk {
+ break
+ }
+ rvcs = reflect.Append(rvcs, recv)
+ }
+ } else {
+ cases := make([]reflect.SelectCase, 2)
+ cases[0] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: rv}
+ if timeout == 0 {
+ cases[1] = reflect.SelectCase{Dir: reflect.SelectDefault}
+ } else {
+ tt := time.NewTimer(timeout)
+ cases[1] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(tt.C)}
+ }
+ for {
+ chosen, recv, recvOk := reflect.Select(cases)
+ if chosen == 1 || !recvOk {
+ break
+ }
+ rvcs = reflect.Append(rvcs, recv)
+ }
+ }
+ rv = rvcs // TODO: ensure this doesn't mess up anywhere that rv of kind chan is expected
+ }
+
+ l = rv.Len()
+ if ti.mbs {
+ if l%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", l)
+ return
+ }
+ ee.WriteMapStart(l / 2)
+ } else {
+ ee.WriteArrayStart(l)
+ }
+
+ if l > 0 {
+ var fn *codecFn
+ for rtelem.Kind() == reflect.Ptr {
+ rtelem = rtelem.Elem()
+ }
+ // if kind is reflect.Interface, do not pre-determine the
+ // encoding type, because preEncodeValue may break it down to
+ // a concrete type and kInterface will bomb.
+ if rtelem.Kind() != reflect.Interface {
+ fn = e.cfer().get(rtelem, true, true)
+ }
+ for j := 0; j < l; j++ {
+ if elemsep {
+ if ti.mbs {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ } else {
+ ee.WriteArrayElem()
+ }
+ }
+ e.encodeValue(rv.Index(j), fn, true)
+ }
+ }
+
+ if ti.mbs {
+ ee.WriteMapEnd()
+ } else {
+ ee.WriteArrayEnd()
+ }
+}
+
+func (e *Encoder) kStructNoOmitempty(f *codecFnInfo, rv reflect.Value) {
+ fti := f.ti
+ elemsep := e.esep
+ tisfi := fti.sfiSrc
+ toMap := !(fti.toArray || e.h.StructToArray)
+ if toMap {
+ tisfi = fti.sfiSort
+ }
+ ee := e.e
+
+ sfn := structFieldNode{v: rv, update: false}
+ if toMap {
+ ee.WriteMapStart(len(tisfi))
+ if elemsep {
+ for _, si := range tisfi {
+ ee.WriteMapElemKey()
+ // ee.EncodeString(cUTF8, si.encName)
+ encStructFieldKey(ee, fti.keyType, si.encName)
+ ee.WriteMapElemValue()
+ e.encodeValue(sfn.field(si), nil, true)
+ }
+ } else {
+ for _, si := range tisfi {
+ // ee.EncodeString(cUTF8, si.encName)
+ encStructFieldKey(ee, fti.keyType, si.encName)
+ e.encodeValue(sfn.field(si), nil, true)
+ }
+ }
+ ee.WriteMapEnd()
+ } else {
+ ee.WriteArrayStart(len(tisfi))
+ if elemsep {
+ for _, si := range tisfi {
+ ee.WriteArrayElem()
+ e.encodeValue(sfn.field(si), nil, true)
+ }
+ } else {
+ for _, si := range tisfi {
+ e.encodeValue(sfn.field(si), nil, true)
+ }
+ }
+ ee.WriteArrayEnd()
+ }
+}
+
+func encStructFieldKey(ee encDriver, keyType valueType, s string) {
+ var m must
+
+ // use if-else-if, not switch (which compiles to binary-search)
+ // since keyType is typically valueTypeString, branch prediction is pretty good.
+
+ if keyType == valueTypeString {
+ ee.EncodeString(cUTF8, s)
+ } else if keyType == valueTypeInt {
+ ee.EncodeInt(m.Int(strconv.ParseInt(s, 10, 64)))
+ } else if keyType == valueTypeUint {
+ ee.EncodeUint(m.Uint(strconv.ParseUint(s, 10, 64)))
+ } else if keyType == valueTypeFloat {
+ ee.EncodeFloat64(m.Float(strconv.ParseFloat(s, 64)))
+ } else {
+ ee.EncodeString(cUTF8, s)
+ }
+}
+
+func (e *Encoder) kStruct(f *codecFnInfo, rv reflect.Value) {
+ fti := f.ti
+ elemsep := e.esep
+ tisfi := fti.sfiSrc
+ toMap := !(fti.toArray || e.h.StructToArray)
+ // if toMap, use the sorted array. If toArray, use unsorted array (to match sequence in struct)
+ if toMap {
+ tisfi = fti.sfiSort
+ }
+ newlen := len(fti.sfiSort)
+ ee := e.e
+
+ // Use sync.Pool to reduce allocating slices unnecessarily.
+ // The cost of sync.Pool is less than the cost of new allocation.
+ //
+ // Each element of the array pools one of encStructPool(8|16|32|64).
+ // It allows the re-use of slices up to 64 in length.
+ // A performance cost of encoding structs was collecting
+ // which values were empty and should be omitted.
+ // We needed slices of reflect.Value and string to collect them.
+ // This shared pool reduces the amount of unnecessary creation we do.
+ // The cost is that of locking sometimes, but sync.Pool is efficient
+ // enough to reduce thread contention.
+
+ var spool *sync.Pool
+ var poolv interface{}
+ var fkvs []stringRv
+ // fmt.Printf(">>>>>>>>>>>>>> encode.kStruct: newlen: %d\n", newlen)
+ if newlen <= 8 {
+ spool, poolv = pool.stringRv8()
+ fkvs = poolv.(*[8]stringRv)[:newlen]
+ } else if newlen <= 16 {
+ spool, poolv = pool.stringRv16()
+ fkvs = poolv.(*[16]stringRv)[:newlen]
+ } else if newlen <= 32 {
+ spool, poolv = pool.stringRv32()
+ fkvs = poolv.(*[32]stringRv)[:newlen]
+ } else if newlen <= 64 {
+ spool, poolv = pool.stringRv64()
+ fkvs = poolv.(*[64]stringRv)[:newlen]
+ } else if newlen <= 128 {
+ spool, poolv = pool.stringRv128()
+ fkvs = poolv.(*[128]stringRv)[:newlen]
+ } else {
+ fkvs = make([]stringRv, newlen)
+ }
+
+ newlen = 0
+ var kv stringRv
+ recur := e.h.RecursiveEmptyCheck
+ sfn := structFieldNode{v: rv, update: false}
+ for _, si := range tisfi {
+ // kv.r = si.field(rv, false)
+ kv.r = sfn.field(si)
+ if toMap {
+ if si.omitEmpty() && isEmptyValue(kv.r, e.h.TypeInfos, recur, recur) {
+ continue
+ }
+ kv.v = si.encName
+ } else {
+ // use the zero value.
+ // if a reference or struct, set to nil (so you do not output too much)
+ if si.omitEmpty() && isEmptyValue(kv.r, e.h.TypeInfos, recur, recur) {
+ switch kv.r.Kind() {
+ case reflect.Struct, reflect.Interface, reflect.Ptr, reflect.Array, reflect.Map, reflect.Slice:
+ kv.r = reflect.Value{} //encode as nil
+ }
+ }
+ }
+ fkvs[newlen] = kv
+ newlen++
+ }
+
+ if toMap {
+ ee.WriteMapStart(newlen)
+ if elemsep {
+ for j := 0; j < newlen; j++ {
+ kv = fkvs[j]
+ ee.WriteMapElemKey()
+ // ee.EncodeString(cUTF8, kv.v)
+ encStructFieldKey(ee, fti.keyType, kv.v)
+ ee.WriteMapElemValue()
+ e.encodeValue(kv.r, nil, true)
+ }
+ } else {
+ for j := 0; j < newlen; j++ {
+ kv = fkvs[j]
+ // ee.EncodeString(cUTF8, kv.v)
+ encStructFieldKey(ee, fti.keyType, kv.v)
+ e.encodeValue(kv.r, nil, true)
+ }
+ }
+ ee.WriteMapEnd()
+ } else {
+ ee.WriteArrayStart(newlen)
+ if elemsep {
+ for j := 0; j < newlen; j++ {
+ ee.WriteArrayElem()
+ e.encodeValue(fkvs[j].r, nil, true)
+ }
+ } else {
+ for j := 0; j < newlen; j++ {
+ e.encodeValue(fkvs[j].r, nil, true)
+ }
+ }
+ ee.WriteArrayEnd()
+ }
+
+ // do not use defer. Instead, use explicit pool return at end of function.
+ // defer has a cost we are trying to avoid.
+ // If there is a panic and these slices are not returned, it is ok.
+ if spool != nil {
+ spool.Put(poolv)
+ }
+}
+
+func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
+ ee := e.e
+ if rv.IsNil() {
+ ee.EncodeNil()
+ return
+ }
+
+ l := rv.Len()
+ ee.WriteMapStart(l)
+ elemsep := e.esep
+ if l == 0 {
+ ee.WriteMapEnd()
+ return
+ }
+ // var asSymbols bool
+ // determine the underlying key and val encFn's for the map.
+ // This eliminates some work which is done for each loop iteration i.e.
+ // rv.Type(), ref.ValueOf(rt).Pointer(), then check map/list for fn.
+ //
+ // However, if kind is reflect.Interface, do not pre-determine the
+ // encoding type, because preEncodeValue may break it down to
+ // a concrete type and kInterface will bomb.
+ var keyFn, valFn *codecFn
+ ti := f.ti
+ rtkey0 := ti.key
+ rtkey := rtkey0
+ rtval0 := ti.elem
+ rtval := rtval0
+ // rtkeyid := rt2id(rtkey0)
+ for rtval.Kind() == reflect.Ptr {
+ rtval = rtval.Elem()
+ }
+ if rtval.Kind() != reflect.Interface {
+ valFn = e.cfer().get(rtval, true, true)
+ }
+ mks := rv.MapKeys()
+
+ if e.h.Canonical {
+ e.kMapCanonical(rtkey, rv, mks, valFn)
+ ee.WriteMapEnd()
+ return
+ }
+
+ var keyTypeIsString = stringTypId == rt2id(rtkey0) // rtkeyid
+ if !keyTypeIsString {
+ for rtkey.Kind() == reflect.Ptr {
+ rtkey = rtkey.Elem()
+ }
+ if rtkey.Kind() != reflect.Interface {
+ // rtkeyid = rt2id(rtkey)
+ keyFn = e.cfer().get(rtkey, true, true)
+ }
+ }
+
+ // for j, lmks := 0, len(mks); j < lmks; j++ {
+ for j := range mks {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ if keyTypeIsString {
+ ee.EncodeString(cUTF8, mks[j].String())
+ } else {
+ e.encodeValue(mks[j], keyFn, true)
+ }
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mks[j]), valFn, true)
+
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []reflect.Value, valFn *codecFn) {
+ ee := e.e
+ elemsep := e.esep
+ // we previously did out-of-band if an extension was registered.
+ // This is not necessary, as the natural kind is sufficient for ordering.
+
+ switch rtkey.Kind() {
+ case reflect.Bool:
+ mksv := make([]boolRv, len(mks))
+ for i, k := range mks {
+ v := &mksv[i]
+ v.r = k
+ v.v = k.Bool()
+ }
+ sort.Sort(boolRvSlice(mksv))
+ for i := range mksv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ ee.EncodeBool(mksv[i].v)
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
+ }
+ case reflect.String:
+ mksv := make([]stringRv, len(mks))
+ for i, k := range mks {
+ v := &mksv[i]
+ v.r = k
+ v.v = k.String()
+ }
+ sort.Sort(stringRvSlice(mksv))
+ for i := range mksv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ ee.EncodeString(cUTF8, mksv[i].v)
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
+ }
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr:
+ mksv := make([]uintRv, len(mks))
+ for i, k := range mks {
+ v := &mksv[i]
+ v.r = k
+ v.v = k.Uint()
+ }
+ sort.Sort(uintRvSlice(mksv))
+ for i := range mksv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ ee.EncodeUint(mksv[i].v)
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
+ }
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ mksv := make([]intRv, len(mks))
+ for i, k := range mks {
+ v := &mksv[i]
+ v.r = k
+ v.v = k.Int()
+ }
+ sort.Sort(intRvSlice(mksv))
+ for i := range mksv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ ee.EncodeInt(mksv[i].v)
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
+ }
+ case reflect.Float32:
+ mksv := make([]floatRv, len(mks))
+ for i, k := range mks {
+ v := &mksv[i]
+ v.r = k
+ v.v = k.Float()
+ }
+ sort.Sort(floatRvSlice(mksv))
+ for i := range mksv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ ee.EncodeFloat32(float32(mksv[i].v))
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
+ }
+ case reflect.Float64:
+ mksv := make([]floatRv, len(mks))
+ for i, k := range mks {
+ v := &mksv[i]
+ v.r = k
+ v.v = k.Float()
+ }
+ sort.Sort(floatRvSlice(mksv))
+ for i := range mksv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ ee.EncodeFloat64(mksv[i].v)
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
+ }
+ case reflect.Struct:
+ if rv.Type() == timeTyp {
+ mksv := make([]timeRv, len(mks))
+ for i, k := range mks {
+ v := &mksv[i]
+ v.r = k
+ v.v = rv2i(k).(time.Time)
+ }
+ sort.Sort(timeRvSlice(mksv))
+ for i := range mksv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ ee.EncodeTime(mksv[i].v)
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksv[i].r), valFn, true)
+ }
+ break
+ }
+ fallthrough
+ default:
+ // out-of-band
+ // first encode each key to a []byte first, then sort them, then record
+ var mksv []byte = make([]byte, 0, len(mks)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ mksbv := make([]bytesRv, len(mks))
+ for i, k := range mks {
+ v := &mksbv[i]
+ l := len(mksv)
+ e2.MustEncode(k)
+ v.r = k
+ v.v = mksv[l:]
+ }
+ sort.Sort(bytesRvSlice(mksbv))
+ for j := range mksbv {
+ if elemsep {
+ ee.WriteMapElemKey()
+ }
+ e.asis(mksbv[j].v)
+ if elemsep {
+ ee.WriteMapElemValue()
+ }
+ e.encodeValue(rv.MapIndex(mksbv[j].r), valFn, true)
+ }
+ }
+}
+
+// // --------------------------------------------------
+
+type encWriterSwitch struct {
+ wi *ioEncWriter
+ // wb bytesEncWriter
+ wb bytesEncAppender
+ wx bool // if bytes, wx=true
+ esep bool // whether it has elem separators
+ isas bool // whether e.as != nil
+}
+
+// // TODO: Uncomment after mid-stack inlining enabled in go 1.11
+
+// func (z *encWriterSwitch) writeb(s []byte) {
+// if z.wx {
+// z.wb.writeb(s)
+// } else {
+// z.wi.writeb(s)
+// }
+// }
+// func (z *encWriterSwitch) writestr(s string) {
+// if z.wx {
+// z.wb.writestr(s)
+// } else {
+// z.wi.writestr(s)
+// }
+// }
+// func (z *encWriterSwitch) writen1(b1 byte) {
+// if z.wx {
+// z.wb.writen1(b1)
+// } else {
+// z.wi.writen1(b1)
+// }
+// }
+// func (z *encWriterSwitch) writen2(b1, b2 byte) {
+// if z.wx {
+// z.wb.writen2(b1, b2)
+// } else {
+// z.wi.writen2(b1, b2)
+// }
+// }
+
+// An Encoder writes an object to an output stream in the codec format.
+type Encoder struct {
+ panicHdl
+ // hopefully, reduce derefencing cost by laying the encWriter inside the Encoder
+ e encDriver
+ // NOTE: Encoder shouldn't call it's write methods,
+ // as the handler MAY need to do some coordination.
+ w encWriter
+
+ h *BasicHandle
+ bw *bufio.Writer
+ as encDriverAsis
+
+ // ---- cpu cache line boundary?
+
+ // ---- cpu cache line boundary?
+ encWriterSwitch
+ err error
+
+ // ---- cpu cache line boundary?
+ codecFnPooler
+ ci set
+ js bool // here, so that no need to piggy back on *codecFner for this
+ be bool // here, so that no need to piggy back on *codecFner for this
+ _ [6]byte // padding
+
+ // ---- writable fields during execution --- *try* to keep in sep cache line
+
+ // ---- cpu cache line boundary?
+ // b [scratchByteArrayLen]byte
+ // _ [cacheLineSize - scratchByteArrayLen]byte // padding
+ b [cacheLineSize - 0]byte // used for encoding a chan or (non-addressable) array of bytes
+}
+
+// NewEncoder returns an Encoder for encoding into an io.Writer.
+//
+// For efficiency, Users are encouraged to pass in a memory buffered writer
+// (eg bufio.Writer, bytes.Buffer).
+func NewEncoder(w io.Writer, h Handle) *Encoder {
+ e := newEncoder(h)
+ e.Reset(w)
+ return e
+}
+
+// NewEncoderBytes returns an encoder for encoding directly and efficiently
+// into a byte slice, using zero-copying to temporary slices.
+//
+// It will potentially replace the output byte slice pointed to.
+// After encoding, the out parameter contains the encoded contents.
+func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
+ e := newEncoder(h)
+ e.ResetBytes(out)
+ return e
+}
+
+func newEncoder(h Handle) *Encoder {
+ e := &Encoder{h: h.getBasicHandle(), err: errEncoderNotInitialized}
+ e.hh = h
+ e.esep = h.hasElemSeparators()
+ return e
+}
+
+func (e *Encoder) resetCommon() {
+ if e.e == nil || e.hh.recreateEncDriver(e.e) {
+ e.e = e.hh.newEncDriver(e)
+ e.as, e.isas = e.e.(encDriverAsis)
+ // e.cr, _ = e.e.(containerStateRecv)
+ }
+ e.be = e.hh.isBinary()
+ _, e.js = e.hh.(*JsonHandle)
+ e.e.reset()
+ e.err = nil
+}
+
+// Reset resets the Encoder with a new output stream.
+//
+// This accommodates using the state of the Encoder,
+// where it has "cached" information about sub-engines.
+func (e *Encoder) Reset(w io.Writer) {
+ if w == nil {
+ return
+ }
+ if e.wi == nil {
+ e.wi = new(ioEncWriter)
+ }
+ var ok bool
+ e.wx = false
+ e.wi.w = w
+ if e.h.WriterBufferSize > 0 {
+ e.bw = bufio.NewWriterSize(w, e.h.WriterBufferSize)
+ e.wi.bw = e.bw
+ e.wi.sw = e.bw
+ e.wi.fw = e.bw
+ e.wi.ww = e.bw
+ } else {
+ if e.wi.bw, ok = w.(io.ByteWriter); !ok {
+ e.wi.bw = e.wi
+ }
+ if e.wi.sw, ok = w.(ioEncStringWriter); !ok {
+ e.wi.sw = e.wi
+ }
+ e.wi.fw, _ = w.(ioFlusher)
+ e.wi.ww = w
+ }
+ e.w = e.wi
+ e.resetCommon()
+}
+
+// ResetBytes resets the Encoder with a new destination output []byte.
+func (e *Encoder) ResetBytes(out *[]byte) {
+ if out == nil {
+ return
+ }
+ var in []byte
+ if out != nil {
+ in = *out
+ }
+ if in == nil {
+ in = make([]byte, defEncByteBufSize)
+ }
+ e.wx = true
+ e.wb.reset(in, out)
+ e.w = &e.wb
+ e.resetCommon()
+}
+
+// Encode writes an object into a stream.
+//
+// Encoding can be configured via the struct tag for the fields.
+// The key (in the struct tags) that we look at is configurable.
+//
+// By default, we look up the "codec" key in the struct field's tags,
+// and fall bak to the "json" key if "codec" is absent.
+// That key in struct field's tag value is the key name,
+// followed by an optional comma and options.
+//
+// To set an option on all fields (e.g. omitempty on all fields), you
+// can create a field called _struct, and set flags on it. The options
+// which can be set on _struct are:
+// - omitempty: so all fields are omitted if empty
+// - toarray: so struct is encoded as an array
+// - int: so struct key names are encoded as signed integers (instead of strings)
+// - uint: so struct key names are encoded as unsigned integers (instead of strings)
+// - float: so struct key names are encoded as floats (instead of strings)
+// More details on these below.
+//
+// Struct values "usually" encode as maps. Each exported struct field is encoded unless:
+// - the field's tag is "-", OR
+// - the field is empty (empty or the zero value) and its tag specifies the "omitempty" option.
+//
+// When encoding as a map, the first string in the tag (before the comma)
+// is the map key string to use when encoding.
+// ...
+// This key is typically encoded as a string.
+// However, there are instances where the encoded stream has mapping keys encoded as numbers.
+// For example, some cbor streams have keys as integer codes in the stream, but they should map
+// to fields in a structured object. Consequently, a struct is the natural representation in code.
+// For these, configure the struct to encode/decode the keys as numbers (instead of string).
+// This is done with the int,uint or float option on the _struct field (see above).
+//
+// However, struct values may encode as arrays. This happens when:
+// - StructToArray Encode option is set, OR
+// - the tag on the _struct field sets the "toarray" option
+// Note that omitempty is ignored when encoding struct values as arrays,
+// as an entry must be encoded for each field, to maintain its position.
+//
+// Values with types that implement MapBySlice are encoded as stream maps.
+//
+// The empty values (for omitempty option) are false, 0, any nil pointer
+// or interface value, and any array, slice, map, or string of length zero.
+//
+// Anonymous fields are encoded inline except:
+// - the struct tag specifies a replacement name (first value)
+// - the field is of an interface type
+//
+// Examples:
+//
+// // NOTE: 'json:' can be used as struct tag key, in place 'codec:' below.
+// type MyStruct struct {
+// _struct bool `codec:",omitempty"` //set omitempty for every field
+// Field1 string `codec:"-"` //skip this field
+// Field2 int `codec:"myName"` //Use key "myName" in encode stream
+// Field3 int32 `codec:",omitempty"` //use key "Field3". Omit if empty.
+// Field4 bool `codec:"f4,omitempty"` //use key "f4". Omit if empty.
+// io.Reader //use key "Reader".
+// MyStruct `codec:"my1" //use key "my1".
+// MyStruct //inline it
+// ...
+// }
+//
+// type MyStruct struct {
+// _struct bool `codec:",toarray"` //encode struct as an array
+// }
+//
+// type MyStruct struct {
+// _struct bool `codec:",uint"` //encode struct with "unsigned integer" keys
+// Field1 string `codec:"1"` //encode Field1 key using: EncodeInt(1)
+// Field2 string `codec:"2"` //encode Field2 key using: EncodeInt(2)
+// }
+//
+// The mode of encoding is based on the type of the value. When a value is seen:
+// - If a Selfer, call its CodecEncodeSelf method
+// - If an extension is registered for it, call that extension function
+// - If implements encoding.(Binary|Text|JSON)Marshaler, call Marshal(Binary|Text|JSON) method
+// - Else encode it based on its reflect.Kind
+//
+// Note that struct field names and keys in map[string]XXX will be treated as symbols.
+// Some formats support symbols (e.g. binc) and will properly encode the string
+// only once in the stream, and use a tag to refer to it thereafter.
+func (e *Encoder) Encode(v interface{}) (err error) {
+ defer e.deferred(&err)
+ e.MustEncode(v)
+ return
+}
+
+// MustEncode is like Encode, but panics if unable to Encode.
+// This provides insight to the code location that triggered the error.
+func (e *Encoder) MustEncode(v interface{}) {
+ if e.err != nil {
+ panic(e.err)
+ }
+ e.encode(v)
+ e.e.atEndOfEncode()
+ e.w.atEndOfEncode()
+ e.alwaysAtEnd()
+}
+
+func (e *Encoder) deferred(err1 *error) {
+ e.alwaysAtEnd()
+ if recoverPanicToErr {
+ if x := recover(); x != nil {
+ panicValToErr(e, x, err1)
+ panicValToErr(e, x, &e.err)
+ }
+ }
+}
+
+// func (e *Encoder) alwaysAtEnd() {
+// e.codecFnPooler.alwaysAtEnd()
+// }
+
+func (e *Encoder) encode(iv interface{}) {
+ if iv == nil || definitelyNil(iv) {
+ e.e.EncodeNil()
+ return
+ }
+ if v, ok := iv.(Selfer); ok {
+ v.CodecEncodeSelf(e)
+ return
+ }
+
+ // a switch with only concrete types can be optimized.
+ // consequently, we deal with nil and interfaces outside.
+
+ switch v := iv.(type) {
+ case Raw:
+ e.rawBytes(v)
+ case reflect.Value:
+ e.encodeValue(v, nil, true)
+
+ case string:
+ e.e.EncodeString(cUTF8, v)
+ case bool:
+ e.e.EncodeBool(v)
+ case int:
+ e.e.EncodeInt(int64(v))
+ case int8:
+ e.e.EncodeInt(int64(v))
+ case int16:
+ e.e.EncodeInt(int64(v))
+ case int32:
+ e.e.EncodeInt(int64(v))
+ case int64:
+ e.e.EncodeInt(v)
+ case uint:
+ e.e.EncodeUint(uint64(v))
+ case uint8:
+ e.e.EncodeUint(uint64(v))
+ case uint16:
+ e.e.EncodeUint(uint64(v))
+ case uint32:
+ e.e.EncodeUint(uint64(v))
+ case uint64:
+ e.e.EncodeUint(v)
+ case uintptr:
+ e.e.EncodeUint(uint64(v))
+ case float32:
+ e.e.EncodeFloat32(v)
+ case float64:
+ e.e.EncodeFloat64(v)
+ case time.Time:
+ e.e.EncodeTime(v)
+ case []uint8:
+ e.e.EncodeStringBytes(cRAW, v)
+
+ case *Raw:
+ e.rawBytes(*v)
+
+ case *string:
+ e.e.EncodeString(cUTF8, *v)
+ case *bool:
+ e.e.EncodeBool(*v)
+ case *int:
+ e.e.EncodeInt(int64(*v))
+ case *int8:
+ e.e.EncodeInt(int64(*v))
+ case *int16:
+ e.e.EncodeInt(int64(*v))
+ case *int32:
+ e.e.EncodeInt(int64(*v))
+ case *int64:
+ e.e.EncodeInt(*v)
+ case *uint:
+ e.e.EncodeUint(uint64(*v))
+ case *uint8:
+ e.e.EncodeUint(uint64(*v))
+ case *uint16:
+ e.e.EncodeUint(uint64(*v))
+ case *uint32:
+ e.e.EncodeUint(uint64(*v))
+ case *uint64:
+ e.e.EncodeUint(*v)
+ case *uintptr:
+ e.e.EncodeUint(uint64(*v))
+ case *float32:
+ e.e.EncodeFloat32(*v)
+ case *float64:
+ e.e.EncodeFloat64(*v)
+ case *time.Time:
+ e.e.EncodeTime(*v)
+
+ case *[]uint8:
+ e.e.EncodeStringBytes(cRAW, *v)
+
+ default:
+ if !fastpathEncodeTypeSwitch(iv, e) {
+ // checkfastpath=true (not false), as underlying slice/map type may be fast-path
+ e.encodeValue(reflect.ValueOf(iv), nil, true)
+ }
+ }
+}
+
+func (e *Encoder) encodeValue(rv reflect.Value, fn *codecFn, checkFastpath bool) {
+ // if a valid fn is passed, it MUST BE for the dereferenced type of rv
+ var sptr uintptr
+ var rvp reflect.Value
+ var rvpValid bool
+TOP:
+ switch rv.Kind() {
+ case reflect.Ptr:
+ if rv.IsNil() {
+ e.e.EncodeNil()
+ return
+ }
+ rvpValid = true
+ rvp = rv
+ rv = rv.Elem()
+ if e.h.CheckCircularRef && rv.Kind() == reflect.Struct {
+ // TODO: Movable pointers will be an issue here. Future problem.
+ sptr = rv.UnsafeAddr()
+ break TOP
+ }
+ goto TOP
+ case reflect.Interface:
+ if rv.IsNil() {
+ e.e.EncodeNil()
+ return
+ }
+ rv = rv.Elem()
+ goto TOP
+ case reflect.Slice, reflect.Map:
+ if rv.IsNil() {
+ e.e.EncodeNil()
+ return
+ }
+ case reflect.Invalid, reflect.Func:
+ e.e.EncodeNil()
+ return
+ }
+
+ if sptr != 0 && (&e.ci).add(sptr) {
+ e.errorf("circular reference found: # %d", sptr)
+ }
+
+ if fn == nil {
+ rt := rv.Type()
+ // always pass checkCodecSelfer=true, in case T or ****T is passed, where *T is a Selfer
+ fn = e.cfer().get(rt, checkFastpath, true)
+ }
+ if fn.i.addrE {
+ if rvpValid {
+ fn.fe(e, &fn.i, rvp)
+ } else if rv.CanAddr() {
+ fn.fe(e, &fn.i, rv.Addr())
+ } else {
+ rv2 := reflect.New(rv.Type())
+ rv2.Elem().Set(rv)
+ fn.fe(e, &fn.i, rv2)
+ }
+ } else {
+ fn.fe(e, &fn.i, rv)
+ }
+ if sptr != 0 {
+ (&e.ci).remove(sptr)
+ }
+}
+
+func (e *Encoder) marshal(bs []byte, fnerr error, asis bool, c charEncoding) {
+ if fnerr != nil {
+ panic(fnerr)
+ }
+ if bs == nil {
+ e.e.EncodeNil()
+ } else if asis {
+ e.asis(bs)
+ } else {
+ e.e.EncodeStringBytes(c, bs)
+ }
+}
+
+func (e *Encoder) asis(v []byte) {
+ if e.isas {
+ e.as.EncodeAsis(v)
+ } else {
+ e.w.writeb(v)
+ }
+}
+
+func (e *Encoder) rawBytes(vv Raw) {
+ v := []byte(vv)
+ if !e.h.Raw {
+ e.errorf("Raw values cannot be encoded: %v", v)
+ }
+ e.asis(v)
+}
+
+func (e *Encoder) wrapErrstr(v interface{}, err *error) {
+ *err = fmt.Errorf("%s encode error: %v", e.hh.Name(), v)
+}
diff --git a/vendor/github.com/ugorji/go/codec/fast-path.generated.go b/vendor/github.com/ugorji/go/codec/fast-path.generated.go
new file mode 100644
index 00000000..87f2562f
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/fast-path.generated.go
@@ -0,0 +1,34522 @@
+// +build !notfastpath
+
+// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// Code generated from fast-path.go.tmpl - DO NOT EDIT.
+
+package codec
+
+// Fast path functions try to create a fast path encode or decode implementation
+// for common maps and slices.
+//
+// We define the functions and register then in this single file
+// so as not to pollute the encode.go and decode.go, and create a dependency in there.
+// This file can be omitted without causing a build failure.
+//
+// The advantage of fast paths is:
+// - Many calls bypass reflection altogether
+//
+// Currently support
+// - slice of all builtin types,
+// - map of all builtin types to string or interface value
+// - symmetrical maps of all builtin types (e.g. str-str, uint8-uint8)
+// This should provide adequate "typical" implementations.
+//
+// Note that fast track decode functions must handle values for which an address cannot be obtained.
+// For example:
+// m2 := map[string]int{}
+// p2 := []interface{}{m2}
+// // decoding into p2 will bomb if fast track functions do not treat like unaddressable.
+//
+
+import (
+ "reflect"
+ "sort"
+)
+
+const fastpathEnabled = true
+
+type fastpathT struct{}
+
+var fastpathTV fastpathT
+
+type fastpathE struct {
+ rtid uintptr
+ rt reflect.Type
+ encfn func(*Encoder, *codecFnInfo, reflect.Value)
+ decfn func(*Decoder, *codecFnInfo, reflect.Value)
+}
+
+type fastpathA [271]fastpathE
+
+func (x *fastpathA) index(rtid uintptr) int {
+ // use binary search to grab the index (adapted from sort/search.go)
+ h, i, j := 0, 0, 271 // len(x)
+ for i < j {
+ h = i + (j-i)/2
+ if x[h].rtid < rtid {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ if i < 271 && x[i].rtid == rtid {
+ return i
+ }
+ return -1
+}
+
+type fastpathAslice []fastpathE
+
+func (x fastpathAslice) Len() int { return len(x) }
+func (x fastpathAslice) Less(i, j int) bool { return x[i].rtid < x[j].rtid }
+func (x fastpathAslice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+var fastpathAV fastpathA
+
+// due to possible initialization loop error, make fastpath in an init()
+func init() {
+ i := 0
+ fn := func(v interface{},
+ fe func(*Encoder, *codecFnInfo, reflect.Value),
+ fd func(*Decoder, *codecFnInfo, reflect.Value)) (f fastpathE) {
+ xrt := reflect.TypeOf(v)
+ xptr := rt2id(xrt)
+ fastpathAV[i] = fastpathE{xptr, xrt, fe, fd}
+ i++
+ return
+ }
+
+ fn([]interface{}(nil), (*Encoder).fastpathEncSliceIntfR, (*Decoder).fastpathDecSliceIntfR)
+ fn([]string(nil), (*Encoder).fastpathEncSliceStringR, (*Decoder).fastpathDecSliceStringR)
+ fn([]float32(nil), (*Encoder).fastpathEncSliceFloat32R, (*Decoder).fastpathDecSliceFloat32R)
+ fn([]float64(nil), (*Encoder).fastpathEncSliceFloat64R, (*Decoder).fastpathDecSliceFloat64R)
+ fn([]uint(nil), (*Encoder).fastpathEncSliceUintR, (*Decoder).fastpathDecSliceUintR)
+ fn([]uint16(nil), (*Encoder).fastpathEncSliceUint16R, (*Decoder).fastpathDecSliceUint16R)
+ fn([]uint32(nil), (*Encoder).fastpathEncSliceUint32R, (*Decoder).fastpathDecSliceUint32R)
+ fn([]uint64(nil), (*Encoder).fastpathEncSliceUint64R, (*Decoder).fastpathDecSliceUint64R)
+ fn([]uintptr(nil), (*Encoder).fastpathEncSliceUintptrR, (*Decoder).fastpathDecSliceUintptrR)
+ fn([]int(nil), (*Encoder).fastpathEncSliceIntR, (*Decoder).fastpathDecSliceIntR)
+ fn([]int8(nil), (*Encoder).fastpathEncSliceInt8R, (*Decoder).fastpathDecSliceInt8R)
+ fn([]int16(nil), (*Encoder).fastpathEncSliceInt16R, (*Decoder).fastpathDecSliceInt16R)
+ fn([]int32(nil), (*Encoder).fastpathEncSliceInt32R, (*Decoder).fastpathDecSliceInt32R)
+ fn([]int64(nil), (*Encoder).fastpathEncSliceInt64R, (*Decoder).fastpathDecSliceInt64R)
+ fn([]bool(nil), (*Encoder).fastpathEncSliceBoolR, (*Decoder).fastpathDecSliceBoolR)
+
+ fn(map[interface{}]interface{}(nil), (*Encoder).fastpathEncMapIntfIntfR, (*Decoder).fastpathDecMapIntfIntfR)
+ fn(map[interface{}]string(nil), (*Encoder).fastpathEncMapIntfStringR, (*Decoder).fastpathDecMapIntfStringR)
+ fn(map[interface{}]uint(nil), (*Encoder).fastpathEncMapIntfUintR, (*Decoder).fastpathDecMapIntfUintR)
+ fn(map[interface{}]uint8(nil), (*Encoder).fastpathEncMapIntfUint8R, (*Decoder).fastpathDecMapIntfUint8R)
+ fn(map[interface{}]uint16(nil), (*Encoder).fastpathEncMapIntfUint16R, (*Decoder).fastpathDecMapIntfUint16R)
+ fn(map[interface{}]uint32(nil), (*Encoder).fastpathEncMapIntfUint32R, (*Decoder).fastpathDecMapIntfUint32R)
+ fn(map[interface{}]uint64(nil), (*Encoder).fastpathEncMapIntfUint64R, (*Decoder).fastpathDecMapIntfUint64R)
+ fn(map[interface{}]uintptr(nil), (*Encoder).fastpathEncMapIntfUintptrR, (*Decoder).fastpathDecMapIntfUintptrR)
+ fn(map[interface{}]int(nil), (*Encoder).fastpathEncMapIntfIntR, (*Decoder).fastpathDecMapIntfIntR)
+ fn(map[interface{}]int8(nil), (*Encoder).fastpathEncMapIntfInt8R, (*Decoder).fastpathDecMapIntfInt8R)
+ fn(map[interface{}]int16(nil), (*Encoder).fastpathEncMapIntfInt16R, (*Decoder).fastpathDecMapIntfInt16R)
+ fn(map[interface{}]int32(nil), (*Encoder).fastpathEncMapIntfInt32R, (*Decoder).fastpathDecMapIntfInt32R)
+ fn(map[interface{}]int64(nil), (*Encoder).fastpathEncMapIntfInt64R, (*Decoder).fastpathDecMapIntfInt64R)
+ fn(map[interface{}]float32(nil), (*Encoder).fastpathEncMapIntfFloat32R, (*Decoder).fastpathDecMapIntfFloat32R)
+ fn(map[interface{}]float64(nil), (*Encoder).fastpathEncMapIntfFloat64R, (*Decoder).fastpathDecMapIntfFloat64R)
+ fn(map[interface{}]bool(nil), (*Encoder).fastpathEncMapIntfBoolR, (*Decoder).fastpathDecMapIntfBoolR)
+ fn(map[string]interface{}(nil), (*Encoder).fastpathEncMapStringIntfR, (*Decoder).fastpathDecMapStringIntfR)
+ fn(map[string]string(nil), (*Encoder).fastpathEncMapStringStringR, (*Decoder).fastpathDecMapStringStringR)
+ fn(map[string]uint(nil), (*Encoder).fastpathEncMapStringUintR, (*Decoder).fastpathDecMapStringUintR)
+ fn(map[string]uint8(nil), (*Encoder).fastpathEncMapStringUint8R, (*Decoder).fastpathDecMapStringUint8R)
+ fn(map[string]uint16(nil), (*Encoder).fastpathEncMapStringUint16R, (*Decoder).fastpathDecMapStringUint16R)
+ fn(map[string]uint32(nil), (*Encoder).fastpathEncMapStringUint32R, (*Decoder).fastpathDecMapStringUint32R)
+ fn(map[string]uint64(nil), (*Encoder).fastpathEncMapStringUint64R, (*Decoder).fastpathDecMapStringUint64R)
+ fn(map[string]uintptr(nil), (*Encoder).fastpathEncMapStringUintptrR, (*Decoder).fastpathDecMapStringUintptrR)
+ fn(map[string]int(nil), (*Encoder).fastpathEncMapStringIntR, (*Decoder).fastpathDecMapStringIntR)
+ fn(map[string]int8(nil), (*Encoder).fastpathEncMapStringInt8R, (*Decoder).fastpathDecMapStringInt8R)
+ fn(map[string]int16(nil), (*Encoder).fastpathEncMapStringInt16R, (*Decoder).fastpathDecMapStringInt16R)
+ fn(map[string]int32(nil), (*Encoder).fastpathEncMapStringInt32R, (*Decoder).fastpathDecMapStringInt32R)
+ fn(map[string]int64(nil), (*Encoder).fastpathEncMapStringInt64R, (*Decoder).fastpathDecMapStringInt64R)
+ fn(map[string]float32(nil), (*Encoder).fastpathEncMapStringFloat32R, (*Decoder).fastpathDecMapStringFloat32R)
+ fn(map[string]float64(nil), (*Encoder).fastpathEncMapStringFloat64R, (*Decoder).fastpathDecMapStringFloat64R)
+ fn(map[string]bool(nil), (*Encoder).fastpathEncMapStringBoolR, (*Decoder).fastpathDecMapStringBoolR)
+ fn(map[float32]interface{}(nil), (*Encoder).fastpathEncMapFloat32IntfR, (*Decoder).fastpathDecMapFloat32IntfR)
+ fn(map[float32]string(nil), (*Encoder).fastpathEncMapFloat32StringR, (*Decoder).fastpathDecMapFloat32StringR)
+ fn(map[float32]uint(nil), (*Encoder).fastpathEncMapFloat32UintR, (*Decoder).fastpathDecMapFloat32UintR)
+ fn(map[float32]uint8(nil), (*Encoder).fastpathEncMapFloat32Uint8R, (*Decoder).fastpathDecMapFloat32Uint8R)
+ fn(map[float32]uint16(nil), (*Encoder).fastpathEncMapFloat32Uint16R, (*Decoder).fastpathDecMapFloat32Uint16R)
+ fn(map[float32]uint32(nil), (*Encoder).fastpathEncMapFloat32Uint32R, (*Decoder).fastpathDecMapFloat32Uint32R)
+ fn(map[float32]uint64(nil), (*Encoder).fastpathEncMapFloat32Uint64R, (*Decoder).fastpathDecMapFloat32Uint64R)
+ fn(map[float32]uintptr(nil), (*Encoder).fastpathEncMapFloat32UintptrR, (*Decoder).fastpathDecMapFloat32UintptrR)
+ fn(map[float32]int(nil), (*Encoder).fastpathEncMapFloat32IntR, (*Decoder).fastpathDecMapFloat32IntR)
+ fn(map[float32]int8(nil), (*Encoder).fastpathEncMapFloat32Int8R, (*Decoder).fastpathDecMapFloat32Int8R)
+ fn(map[float32]int16(nil), (*Encoder).fastpathEncMapFloat32Int16R, (*Decoder).fastpathDecMapFloat32Int16R)
+ fn(map[float32]int32(nil), (*Encoder).fastpathEncMapFloat32Int32R, (*Decoder).fastpathDecMapFloat32Int32R)
+ fn(map[float32]int64(nil), (*Encoder).fastpathEncMapFloat32Int64R, (*Decoder).fastpathDecMapFloat32Int64R)
+ fn(map[float32]float32(nil), (*Encoder).fastpathEncMapFloat32Float32R, (*Decoder).fastpathDecMapFloat32Float32R)
+ fn(map[float32]float64(nil), (*Encoder).fastpathEncMapFloat32Float64R, (*Decoder).fastpathDecMapFloat32Float64R)
+ fn(map[float32]bool(nil), (*Encoder).fastpathEncMapFloat32BoolR, (*Decoder).fastpathDecMapFloat32BoolR)
+ fn(map[float64]interface{}(nil), (*Encoder).fastpathEncMapFloat64IntfR, (*Decoder).fastpathDecMapFloat64IntfR)
+ fn(map[float64]string(nil), (*Encoder).fastpathEncMapFloat64StringR, (*Decoder).fastpathDecMapFloat64StringR)
+ fn(map[float64]uint(nil), (*Encoder).fastpathEncMapFloat64UintR, (*Decoder).fastpathDecMapFloat64UintR)
+ fn(map[float64]uint8(nil), (*Encoder).fastpathEncMapFloat64Uint8R, (*Decoder).fastpathDecMapFloat64Uint8R)
+ fn(map[float64]uint16(nil), (*Encoder).fastpathEncMapFloat64Uint16R, (*Decoder).fastpathDecMapFloat64Uint16R)
+ fn(map[float64]uint32(nil), (*Encoder).fastpathEncMapFloat64Uint32R, (*Decoder).fastpathDecMapFloat64Uint32R)
+ fn(map[float64]uint64(nil), (*Encoder).fastpathEncMapFloat64Uint64R, (*Decoder).fastpathDecMapFloat64Uint64R)
+ fn(map[float64]uintptr(nil), (*Encoder).fastpathEncMapFloat64UintptrR, (*Decoder).fastpathDecMapFloat64UintptrR)
+ fn(map[float64]int(nil), (*Encoder).fastpathEncMapFloat64IntR, (*Decoder).fastpathDecMapFloat64IntR)
+ fn(map[float64]int8(nil), (*Encoder).fastpathEncMapFloat64Int8R, (*Decoder).fastpathDecMapFloat64Int8R)
+ fn(map[float64]int16(nil), (*Encoder).fastpathEncMapFloat64Int16R, (*Decoder).fastpathDecMapFloat64Int16R)
+ fn(map[float64]int32(nil), (*Encoder).fastpathEncMapFloat64Int32R, (*Decoder).fastpathDecMapFloat64Int32R)
+ fn(map[float64]int64(nil), (*Encoder).fastpathEncMapFloat64Int64R, (*Decoder).fastpathDecMapFloat64Int64R)
+ fn(map[float64]float32(nil), (*Encoder).fastpathEncMapFloat64Float32R, (*Decoder).fastpathDecMapFloat64Float32R)
+ fn(map[float64]float64(nil), (*Encoder).fastpathEncMapFloat64Float64R, (*Decoder).fastpathDecMapFloat64Float64R)
+ fn(map[float64]bool(nil), (*Encoder).fastpathEncMapFloat64BoolR, (*Decoder).fastpathDecMapFloat64BoolR)
+ fn(map[uint]interface{}(nil), (*Encoder).fastpathEncMapUintIntfR, (*Decoder).fastpathDecMapUintIntfR)
+ fn(map[uint]string(nil), (*Encoder).fastpathEncMapUintStringR, (*Decoder).fastpathDecMapUintStringR)
+ fn(map[uint]uint(nil), (*Encoder).fastpathEncMapUintUintR, (*Decoder).fastpathDecMapUintUintR)
+ fn(map[uint]uint8(nil), (*Encoder).fastpathEncMapUintUint8R, (*Decoder).fastpathDecMapUintUint8R)
+ fn(map[uint]uint16(nil), (*Encoder).fastpathEncMapUintUint16R, (*Decoder).fastpathDecMapUintUint16R)
+ fn(map[uint]uint32(nil), (*Encoder).fastpathEncMapUintUint32R, (*Decoder).fastpathDecMapUintUint32R)
+ fn(map[uint]uint64(nil), (*Encoder).fastpathEncMapUintUint64R, (*Decoder).fastpathDecMapUintUint64R)
+ fn(map[uint]uintptr(nil), (*Encoder).fastpathEncMapUintUintptrR, (*Decoder).fastpathDecMapUintUintptrR)
+ fn(map[uint]int(nil), (*Encoder).fastpathEncMapUintIntR, (*Decoder).fastpathDecMapUintIntR)
+ fn(map[uint]int8(nil), (*Encoder).fastpathEncMapUintInt8R, (*Decoder).fastpathDecMapUintInt8R)
+ fn(map[uint]int16(nil), (*Encoder).fastpathEncMapUintInt16R, (*Decoder).fastpathDecMapUintInt16R)
+ fn(map[uint]int32(nil), (*Encoder).fastpathEncMapUintInt32R, (*Decoder).fastpathDecMapUintInt32R)
+ fn(map[uint]int64(nil), (*Encoder).fastpathEncMapUintInt64R, (*Decoder).fastpathDecMapUintInt64R)
+ fn(map[uint]float32(nil), (*Encoder).fastpathEncMapUintFloat32R, (*Decoder).fastpathDecMapUintFloat32R)
+ fn(map[uint]float64(nil), (*Encoder).fastpathEncMapUintFloat64R, (*Decoder).fastpathDecMapUintFloat64R)
+ fn(map[uint]bool(nil), (*Encoder).fastpathEncMapUintBoolR, (*Decoder).fastpathDecMapUintBoolR)
+ fn(map[uint8]interface{}(nil), (*Encoder).fastpathEncMapUint8IntfR, (*Decoder).fastpathDecMapUint8IntfR)
+ fn(map[uint8]string(nil), (*Encoder).fastpathEncMapUint8StringR, (*Decoder).fastpathDecMapUint8StringR)
+ fn(map[uint8]uint(nil), (*Encoder).fastpathEncMapUint8UintR, (*Decoder).fastpathDecMapUint8UintR)
+ fn(map[uint8]uint8(nil), (*Encoder).fastpathEncMapUint8Uint8R, (*Decoder).fastpathDecMapUint8Uint8R)
+ fn(map[uint8]uint16(nil), (*Encoder).fastpathEncMapUint8Uint16R, (*Decoder).fastpathDecMapUint8Uint16R)
+ fn(map[uint8]uint32(nil), (*Encoder).fastpathEncMapUint8Uint32R, (*Decoder).fastpathDecMapUint8Uint32R)
+ fn(map[uint8]uint64(nil), (*Encoder).fastpathEncMapUint8Uint64R, (*Decoder).fastpathDecMapUint8Uint64R)
+ fn(map[uint8]uintptr(nil), (*Encoder).fastpathEncMapUint8UintptrR, (*Decoder).fastpathDecMapUint8UintptrR)
+ fn(map[uint8]int(nil), (*Encoder).fastpathEncMapUint8IntR, (*Decoder).fastpathDecMapUint8IntR)
+ fn(map[uint8]int8(nil), (*Encoder).fastpathEncMapUint8Int8R, (*Decoder).fastpathDecMapUint8Int8R)
+ fn(map[uint8]int16(nil), (*Encoder).fastpathEncMapUint8Int16R, (*Decoder).fastpathDecMapUint8Int16R)
+ fn(map[uint8]int32(nil), (*Encoder).fastpathEncMapUint8Int32R, (*Decoder).fastpathDecMapUint8Int32R)
+ fn(map[uint8]int64(nil), (*Encoder).fastpathEncMapUint8Int64R, (*Decoder).fastpathDecMapUint8Int64R)
+ fn(map[uint8]float32(nil), (*Encoder).fastpathEncMapUint8Float32R, (*Decoder).fastpathDecMapUint8Float32R)
+ fn(map[uint8]float64(nil), (*Encoder).fastpathEncMapUint8Float64R, (*Decoder).fastpathDecMapUint8Float64R)
+ fn(map[uint8]bool(nil), (*Encoder).fastpathEncMapUint8BoolR, (*Decoder).fastpathDecMapUint8BoolR)
+ fn(map[uint16]interface{}(nil), (*Encoder).fastpathEncMapUint16IntfR, (*Decoder).fastpathDecMapUint16IntfR)
+ fn(map[uint16]string(nil), (*Encoder).fastpathEncMapUint16StringR, (*Decoder).fastpathDecMapUint16StringR)
+ fn(map[uint16]uint(nil), (*Encoder).fastpathEncMapUint16UintR, (*Decoder).fastpathDecMapUint16UintR)
+ fn(map[uint16]uint8(nil), (*Encoder).fastpathEncMapUint16Uint8R, (*Decoder).fastpathDecMapUint16Uint8R)
+ fn(map[uint16]uint16(nil), (*Encoder).fastpathEncMapUint16Uint16R, (*Decoder).fastpathDecMapUint16Uint16R)
+ fn(map[uint16]uint32(nil), (*Encoder).fastpathEncMapUint16Uint32R, (*Decoder).fastpathDecMapUint16Uint32R)
+ fn(map[uint16]uint64(nil), (*Encoder).fastpathEncMapUint16Uint64R, (*Decoder).fastpathDecMapUint16Uint64R)
+ fn(map[uint16]uintptr(nil), (*Encoder).fastpathEncMapUint16UintptrR, (*Decoder).fastpathDecMapUint16UintptrR)
+ fn(map[uint16]int(nil), (*Encoder).fastpathEncMapUint16IntR, (*Decoder).fastpathDecMapUint16IntR)
+ fn(map[uint16]int8(nil), (*Encoder).fastpathEncMapUint16Int8R, (*Decoder).fastpathDecMapUint16Int8R)
+ fn(map[uint16]int16(nil), (*Encoder).fastpathEncMapUint16Int16R, (*Decoder).fastpathDecMapUint16Int16R)
+ fn(map[uint16]int32(nil), (*Encoder).fastpathEncMapUint16Int32R, (*Decoder).fastpathDecMapUint16Int32R)
+ fn(map[uint16]int64(nil), (*Encoder).fastpathEncMapUint16Int64R, (*Decoder).fastpathDecMapUint16Int64R)
+ fn(map[uint16]float32(nil), (*Encoder).fastpathEncMapUint16Float32R, (*Decoder).fastpathDecMapUint16Float32R)
+ fn(map[uint16]float64(nil), (*Encoder).fastpathEncMapUint16Float64R, (*Decoder).fastpathDecMapUint16Float64R)
+ fn(map[uint16]bool(nil), (*Encoder).fastpathEncMapUint16BoolR, (*Decoder).fastpathDecMapUint16BoolR)
+ fn(map[uint32]interface{}(nil), (*Encoder).fastpathEncMapUint32IntfR, (*Decoder).fastpathDecMapUint32IntfR)
+ fn(map[uint32]string(nil), (*Encoder).fastpathEncMapUint32StringR, (*Decoder).fastpathDecMapUint32StringR)
+ fn(map[uint32]uint(nil), (*Encoder).fastpathEncMapUint32UintR, (*Decoder).fastpathDecMapUint32UintR)
+ fn(map[uint32]uint8(nil), (*Encoder).fastpathEncMapUint32Uint8R, (*Decoder).fastpathDecMapUint32Uint8R)
+ fn(map[uint32]uint16(nil), (*Encoder).fastpathEncMapUint32Uint16R, (*Decoder).fastpathDecMapUint32Uint16R)
+ fn(map[uint32]uint32(nil), (*Encoder).fastpathEncMapUint32Uint32R, (*Decoder).fastpathDecMapUint32Uint32R)
+ fn(map[uint32]uint64(nil), (*Encoder).fastpathEncMapUint32Uint64R, (*Decoder).fastpathDecMapUint32Uint64R)
+ fn(map[uint32]uintptr(nil), (*Encoder).fastpathEncMapUint32UintptrR, (*Decoder).fastpathDecMapUint32UintptrR)
+ fn(map[uint32]int(nil), (*Encoder).fastpathEncMapUint32IntR, (*Decoder).fastpathDecMapUint32IntR)
+ fn(map[uint32]int8(nil), (*Encoder).fastpathEncMapUint32Int8R, (*Decoder).fastpathDecMapUint32Int8R)
+ fn(map[uint32]int16(nil), (*Encoder).fastpathEncMapUint32Int16R, (*Decoder).fastpathDecMapUint32Int16R)
+ fn(map[uint32]int32(nil), (*Encoder).fastpathEncMapUint32Int32R, (*Decoder).fastpathDecMapUint32Int32R)
+ fn(map[uint32]int64(nil), (*Encoder).fastpathEncMapUint32Int64R, (*Decoder).fastpathDecMapUint32Int64R)
+ fn(map[uint32]float32(nil), (*Encoder).fastpathEncMapUint32Float32R, (*Decoder).fastpathDecMapUint32Float32R)
+ fn(map[uint32]float64(nil), (*Encoder).fastpathEncMapUint32Float64R, (*Decoder).fastpathDecMapUint32Float64R)
+ fn(map[uint32]bool(nil), (*Encoder).fastpathEncMapUint32BoolR, (*Decoder).fastpathDecMapUint32BoolR)
+ fn(map[uint64]interface{}(nil), (*Encoder).fastpathEncMapUint64IntfR, (*Decoder).fastpathDecMapUint64IntfR)
+ fn(map[uint64]string(nil), (*Encoder).fastpathEncMapUint64StringR, (*Decoder).fastpathDecMapUint64StringR)
+ fn(map[uint64]uint(nil), (*Encoder).fastpathEncMapUint64UintR, (*Decoder).fastpathDecMapUint64UintR)
+ fn(map[uint64]uint8(nil), (*Encoder).fastpathEncMapUint64Uint8R, (*Decoder).fastpathDecMapUint64Uint8R)
+ fn(map[uint64]uint16(nil), (*Encoder).fastpathEncMapUint64Uint16R, (*Decoder).fastpathDecMapUint64Uint16R)
+ fn(map[uint64]uint32(nil), (*Encoder).fastpathEncMapUint64Uint32R, (*Decoder).fastpathDecMapUint64Uint32R)
+ fn(map[uint64]uint64(nil), (*Encoder).fastpathEncMapUint64Uint64R, (*Decoder).fastpathDecMapUint64Uint64R)
+ fn(map[uint64]uintptr(nil), (*Encoder).fastpathEncMapUint64UintptrR, (*Decoder).fastpathDecMapUint64UintptrR)
+ fn(map[uint64]int(nil), (*Encoder).fastpathEncMapUint64IntR, (*Decoder).fastpathDecMapUint64IntR)
+ fn(map[uint64]int8(nil), (*Encoder).fastpathEncMapUint64Int8R, (*Decoder).fastpathDecMapUint64Int8R)
+ fn(map[uint64]int16(nil), (*Encoder).fastpathEncMapUint64Int16R, (*Decoder).fastpathDecMapUint64Int16R)
+ fn(map[uint64]int32(nil), (*Encoder).fastpathEncMapUint64Int32R, (*Decoder).fastpathDecMapUint64Int32R)
+ fn(map[uint64]int64(nil), (*Encoder).fastpathEncMapUint64Int64R, (*Decoder).fastpathDecMapUint64Int64R)
+ fn(map[uint64]float32(nil), (*Encoder).fastpathEncMapUint64Float32R, (*Decoder).fastpathDecMapUint64Float32R)
+ fn(map[uint64]float64(nil), (*Encoder).fastpathEncMapUint64Float64R, (*Decoder).fastpathDecMapUint64Float64R)
+ fn(map[uint64]bool(nil), (*Encoder).fastpathEncMapUint64BoolR, (*Decoder).fastpathDecMapUint64BoolR)
+ fn(map[uintptr]interface{}(nil), (*Encoder).fastpathEncMapUintptrIntfR, (*Decoder).fastpathDecMapUintptrIntfR)
+ fn(map[uintptr]string(nil), (*Encoder).fastpathEncMapUintptrStringR, (*Decoder).fastpathDecMapUintptrStringR)
+ fn(map[uintptr]uint(nil), (*Encoder).fastpathEncMapUintptrUintR, (*Decoder).fastpathDecMapUintptrUintR)
+ fn(map[uintptr]uint8(nil), (*Encoder).fastpathEncMapUintptrUint8R, (*Decoder).fastpathDecMapUintptrUint8R)
+ fn(map[uintptr]uint16(nil), (*Encoder).fastpathEncMapUintptrUint16R, (*Decoder).fastpathDecMapUintptrUint16R)
+ fn(map[uintptr]uint32(nil), (*Encoder).fastpathEncMapUintptrUint32R, (*Decoder).fastpathDecMapUintptrUint32R)
+ fn(map[uintptr]uint64(nil), (*Encoder).fastpathEncMapUintptrUint64R, (*Decoder).fastpathDecMapUintptrUint64R)
+ fn(map[uintptr]uintptr(nil), (*Encoder).fastpathEncMapUintptrUintptrR, (*Decoder).fastpathDecMapUintptrUintptrR)
+ fn(map[uintptr]int(nil), (*Encoder).fastpathEncMapUintptrIntR, (*Decoder).fastpathDecMapUintptrIntR)
+ fn(map[uintptr]int8(nil), (*Encoder).fastpathEncMapUintptrInt8R, (*Decoder).fastpathDecMapUintptrInt8R)
+ fn(map[uintptr]int16(nil), (*Encoder).fastpathEncMapUintptrInt16R, (*Decoder).fastpathDecMapUintptrInt16R)
+ fn(map[uintptr]int32(nil), (*Encoder).fastpathEncMapUintptrInt32R, (*Decoder).fastpathDecMapUintptrInt32R)
+ fn(map[uintptr]int64(nil), (*Encoder).fastpathEncMapUintptrInt64R, (*Decoder).fastpathDecMapUintptrInt64R)
+ fn(map[uintptr]float32(nil), (*Encoder).fastpathEncMapUintptrFloat32R, (*Decoder).fastpathDecMapUintptrFloat32R)
+ fn(map[uintptr]float64(nil), (*Encoder).fastpathEncMapUintptrFloat64R, (*Decoder).fastpathDecMapUintptrFloat64R)
+ fn(map[uintptr]bool(nil), (*Encoder).fastpathEncMapUintptrBoolR, (*Decoder).fastpathDecMapUintptrBoolR)
+ fn(map[int]interface{}(nil), (*Encoder).fastpathEncMapIntIntfR, (*Decoder).fastpathDecMapIntIntfR)
+ fn(map[int]string(nil), (*Encoder).fastpathEncMapIntStringR, (*Decoder).fastpathDecMapIntStringR)
+ fn(map[int]uint(nil), (*Encoder).fastpathEncMapIntUintR, (*Decoder).fastpathDecMapIntUintR)
+ fn(map[int]uint8(nil), (*Encoder).fastpathEncMapIntUint8R, (*Decoder).fastpathDecMapIntUint8R)
+ fn(map[int]uint16(nil), (*Encoder).fastpathEncMapIntUint16R, (*Decoder).fastpathDecMapIntUint16R)
+ fn(map[int]uint32(nil), (*Encoder).fastpathEncMapIntUint32R, (*Decoder).fastpathDecMapIntUint32R)
+ fn(map[int]uint64(nil), (*Encoder).fastpathEncMapIntUint64R, (*Decoder).fastpathDecMapIntUint64R)
+ fn(map[int]uintptr(nil), (*Encoder).fastpathEncMapIntUintptrR, (*Decoder).fastpathDecMapIntUintptrR)
+ fn(map[int]int(nil), (*Encoder).fastpathEncMapIntIntR, (*Decoder).fastpathDecMapIntIntR)
+ fn(map[int]int8(nil), (*Encoder).fastpathEncMapIntInt8R, (*Decoder).fastpathDecMapIntInt8R)
+ fn(map[int]int16(nil), (*Encoder).fastpathEncMapIntInt16R, (*Decoder).fastpathDecMapIntInt16R)
+ fn(map[int]int32(nil), (*Encoder).fastpathEncMapIntInt32R, (*Decoder).fastpathDecMapIntInt32R)
+ fn(map[int]int64(nil), (*Encoder).fastpathEncMapIntInt64R, (*Decoder).fastpathDecMapIntInt64R)
+ fn(map[int]float32(nil), (*Encoder).fastpathEncMapIntFloat32R, (*Decoder).fastpathDecMapIntFloat32R)
+ fn(map[int]float64(nil), (*Encoder).fastpathEncMapIntFloat64R, (*Decoder).fastpathDecMapIntFloat64R)
+ fn(map[int]bool(nil), (*Encoder).fastpathEncMapIntBoolR, (*Decoder).fastpathDecMapIntBoolR)
+ fn(map[int8]interface{}(nil), (*Encoder).fastpathEncMapInt8IntfR, (*Decoder).fastpathDecMapInt8IntfR)
+ fn(map[int8]string(nil), (*Encoder).fastpathEncMapInt8StringR, (*Decoder).fastpathDecMapInt8StringR)
+ fn(map[int8]uint(nil), (*Encoder).fastpathEncMapInt8UintR, (*Decoder).fastpathDecMapInt8UintR)
+ fn(map[int8]uint8(nil), (*Encoder).fastpathEncMapInt8Uint8R, (*Decoder).fastpathDecMapInt8Uint8R)
+ fn(map[int8]uint16(nil), (*Encoder).fastpathEncMapInt8Uint16R, (*Decoder).fastpathDecMapInt8Uint16R)
+ fn(map[int8]uint32(nil), (*Encoder).fastpathEncMapInt8Uint32R, (*Decoder).fastpathDecMapInt8Uint32R)
+ fn(map[int8]uint64(nil), (*Encoder).fastpathEncMapInt8Uint64R, (*Decoder).fastpathDecMapInt8Uint64R)
+ fn(map[int8]uintptr(nil), (*Encoder).fastpathEncMapInt8UintptrR, (*Decoder).fastpathDecMapInt8UintptrR)
+ fn(map[int8]int(nil), (*Encoder).fastpathEncMapInt8IntR, (*Decoder).fastpathDecMapInt8IntR)
+ fn(map[int8]int8(nil), (*Encoder).fastpathEncMapInt8Int8R, (*Decoder).fastpathDecMapInt8Int8R)
+ fn(map[int8]int16(nil), (*Encoder).fastpathEncMapInt8Int16R, (*Decoder).fastpathDecMapInt8Int16R)
+ fn(map[int8]int32(nil), (*Encoder).fastpathEncMapInt8Int32R, (*Decoder).fastpathDecMapInt8Int32R)
+ fn(map[int8]int64(nil), (*Encoder).fastpathEncMapInt8Int64R, (*Decoder).fastpathDecMapInt8Int64R)
+ fn(map[int8]float32(nil), (*Encoder).fastpathEncMapInt8Float32R, (*Decoder).fastpathDecMapInt8Float32R)
+ fn(map[int8]float64(nil), (*Encoder).fastpathEncMapInt8Float64R, (*Decoder).fastpathDecMapInt8Float64R)
+ fn(map[int8]bool(nil), (*Encoder).fastpathEncMapInt8BoolR, (*Decoder).fastpathDecMapInt8BoolR)
+ fn(map[int16]interface{}(nil), (*Encoder).fastpathEncMapInt16IntfR, (*Decoder).fastpathDecMapInt16IntfR)
+ fn(map[int16]string(nil), (*Encoder).fastpathEncMapInt16StringR, (*Decoder).fastpathDecMapInt16StringR)
+ fn(map[int16]uint(nil), (*Encoder).fastpathEncMapInt16UintR, (*Decoder).fastpathDecMapInt16UintR)
+ fn(map[int16]uint8(nil), (*Encoder).fastpathEncMapInt16Uint8R, (*Decoder).fastpathDecMapInt16Uint8R)
+ fn(map[int16]uint16(nil), (*Encoder).fastpathEncMapInt16Uint16R, (*Decoder).fastpathDecMapInt16Uint16R)
+ fn(map[int16]uint32(nil), (*Encoder).fastpathEncMapInt16Uint32R, (*Decoder).fastpathDecMapInt16Uint32R)
+ fn(map[int16]uint64(nil), (*Encoder).fastpathEncMapInt16Uint64R, (*Decoder).fastpathDecMapInt16Uint64R)
+ fn(map[int16]uintptr(nil), (*Encoder).fastpathEncMapInt16UintptrR, (*Decoder).fastpathDecMapInt16UintptrR)
+ fn(map[int16]int(nil), (*Encoder).fastpathEncMapInt16IntR, (*Decoder).fastpathDecMapInt16IntR)
+ fn(map[int16]int8(nil), (*Encoder).fastpathEncMapInt16Int8R, (*Decoder).fastpathDecMapInt16Int8R)
+ fn(map[int16]int16(nil), (*Encoder).fastpathEncMapInt16Int16R, (*Decoder).fastpathDecMapInt16Int16R)
+ fn(map[int16]int32(nil), (*Encoder).fastpathEncMapInt16Int32R, (*Decoder).fastpathDecMapInt16Int32R)
+ fn(map[int16]int64(nil), (*Encoder).fastpathEncMapInt16Int64R, (*Decoder).fastpathDecMapInt16Int64R)
+ fn(map[int16]float32(nil), (*Encoder).fastpathEncMapInt16Float32R, (*Decoder).fastpathDecMapInt16Float32R)
+ fn(map[int16]float64(nil), (*Encoder).fastpathEncMapInt16Float64R, (*Decoder).fastpathDecMapInt16Float64R)
+ fn(map[int16]bool(nil), (*Encoder).fastpathEncMapInt16BoolR, (*Decoder).fastpathDecMapInt16BoolR)
+ fn(map[int32]interface{}(nil), (*Encoder).fastpathEncMapInt32IntfR, (*Decoder).fastpathDecMapInt32IntfR)
+ fn(map[int32]string(nil), (*Encoder).fastpathEncMapInt32StringR, (*Decoder).fastpathDecMapInt32StringR)
+ fn(map[int32]uint(nil), (*Encoder).fastpathEncMapInt32UintR, (*Decoder).fastpathDecMapInt32UintR)
+ fn(map[int32]uint8(nil), (*Encoder).fastpathEncMapInt32Uint8R, (*Decoder).fastpathDecMapInt32Uint8R)
+ fn(map[int32]uint16(nil), (*Encoder).fastpathEncMapInt32Uint16R, (*Decoder).fastpathDecMapInt32Uint16R)
+ fn(map[int32]uint32(nil), (*Encoder).fastpathEncMapInt32Uint32R, (*Decoder).fastpathDecMapInt32Uint32R)
+ fn(map[int32]uint64(nil), (*Encoder).fastpathEncMapInt32Uint64R, (*Decoder).fastpathDecMapInt32Uint64R)
+ fn(map[int32]uintptr(nil), (*Encoder).fastpathEncMapInt32UintptrR, (*Decoder).fastpathDecMapInt32UintptrR)
+ fn(map[int32]int(nil), (*Encoder).fastpathEncMapInt32IntR, (*Decoder).fastpathDecMapInt32IntR)
+ fn(map[int32]int8(nil), (*Encoder).fastpathEncMapInt32Int8R, (*Decoder).fastpathDecMapInt32Int8R)
+ fn(map[int32]int16(nil), (*Encoder).fastpathEncMapInt32Int16R, (*Decoder).fastpathDecMapInt32Int16R)
+ fn(map[int32]int32(nil), (*Encoder).fastpathEncMapInt32Int32R, (*Decoder).fastpathDecMapInt32Int32R)
+ fn(map[int32]int64(nil), (*Encoder).fastpathEncMapInt32Int64R, (*Decoder).fastpathDecMapInt32Int64R)
+ fn(map[int32]float32(nil), (*Encoder).fastpathEncMapInt32Float32R, (*Decoder).fastpathDecMapInt32Float32R)
+ fn(map[int32]float64(nil), (*Encoder).fastpathEncMapInt32Float64R, (*Decoder).fastpathDecMapInt32Float64R)
+ fn(map[int32]bool(nil), (*Encoder).fastpathEncMapInt32BoolR, (*Decoder).fastpathDecMapInt32BoolR)
+ fn(map[int64]interface{}(nil), (*Encoder).fastpathEncMapInt64IntfR, (*Decoder).fastpathDecMapInt64IntfR)
+ fn(map[int64]string(nil), (*Encoder).fastpathEncMapInt64StringR, (*Decoder).fastpathDecMapInt64StringR)
+ fn(map[int64]uint(nil), (*Encoder).fastpathEncMapInt64UintR, (*Decoder).fastpathDecMapInt64UintR)
+ fn(map[int64]uint8(nil), (*Encoder).fastpathEncMapInt64Uint8R, (*Decoder).fastpathDecMapInt64Uint8R)
+ fn(map[int64]uint16(nil), (*Encoder).fastpathEncMapInt64Uint16R, (*Decoder).fastpathDecMapInt64Uint16R)
+ fn(map[int64]uint32(nil), (*Encoder).fastpathEncMapInt64Uint32R, (*Decoder).fastpathDecMapInt64Uint32R)
+ fn(map[int64]uint64(nil), (*Encoder).fastpathEncMapInt64Uint64R, (*Decoder).fastpathDecMapInt64Uint64R)
+ fn(map[int64]uintptr(nil), (*Encoder).fastpathEncMapInt64UintptrR, (*Decoder).fastpathDecMapInt64UintptrR)
+ fn(map[int64]int(nil), (*Encoder).fastpathEncMapInt64IntR, (*Decoder).fastpathDecMapInt64IntR)
+ fn(map[int64]int8(nil), (*Encoder).fastpathEncMapInt64Int8R, (*Decoder).fastpathDecMapInt64Int8R)
+ fn(map[int64]int16(nil), (*Encoder).fastpathEncMapInt64Int16R, (*Decoder).fastpathDecMapInt64Int16R)
+ fn(map[int64]int32(nil), (*Encoder).fastpathEncMapInt64Int32R, (*Decoder).fastpathDecMapInt64Int32R)
+ fn(map[int64]int64(nil), (*Encoder).fastpathEncMapInt64Int64R, (*Decoder).fastpathDecMapInt64Int64R)
+ fn(map[int64]float32(nil), (*Encoder).fastpathEncMapInt64Float32R, (*Decoder).fastpathDecMapInt64Float32R)
+ fn(map[int64]float64(nil), (*Encoder).fastpathEncMapInt64Float64R, (*Decoder).fastpathDecMapInt64Float64R)
+ fn(map[int64]bool(nil), (*Encoder).fastpathEncMapInt64BoolR, (*Decoder).fastpathDecMapInt64BoolR)
+ fn(map[bool]interface{}(nil), (*Encoder).fastpathEncMapBoolIntfR, (*Decoder).fastpathDecMapBoolIntfR)
+ fn(map[bool]string(nil), (*Encoder).fastpathEncMapBoolStringR, (*Decoder).fastpathDecMapBoolStringR)
+ fn(map[bool]uint(nil), (*Encoder).fastpathEncMapBoolUintR, (*Decoder).fastpathDecMapBoolUintR)
+ fn(map[bool]uint8(nil), (*Encoder).fastpathEncMapBoolUint8R, (*Decoder).fastpathDecMapBoolUint8R)
+ fn(map[bool]uint16(nil), (*Encoder).fastpathEncMapBoolUint16R, (*Decoder).fastpathDecMapBoolUint16R)
+ fn(map[bool]uint32(nil), (*Encoder).fastpathEncMapBoolUint32R, (*Decoder).fastpathDecMapBoolUint32R)
+ fn(map[bool]uint64(nil), (*Encoder).fastpathEncMapBoolUint64R, (*Decoder).fastpathDecMapBoolUint64R)
+ fn(map[bool]uintptr(nil), (*Encoder).fastpathEncMapBoolUintptrR, (*Decoder).fastpathDecMapBoolUintptrR)
+ fn(map[bool]int(nil), (*Encoder).fastpathEncMapBoolIntR, (*Decoder).fastpathDecMapBoolIntR)
+ fn(map[bool]int8(nil), (*Encoder).fastpathEncMapBoolInt8R, (*Decoder).fastpathDecMapBoolInt8R)
+ fn(map[bool]int16(nil), (*Encoder).fastpathEncMapBoolInt16R, (*Decoder).fastpathDecMapBoolInt16R)
+ fn(map[bool]int32(nil), (*Encoder).fastpathEncMapBoolInt32R, (*Decoder).fastpathDecMapBoolInt32R)
+ fn(map[bool]int64(nil), (*Encoder).fastpathEncMapBoolInt64R, (*Decoder).fastpathDecMapBoolInt64R)
+ fn(map[bool]float32(nil), (*Encoder).fastpathEncMapBoolFloat32R, (*Decoder).fastpathDecMapBoolFloat32R)
+ fn(map[bool]float64(nil), (*Encoder).fastpathEncMapBoolFloat64R, (*Decoder).fastpathDecMapBoolFloat64R)
+ fn(map[bool]bool(nil), (*Encoder).fastpathEncMapBoolBoolR, (*Decoder).fastpathDecMapBoolBoolR)
+
+ sort.Sort(fastpathAslice(fastpathAV[:]))
+}
+
+// -- encode
+
+// -- -- fast path type switch
+func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool {
+ switch v := iv.(type) {
+
+ case []interface{}:
+ fastpathTV.EncSliceIntfV(v, e)
+ case *[]interface{}:
+ fastpathTV.EncSliceIntfV(*v, e)
+ case []string:
+ fastpathTV.EncSliceStringV(v, e)
+ case *[]string:
+ fastpathTV.EncSliceStringV(*v, e)
+ case []float32:
+ fastpathTV.EncSliceFloat32V(v, e)
+ case *[]float32:
+ fastpathTV.EncSliceFloat32V(*v, e)
+ case []float64:
+ fastpathTV.EncSliceFloat64V(v, e)
+ case *[]float64:
+ fastpathTV.EncSliceFloat64V(*v, e)
+ case []uint:
+ fastpathTV.EncSliceUintV(v, e)
+ case *[]uint:
+ fastpathTV.EncSliceUintV(*v, e)
+ case []uint16:
+ fastpathTV.EncSliceUint16V(v, e)
+ case *[]uint16:
+ fastpathTV.EncSliceUint16V(*v, e)
+ case []uint32:
+ fastpathTV.EncSliceUint32V(v, e)
+ case *[]uint32:
+ fastpathTV.EncSliceUint32V(*v, e)
+ case []uint64:
+ fastpathTV.EncSliceUint64V(v, e)
+ case *[]uint64:
+ fastpathTV.EncSliceUint64V(*v, e)
+ case []uintptr:
+ fastpathTV.EncSliceUintptrV(v, e)
+ case *[]uintptr:
+ fastpathTV.EncSliceUintptrV(*v, e)
+ case []int:
+ fastpathTV.EncSliceIntV(v, e)
+ case *[]int:
+ fastpathTV.EncSliceIntV(*v, e)
+ case []int8:
+ fastpathTV.EncSliceInt8V(v, e)
+ case *[]int8:
+ fastpathTV.EncSliceInt8V(*v, e)
+ case []int16:
+ fastpathTV.EncSliceInt16V(v, e)
+ case *[]int16:
+ fastpathTV.EncSliceInt16V(*v, e)
+ case []int32:
+ fastpathTV.EncSliceInt32V(v, e)
+ case *[]int32:
+ fastpathTV.EncSliceInt32V(*v, e)
+ case []int64:
+ fastpathTV.EncSliceInt64V(v, e)
+ case *[]int64:
+ fastpathTV.EncSliceInt64V(*v, e)
+ case []bool:
+ fastpathTV.EncSliceBoolV(v, e)
+ case *[]bool:
+ fastpathTV.EncSliceBoolV(*v, e)
+
+ case map[interface{}]interface{}:
+ fastpathTV.EncMapIntfIntfV(v, e)
+ case *map[interface{}]interface{}:
+ fastpathTV.EncMapIntfIntfV(*v, e)
+ case map[interface{}]string:
+ fastpathTV.EncMapIntfStringV(v, e)
+ case *map[interface{}]string:
+ fastpathTV.EncMapIntfStringV(*v, e)
+ case map[interface{}]uint:
+ fastpathTV.EncMapIntfUintV(v, e)
+ case *map[interface{}]uint:
+ fastpathTV.EncMapIntfUintV(*v, e)
+ case map[interface{}]uint8:
+ fastpathTV.EncMapIntfUint8V(v, e)
+ case *map[interface{}]uint8:
+ fastpathTV.EncMapIntfUint8V(*v, e)
+ case map[interface{}]uint16:
+ fastpathTV.EncMapIntfUint16V(v, e)
+ case *map[interface{}]uint16:
+ fastpathTV.EncMapIntfUint16V(*v, e)
+ case map[interface{}]uint32:
+ fastpathTV.EncMapIntfUint32V(v, e)
+ case *map[interface{}]uint32:
+ fastpathTV.EncMapIntfUint32V(*v, e)
+ case map[interface{}]uint64:
+ fastpathTV.EncMapIntfUint64V(v, e)
+ case *map[interface{}]uint64:
+ fastpathTV.EncMapIntfUint64V(*v, e)
+ case map[interface{}]uintptr:
+ fastpathTV.EncMapIntfUintptrV(v, e)
+ case *map[interface{}]uintptr:
+ fastpathTV.EncMapIntfUintptrV(*v, e)
+ case map[interface{}]int:
+ fastpathTV.EncMapIntfIntV(v, e)
+ case *map[interface{}]int:
+ fastpathTV.EncMapIntfIntV(*v, e)
+ case map[interface{}]int8:
+ fastpathTV.EncMapIntfInt8V(v, e)
+ case *map[interface{}]int8:
+ fastpathTV.EncMapIntfInt8V(*v, e)
+ case map[interface{}]int16:
+ fastpathTV.EncMapIntfInt16V(v, e)
+ case *map[interface{}]int16:
+ fastpathTV.EncMapIntfInt16V(*v, e)
+ case map[interface{}]int32:
+ fastpathTV.EncMapIntfInt32V(v, e)
+ case *map[interface{}]int32:
+ fastpathTV.EncMapIntfInt32V(*v, e)
+ case map[interface{}]int64:
+ fastpathTV.EncMapIntfInt64V(v, e)
+ case *map[interface{}]int64:
+ fastpathTV.EncMapIntfInt64V(*v, e)
+ case map[interface{}]float32:
+ fastpathTV.EncMapIntfFloat32V(v, e)
+ case *map[interface{}]float32:
+ fastpathTV.EncMapIntfFloat32V(*v, e)
+ case map[interface{}]float64:
+ fastpathTV.EncMapIntfFloat64V(v, e)
+ case *map[interface{}]float64:
+ fastpathTV.EncMapIntfFloat64V(*v, e)
+ case map[interface{}]bool:
+ fastpathTV.EncMapIntfBoolV(v, e)
+ case *map[interface{}]bool:
+ fastpathTV.EncMapIntfBoolV(*v, e)
+ case map[string]interface{}:
+ fastpathTV.EncMapStringIntfV(v, e)
+ case *map[string]interface{}:
+ fastpathTV.EncMapStringIntfV(*v, e)
+ case map[string]string:
+ fastpathTV.EncMapStringStringV(v, e)
+ case *map[string]string:
+ fastpathTV.EncMapStringStringV(*v, e)
+ case map[string]uint:
+ fastpathTV.EncMapStringUintV(v, e)
+ case *map[string]uint:
+ fastpathTV.EncMapStringUintV(*v, e)
+ case map[string]uint8:
+ fastpathTV.EncMapStringUint8V(v, e)
+ case *map[string]uint8:
+ fastpathTV.EncMapStringUint8V(*v, e)
+ case map[string]uint16:
+ fastpathTV.EncMapStringUint16V(v, e)
+ case *map[string]uint16:
+ fastpathTV.EncMapStringUint16V(*v, e)
+ case map[string]uint32:
+ fastpathTV.EncMapStringUint32V(v, e)
+ case *map[string]uint32:
+ fastpathTV.EncMapStringUint32V(*v, e)
+ case map[string]uint64:
+ fastpathTV.EncMapStringUint64V(v, e)
+ case *map[string]uint64:
+ fastpathTV.EncMapStringUint64V(*v, e)
+ case map[string]uintptr:
+ fastpathTV.EncMapStringUintptrV(v, e)
+ case *map[string]uintptr:
+ fastpathTV.EncMapStringUintptrV(*v, e)
+ case map[string]int:
+ fastpathTV.EncMapStringIntV(v, e)
+ case *map[string]int:
+ fastpathTV.EncMapStringIntV(*v, e)
+ case map[string]int8:
+ fastpathTV.EncMapStringInt8V(v, e)
+ case *map[string]int8:
+ fastpathTV.EncMapStringInt8V(*v, e)
+ case map[string]int16:
+ fastpathTV.EncMapStringInt16V(v, e)
+ case *map[string]int16:
+ fastpathTV.EncMapStringInt16V(*v, e)
+ case map[string]int32:
+ fastpathTV.EncMapStringInt32V(v, e)
+ case *map[string]int32:
+ fastpathTV.EncMapStringInt32V(*v, e)
+ case map[string]int64:
+ fastpathTV.EncMapStringInt64V(v, e)
+ case *map[string]int64:
+ fastpathTV.EncMapStringInt64V(*v, e)
+ case map[string]float32:
+ fastpathTV.EncMapStringFloat32V(v, e)
+ case *map[string]float32:
+ fastpathTV.EncMapStringFloat32V(*v, e)
+ case map[string]float64:
+ fastpathTV.EncMapStringFloat64V(v, e)
+ case *map[string]float64:
+ fastpathTV.EncMapStringFloat64V(*v, e)
+ case map[string]bool:
+ fastpathTV.EncMapStringBoolV(v, e)
+ case *map[string]bool:
+ fastpathTV.EncMapStringBoolV(*v, e)
+ case map[float32]interface{}:
+ fastpathTV.EncMapFloat32IntfV(v, e)
+ case *map[float32]interface{}:
+ fastpathTV.EncMapFloat32IntfV(*v, e)
+ case map[float32]string:
+ fastpathTV.EncMapFloat32StringV(v, e)
+ case *map[float32]string:
+ fastpathTV.EncMapFloat32StringV(*v, e)
+ case map[float32]uint:
+ fastpathTV.EncMapFloat32UintV(v, e)
+ case *map[float32]uint:
+ fastpathTV.EncMapFloat32UintV(*v, e)
+ case map[float32]uint8:
+ fastpathTV.EncMapFloat32Uint8V(v, e)
+ case *map[float32]uint8:
+ fastpathTV.EncMapFloat32Uint8V(*v, e)
+ case map[float32]uint16:
+ fastpathTV.EncMapFloat32Uint16V(v, e)
+ case *map[float32]uint16:
+ fastpathTV.EncMapFloat32Uint16V(*v, e)
+ case map[float32]uint32:
+ fastpathTV.EncMapFloat32Uint32V(v, e)
+ case *map[float32]uint32:
+ fastpathTV.EncMapFloat32Uint32V(*v, e)
+ case map[float32]uint64:
+ fastpathTV.EncMapFloat32Uint64V(v, e)
+ case *map[float32]uint64:
+ fastpathTV.EncMapFloat32Uint64V(*v, e)
+ case map[float32]uintptr:
+ fastpathTV.EncMapFloat32UintptrV(v, e)
+ case *map[float32]uintptr:
+ fastpathTV.EncMapFloat32UintptrV(*v, e)
+ case map[float32]int:
+ fastpathTV.EncMapFloat32IntV(v, e)
+ case *map[float32]int:
+ fastpathTV.EncMapFloat32IntV(*v, e)
+ case map[float32]int8:
+ fastpathTV.EncMapFloat32Int8V(v, e)
+ case *map[float32]int8:
+ fastpathTV.EncMapFloat32Int8V(*v, e)
+ case map[float32]int16:
+ fastpathTV.EncMapFloat32Int16V(v, e)
+ case *map[float32]int16:
+ fastpathTV.EncMapFloat32Int16V(*v, e)
+ case map[float32]int32:
+ fastpathTV.EncMapFloat32Int32V(v, e)
+ case *map[float32]int32:
+ fastpathTV.EncMapFloat32Int32V(*v, e)
+ case map[float32]int64:
+ fastpathTV.EncMapFloat32Int64V(v, e)
+ case *map[float32]int64:
+ fastpathTV.EncMapFloat32Int64V(*v, e)
+ case map[float32]float32:
+ fastpathTV.EncMapFloat32Float32V(v, e)
+ case *map[float32]float32:
+ fastpathTV.EncMapFloat32Float32V(*v, e)
+ case map[float32]float64:
+ fastpathTV.EncMapFloat32Float64V(v, e)
+ case *map[float32]float64:
+ fastpathTV.EncMapFloat32Float64V(*v, e)
+ case map[float32]bool:
+ fastpathTV.EncMapFloat32BoolV(v, e)
+ case *map[float32]bool:
+ fastpathTV.EncMapFloat32BoolV(*v, e)
+ case map[float64]interface{}:
+ fastpathTV.EncMapFloat64IntfV(v, e)
+ case *map[float64]interface{}:
+ fastpathTV.EncMapFloat64IntfV(*v, e)
+ case map[float64]string:
+ fastpathTV.EncMapFloat64StringV(v, e)
+ case *map[float64]string:
+ fastpathTV.EncMapFloat64StringV(*v, e)
+ case map[float64]uint:
+ fastpathTV.EncMapFloat64UintV(v, e)
+ case *map[float64]uint:
+ fastpathTV.EncMapFloat64UintV(*v, e)
+ case map[float64]uint8:
+ fastpathTV.EncMapFloat64Uint8V(v, e)
+ case *map[float64]uint8:
+ fastpathTV.EncMapFloat64Uint8V(*v, e)
+ case map[float64]uint16:
+ fastpathTV.EncMapFloat64Uint16V(v, e)
+ case *map[float64]uint16:
+ fastpathTV.EncMapFloat64Uint16V(*v, e)
+ case map[float64]uint32:
+ fastpathTV.EncMapFloat64Uint32V(v, e)
+ case *map[float64]uint32:
+ fastpathTV.EncMapFloat64Uint32V(*v, e)
+ case map[float64]uint64:
+ fastpathTV.EncMapFloat64Uint64V(v, e)
+ case *map[float64]uint64:
+ fastpathTV.EncMapFloat64Uint64V(*v, e)
+ case map[float64]uintptr:
+ fastpathTV.EncMapFloat64UintptrV(v, e)
+ case *map[float64]uintptr:
+ fastpathTV.EncMapFloat64UintptrV(*v, e)
+ case map[float64]int:
+ fastpathTV.EncMapFloat64IntV(v, e)
+ case *map[float64]int:
+ fastpathTV.EncMapFloat64IntV(*v, e)
+ case map[float64]int8:
+ fastpathTV.EncMapFloat64Int8V(v, e)
+ case *map[float64]int8:
+ fastpathTV.EncMapFloat64Int8V(*v, e)
+ case map[float64]int16:
+ fastpathTV.EncMapFloat64Int16V(v, e)
+ case *map[float64]int16:
+ fastpathTV.EncMapFloat64Int16V(*v, e)
+ case map[float64]int32:
+ fastpathTV.EncMapFloat64Int32V(v, e)
+ case *map[float64]int32:
+ fastpathTV.EncMapFloat64Int32V(*v, e)
+ case map[float64]int64:
+ fastpathTV.EncMapFloat64Int64V(v, e)
+ case *map[float64]int64:
+ fastpathTV.EncMapFloat64Int64V(*v, e)
+ case map[float64]float32:
+ fastpathTV.EncMapFloat64Float32V(v, e)
+ case *map[float64]float32:
+ fastpathTV.EncMapFloat64Float32V(*v, e)
+ case map[float64]float64:
+ fastpathTV.EncMapFloat64Float64V(v, e)
+ case *map[float64]float64:
+ fastpathTV.EncMapFloat64Float64V(*v, e)
+ case map[float64]bool:
+ fastpathTV.EncMapFloat64BoolV(v, e)
+ case *map[float64]bool:
+ fastpathTV.EncMapFloat64BoolV(*v, e)
+ case map[uint]interface{}:
+ fastpathTV.EncMapUintIntfV(v, e)
+ case *map[uint]interface{}:
+ fastpathTV.EncMapUintIntfV(*v, e)
+ case map[uint]string:
+ fastpathTV.EncMapUintStringV(v, e)
+ case *map[uint]string:
+ fastpathTV.EncMapUintStringV(*v, e)
+ case map[uint]uint:
+ fastpathTV.EncMapUintUintV(v, e)
+ case *map[uint]uint:
+ fastpathTV.EncMapUintUintV(*v, e)
+ case map[uint]uint8:
+ fastpathTV.EncMapUintUint8V(v, e)
+ case *map[uint]uint8:
+ fastpathTV.EncMapUintUint8V(*v, e)
+ case map[uint]uint16:
+ fastpathTV.EncMapUintUint16V(v, e)
+ case *map[uint]uint16:
+ fastpathTV.EncMapUintUint16V(*v, e)
+ case map[uint]uint32:
+ fastpathTV.EncMapUintUint32V(v, e)
+ case *map[uint]uint32:
+ fastpathTV.EncMapUintUint32V(*v, e)
+ case map[uint]uint64:
+ fastpathTV.EncMapUintUint64V(v, e)
+ case *map[uint]uint64:
+ fastpathTV.EncMapUintUint64V(*v, e)
+ case map[uint]uintptr:
+ fastpathTV.EncMapUintUintptrV(v, e)
+ case *map[uint]uintptr:
+ fastpathTV.EncMapUintUintptrV(*v, e)
+ case map[uint]int:
+ fastpathTV.EncMapUintIntV(v, e)
+ case *map[uint]int:
+ fastpathTV.EncMapUintIntV(*v, e)
+ case map[uint]int8:
+ fastpathTV.EncMapUintInt8V(v, e)
+ case *map[uint]int8:
+ fastpathTV.EncMapUintInt8V(*v, e)
+ case map[uint]int16:
+ fastpathTV.EncMapUintInt16V(v, e)
+ case *map[uint]int16:
+ fastpathTV.EncMapUintInt16V(*v, e)
+ case map[uint]int32:
+ fastpathTV.EncMapUintInt32V(v, e)
+ case *map[uint]int32:
+ fastpathTV.EncMapUintInt32V(*v, e)
+ case map[uint]int64:
+ fastpathTV.EncMapUintInt64V(v, e)
+ case *map[uint]int64:
+ fastpathTV.EncMapUintInt64V(*v, e)
+ case map[uint]float32:
+ fastpathTV.EncMapUintFloat32V(v, e)
+ case *map[uint]float32:
+ fastpathTV.EncMapUintFloat32V(*v, e)
+ case map[uint]float64:
+ fastpathTV.EncMapUintFloat64V(v, e)
+ case *map[uint]float64:
+ fastpathTV.EncMapUintFloat64V(*v, e)
+ case map[uint]bool:
+ fastpathTV.EncMapUintBoolV(v, e)
+ case *map[uint]bool:
+ fastpathTV.EncMapUintBoolV(*v, e)
+ case map[uint8]interface{}:
+ fastpathTV.EncMapUint8IntfV(v, e)
+ case *map[uint8]interface{}:
+ fastpathTV.EncMapUint8IntfV(*v, e)
+ case map[uint8]string:
+ fastpathTV.EncMapUint8StringV(v, e)
+ case *map[uint8]string:
+ fastpathTV.EncMapUint8StringV(*v, e)
+ case map[uint8]uint:
+ fastpathTV.EncMapUint8UintV(v, e)
+ case *map[uint8]uint:
+ fastpathTV.EncMapUint8UintV(*v, e)
+ case map[uint8]uint8:
+ fastpathTV.EncMapUint8Uint8V(v, e)
+ case *map[uint8]uint8:
+ fastpathTV.EncMapUint8Uint8V(*v, e)
+ case map[uint8]uint16:
+ fastpathTV.EncMapUint8Uint16V(v, e)
+ case *map[uint8]uint16:
+ fastpathTV.EncMapUint8Uint16V(*v, e)
+ case map[uint8]uint32:
+ fastpathTV.EncMapUint8Uint32V(v, e)
+ case *map[uint8]uint32:
+ fastpathTV.EncMapUint8Uint32V(*v, e)
+ case map[uint8]uint64:
+ fastpathTV.EncMapUint8Uint64V(v, e)
+ case *map[uint8]uint64:
+ fastpathTV.EncMapUint8Uint64V(*v, e)
+ case map[uint8]uintptr:
+ fastpathTV.EncMapUint8UintptrV(v, e)
+ case *map[uint8]uintptr:
+ fastpathTV.EncMapUint8UintptrV(*v, e)
+ case map[uint8]int:
+ fastpathTV.EncMapUint8IntV(v, e)
+ case *map[uint8]int:
+ fastpathTV.EncMapUint8IntV(*v, e)
+ case map[uint8]int8:
+ fastpathTV.EncMapUint8Int8V(v, e)
+ case *map[uint8]int8:
+ fastpathTV.EncMapUint8Int8V(*v, e)
+ case map[uint8]int16:
+ fastpathTV.EncMapUint8Int16V(v, e)
+ case *map[uint8]int16:
+ fastpathTV.EncMapUint8Int16V(*v, e)
+ case map[uint8]int32:
+ fastpathTV.EncMapUint8Int32V(v, e)
+ case *map[uint8]int32:
+ fastpathTV.EncMapUint8Int32V(*v, e)
+ case map[uint8]int64:
+ fastpathTV.EncMapUint8Int64V(v, e)
+ case *map[uint8]int64:
+ fastpathTV.EncMapUint8Int64V(*v, e)
+ case map[uint8]float32:
+ fastpathTV.EncMapUint8Float32V(v, e)
+ case *map[uint8]float32:
+ fastpathTV.EncMapUint8Float32V(*v, e)
+ case map[uint8]float64:
+ fastpathTV.EncMapUint8Float64V(v, e)
+ case *map[uint8]float64:
+ fastpathTV.EncMapUint8Float64V(*v, e)
+ case map[uint8]bool:
+ fastpathTV.EncMapUint8BoolV(v, e)
+ case *map[uint8]bool:
+ fastpathTV.EncMapUint8BoolV(*v, e)
+ case map[uint16]interface{}:
+ fastpathTV.EncMapUint16IntfV(v, e)
+ case *map[uint16]interface{}:
+ fastpathTV.EncMapUint16IntfV(*v, e)
+ case map[uint16]string:
+ fastpathTV.EncMapUint16StringV(v, e)
+ case *map[uint16]string:
+ fastpathTV.EncMapUint16StringV(*v, e)
+ case map[uint16]uint:
+ fastpathTV.EncMapUint16UintV(v, e)
+ case *map[uint16]uint:
+ fastpathTV.EncMapUint16UintV(*v, e)
+ case map[uint16]uint8:
+ fastpathTV.EncMapUint16Uint8V(v, e)
+ case *map[uint16]uint8:
+ fastpathTV.EncMapUint16Uint8V(*v, e)
+ case map[uint16]uint16:
+ fastpathTV.EncMapUint16Uint16V(v, e)
+ case *map[uint16]uint16:
+ fastpathTV.EncMapUint16Uint16V(*v, e)
+ case map[uint16]uint32:
+ fastpathTV.EncMapUint16Uint32V(v, e)
+ case *map[uint16]uint32:
+ fastpathTV.EncMapUint16Uint32V(*v, e)
+ case map[uint16]uint64:
+ fastpathTV.EncMapUint16Uint64V(v, e)
+ case *map[uint16]uint64:
+ fastpathTV.EncMapUint16Uint64V(*v, e)
+ case map[uint16]uintptr:
+ fastpathTV.EncMapUint16UintptrV(v, e)
+ case *map[uint16]uintptr:
+ fastpathTV.EncMapUint16UintptrV(*v, e)
+ case map[uint16]int:
+ fastpathTV.EncMapUint16IntV(v, e)
+ case *map[uint16]int:
+ fastpathTV.EncMapUint16IntV(*v, e)
+ case map[uint16]int8:
+ fastpathTV.EncMapUint16Int8V(v, e)
+ case *map[uint16]int8:
+ fastpathTV.EncMapUint16Int8V(*v, e)
+ case map[uint16]int16:
+ fastpathTV.EncMapUint16Int16V(v, e)
+ case *map[uint16]int16:
+ fastpathTV.EncMapUint16Int16V(*v, e)
+ case map[uint16]int32:
+ fastpathTV.EncMapUint16Int32V(v, e)
+ case *map[uint16]int32:
+ fastpathTV.EncMapUint16Int32V(*v, e)
+ case map[uint16]int64:
+ fastpathTV.EncMapUint16Int64V(v, e)
+ case *map[uint16]int64:
+ fastpathTV.EncMapUint16Int64V(*v, e)
+ case map[uint16]float32:
+ fastpathTV.EncMapUint16Float32V(v, e)
+ case *map[uint16]float32:
+ fastpathTV.EncMapUint16Float32V(*v, e)
+ case map[uint16]float64:
+ fastpathTV.EncMapUint16Float64V(v, e)
+ case *map[uint16]float64:
+ fastpathTV.EncMapUint16Float64V(*v, e)
+ case map[uint16]bool:
+ fastpathTV.EncMapUint16BoolV(v, e)
+ case *map[uint16]bool:
+ fastpathTV.EncMapUint16BoolV(*v, e)
+ case map[uint32]interface{}:
+ fastpathTV.EncMapUint32IntfV(v, e)
+ case *map[uint32]interface{}:
+ fastpathTV.EncMapUint32IntfV(*v, e)
+ case map[uint32]string:
+ fastpathTV.EncMapUint32StringV(v, e)
+ case *map[uint32]string:
+ fastpathTV.EncMapUint32StringV(*v, e)
+ case map[uint32]uint:
+ fastpathTV.EncMapUint32UintV(v, e)
+ case *map[uint32]uint:
+ fastpathTV.EncMapUint32UintV(*v, e)
+ case map[uint32]uint8:
+ fastpathTV.EncMapUint32Uint8V(v, e)
+ case *map[uint32]uint8:
+ fastpathTV.EncMapUint32Uint8V(*v, e)
+ case map[uint32]uint16:
+ fastpathTV.EncMapUint32Uint16V(v, e)
+ case *map[uint32]uint16:
+ fastpathTV.EncMapUint32Uint16V(*v, e)
+ case map[uint32]uint32:
+ fastpathTV.EncMapUint32Uint32V(v, e)
+ case *map[uint32]uint32:
+ fastpathTV.EncMapUint32Uint32V(*v, e)
+ case map[uint32]uint64:
+ fastpathTV.EncMapUint32Uint64V(v, e)
+ case *map[uint32]uint64:
+ fastpathTV.EncMapUint32Uint64V(*v, e)
+ case map[uint32]uintptr:
+ fastpathTV.EncMapUint32UintptrV(v, e)
+ case *map[uint32]uintptr:
+ fastpathTV.EncMapUint32UintptrV(*v, e)
+ case map[uint32]int:
+ fastpathTV.EncMapUint32IntV(v, e)
+ case *map[uint32]int:
+ fastpathTV.EncMapUint32IntV(*v, e)
+ case map[uint32]int8:
+ fastpathTV.EncMapUint32Int8V(v, e)
+ case *map[uint32]int8:
+ fastpathTV.EncMapUint32Int8V(*v, e)
+ case map[uint32]int16:
+ fastpathTV.EncMapUint32Int16V(v, e)
+ case *map[uint32]int16:
+ fastpathTV.EncMapUint32Int16V(*v, e)
+ case map[uint32]int32:
+ fastpathTV.EncMapUint32Int32V(v, e)
+ case *map[uint32]int32:
+ fastpathTV.EncMapUint32Int32V(*v, e)
+ case map[uint32]int64:
+ fastpathTV.EncMapUint32Int64V(v, e)
+ case *map[uint32]int64:
+ fastpathTV.EncMapUint32Int64V(*v, e)
+ case map[uint32]float32:
+ fastpathTV.EncMapUint32Float32V(v, e)
+ case *map[uint32]float32:
+ fastpathTV.EncMapUint32Float32V(*v, e)
+ case map[uint32]float64:
+ fastpathTV.EncMapUint32Float64V(v, e)
+ case *map[uint32]float64:
+ fastpathTV.EncMapUint32Float64V(*v, e)
+ case map[uint32]bool:
+ fastpathTV.EncMapUint32BoolV(v, e)
+ case *map[uint32]bool:
+ fastpathTV.EncMapUint32BoolV(*v, e)
+ case map[uint64]interface{}:
+ fastpathTV.EncMapUint64IntfV(v, e)
+ case *map[uint64]interface{}:
+ fastpathTV.EncMapUint64IntfV(*v, e)
+ case map[uint64]string:
+ fastpathTV.EncMapUint64StringV(v, e)
+ case *map[uint64]string:
+ fastpathTV.EncMapUint64StringV(*v, e)
+ case map[uint64]uint:
+ fastpathTV.EncMapUint64UintV(v, e)
+ case *map[uint64]uint:
+ fastpathTV.EncMapUint64UintV(*v, e)
+ case map[uint64]uint8:
+ fastpathTV.EncMapUint64Uint8V(v, e)
+ case *map[uint64]uint8:
+ fastpathTV.EncMapUint64Uint8V(*v, e)
+ case map[uint64]uint16:
+ fastpathTV.EncMapUint64Uint16V(v, e)
+ case *map[uint64]uint16:
+ fastpathTV.EncMapUint64Uint16V(*v, e)
+ case map[uint64]uint32:
+ fastpathTV.EncMapUint64Uint32V(v, e)
+ case *map[uint64]uint32:
+ fastpathTV.EncMapUint64Uint32V(*v, e)
+ case map[uint64]uint64:
+ fastpathTV.EncMapUint64Uint64V(v, e)
+ case *map[uint64]uint64:
+ fastpathTV.EncMapUint64Uint64V(*v, e)
+ case map[uint64]uintptr:
+ fastpathTV.EncMapUint64UintptrV(v, e)
+ case *map[uint64]uintptr:
+ fastpathTV.EncMapUint64UintptrV(*v, e)
+ case map[uint64]int:
+ fastpathTV.EncMapUint64IntV(v, e)
+ case *map[uint64]int:
+ fastpathTV.EncMapUint64IntV(*v, e)
+ case map[uint64]int8:
+ fastpathTV.EncMapUint64Int8V(v, e)
+ case *map[uint64]int8:
+ fastpathTV.EncMapUint64Int8V(*v, e)
+ case map[uint64]int16:
+ fastpathTV.EncMapUint64Int16V(v, e)
+ case *map[uint64]int16:
+ fastpathTV.EncMapUint64Int16V(*v, e)
+ case map[uint64]int32:
+ fastpathTV.EncMapUint64Int32V(v, e)
+ case *map[uint64]int32:
+ fastpathTV.EncMapUint64Int32V(*v, e)
+ case map[uint64]int64:
+ fastpathTV.EncMapUint64Int64V(v, e)
+ case *map[uint64]int64:
+ fastpathTV.EncMapUint64Int64V(*v, e)
+ case map[uint64]float32:
+ fastpathTV.EncMapUint64Float32V(v, e)
+ case *map[uint64]float32:
+ fastpathTV.EncMapUint64Float32V(*v, e)
+ case map[uint64]float64:
+ fastpathTV.EncMapUint64Float64V(v, e)
+ case *map[uint64]float64:
+ fastpathTV.EncMapUint64Float64V(*v, e)
+ case map[uint64]bool:
+ fastpathTV.EncMapUint64BoolV(v, e)
+ case *map[uint64]bool:
+ fastpathTV.EncMapUint64BoolV(*v, e)
+ case map[uintptr]interface{}:
+ fastpathTV.EncMapUintptrIntfV(v, e)
+ case *map[uintptr]interface{}:
+ fastpathTV.EncMapUintptrIntfV(*v, e)
+ case map[uintptr]string:
+ fastpathTV.EncMapUintptrStringV(v, e)
+ case *map[uintptr]string:
+ fastpathTV.EncMapUintptrStringV(*v, e)
+ case map[uintptr]uint:
+ fastpathTV.EncMapUintptrUintV(v, e)
+ case *map[uintptr]uint:
+ fastpathTV.EncMapUintptrUintV(*v, e)
+ case map[uintptr]uint8:
+ fastpathTV.EncMapUintptrUint8V(v, e)
+ case *map[uintptr]uint8:
+ fastpathTV.EncMapUintptrUint8V(*v, e)
+ case map[uintptr]uint16:
+ fastpathTV.EncMapUintptrUint16V(v, e)
+ case *map[uintptr]uint16:
+ fastpathTV.EncMapUintptrUint16V(*v, e)
+ case map[uintptr]uint32:
+ fastpathTV.EncMapUintptrUint32V(v, e)
+ case *map[uintptr]uint32:
+ fastpathTV.EncMapUintptrUint32V(*v, e)
+ case map[uintptr]uint64:
+ fastpathTV.EncMapUintptrUint64V(v, e)
+ case *map[uintptr]uint64:
+ fastpathTV.EncMapUintptrUint64V(*v, e)
+ case map[uintptr]uintptr:
+ fastpathTV.EncMapUintptrUintptrV(v, e)
+ case *map[uintptr]uintptr:
+ fastpathTV.EncMapUintptrUintptrV(*v, e)
+ case map[uintptr]int:
+ fastpathTV.EncMapUintptrIntV(v, e)
+ case *map[uintptr]int:
+ fastpathTV.EncMapUintptrIntV(*v, e)
+ case map[uintptr]int8:
+ fastpathTV.EncMapUintptrInt8V(v, e)
+ case *map[uintptr]int8:
+ fastpathTV.EncMapUintptrInt8V(*v, e)
+ case map[uintptr]int16:
+ fastpathTV.EncMapUintptrInt16V(v, e)
+ case *map[uintptr]int16:
+ fastpathTV.EncMapUintptrInt16V(*v, e)
+ case map[uintptr]int32:
+ fastpathTV.EncMapUintptrInt32V(v, e)
+ case *map[uintptr]int32:
+ fastpathTV.EncMapUintptrInt32V(*v, e)
+ case map[uintptr]int64:
+ fastpathTV.EncMapUintptrInt64V(v, e)
+ case *map[uintptr]int64:
+ fastpathTV.EncMapUintptrInt64V(*v, e)
+ case map[uintptr]float32:
+ fastpathTV.EncMapUintptrFloat32V(v, e)
+ case *map[uintptr]float32:
+ fastpathTV.EncMapUintptrFloat32V(*v, e)
+ case map[uintptr]float64:
+ fastpathTV.EncMapUintptrFloat64V(v, e)
+ case *map[uintptr]float64:
+ fastpathTV.EncMapUintptrFloat64V(*v, e)
+ case map[uintptr]bool:
+ fastpathTV.EncMapUintptrBoolV(v, e)
+ case *map[uintptr]bool:
+ fastpathTV.EncMapUintptrBoolV(*v, e)
+ case map[int]interface{}:
+ fastpathTV.EncMapIntIntfV(v, e)
+ case *map[int]interface{}:
+ fastpathTV.EncMapIntIntfV(*v, e)
+ case map[int]string:
+ fastpathTV.EncMapIntStringV(v, e)
+ case *map[int]string:
+ fastpathTV.EncMapIntStringV(*v, e)
+ case map[int]uint:
+ fastpathTV.EncMapIntUintV(v, e)
+ case *map[int]uint:
+ fastpathTV.EncMapIntUintV(*v, e)
+ case map[int]uint8:
+ fastpathTV.EncMapIntUint8V(v, e)
+ case *map[int]uint8:
+ fastpathTV.EncMapIntUint8V(*v, e)
+ case map[int]uint16:
+ fastpathTV.EncMapIntUint16V(v, e)
+ case *map[int]uint16:
+ fastpathTV.EncMapIntUint16V(*v, e)
+ case map[int]uint32:
+ fastpathTV.EncMapIntUint32V(v, e)
+ case *map[int]uint32:
+ fastpathTV.EncMapIntUint32V(*v, e)
+ case map[int]uint64:
+ fastpathTV.EncMapIntUint64V(v, e)
+ case *map[int]uint64:
+ fastpathTV.EncMapIntUint64V(*v, e)
+ case map[int]uintptr:
+ fastpathTV.EncMapIntUintptrV(v, e)
+ case *map[int]uintptr:
+ fastpathTV.EncMapIntUintptrV(*v, e)
+ case map[int]int:
+ fastpathTV.EncMapIntIntV(v, e)
+ case *map[int]int:
+ fastpathTV.EncMapIntIntV(*v, e)
+ case map[int]int8:
+ fastpathTV.EncMapIntInt8V(v, e)
+ case *map[int]int8:
+ fastpathTV.EncMapIntInt8V(*v, e)
+ case map[int]int16:
+ fastpathTV.EncMapIntInt16V(v, e)
+ case *map[int]int16:
+ fastpathTV.EncMapIntInt16V(*v, e)
+ case map[int]int32:
+ fastpathTV.EncMapIntInt32V(v, e)
+ case *map[int]int32:
+ fastpathTV.EncMapIntInt32V(*v, e)
+ case map[int]int64:
+ fastpathTV.EncMapIntInt64V(v, e)
+ case *map[int]int64:
+ fastpathTV.EncMapIntInt64V(*v, e)
+ case map[int]float32:
+ fastpathTV.EncMapIntFloat32V(v, e)
+ case *map[int]float32:
+ fastpathTV.EncMapIntFloat32V(*v, e)
+ case map[int]float64:
+ fastpathTV.EncMapIntFloat64V(v, e)
+ case *map[int]float64:
+ fastpathTV.EncMapIntFloat64V(*v, e)
+ case map[int]bool:
+ fastpathTV.EncMapIntBoolV(v, e)
+ case *map[int]bool:
+ fastpathTV.EncMapIntBoolV(*v, e)
+ case map[int8]interface{}:
+ fastpathTV.EncMapInt8IntfV(v, e)
+ case *map[int8]interface{}:
+ fastpathTV.EncMapInt8IntfV(*v, e)
+ case map[int8]string:
+ fastpathTV.EncMapInt8StringV(v, e)
+ case *map[int8]string:
+ fastpathTV.EncMapInt8StringV(*v, e)
+ case map[int8]uint:
+ fastpathTV.EncMapInt8UintV(v, e)
+ case *map[int8]uint:
+ fastpathTV.EncMapInt8UintV(*v, e)
+ case map[int8]uint8:
+ fastpathTV.EncMapInt8Uint8V(v, e)
+ case *map[int8]uint8:
+ fastpathTV.EncMapInt8Uint8V(*v, e)
+ case map[int8]uint16:
+ fastpathTV.EncMapInt8Uint16V(v, e)
+ case *map[int8]uint16:
+ fastpathTV.EncMapInt8Uint16V(*v, e)
+ case map[int8]uint32:
+ fastpathTV.EncMapInt8Uint32V(v, e)
+ case *map[int8]uint32:
+ fastpathTV.EncMapInt8Uint32V(*v, e)
+ case map[int8]uint64:
+ fastpathTV.EncMapInt8Uint64V(v, e)
+ case *map[int8]uint64:
+ fastpathTV.EncMapInt8Uint64V(*v, e)
+ case map[int8]uintptr:
+ fastpathTV.EncMapInt8UintptrV(v, e)
+ case *map[int8]uintptr:
+ fastpathTV.EncMapInt8UintptrV(*v, e)
+ case map[int8]int:
+ fastpathTV.EncMapInt8IntV(v, e)
+ case *map[int8]int:
+ fastpathTV.EncMapInt8IntV(*v, e)
+ case map[int8]int8:
+ fastpathTV.EncMapInt8Int8V(v, e)
+ case *map[int8]int8:
+ fastpathTV.EncMapInt8Int8V(*v, e)
+ case map[int8]int16:
+ fastpathTV.EncMapInt8Int16V(v, e)
+ case *map[int8]int16:
+ fastpathTV.EncMapInt8Int16V(*v, e)
+ case map[int8]int32:
+ fastpathTV.EncMapInt8Int32V(v, e)
+ case *map[int8]int32:
+ fastpathTV.EncMapInt8Int32V(*v, e)
+ case map[int8]int64:
+ fastpathTV.EncMapInt8Int64V(v, e)
+ case *map[int8]int64:
+ fastpathTV.EncMapInt8Int64V(*v, e)
+ case map[int8]float32:
+ fastpathTV.EncMapInt8Float32V(v, e)
+ case *map[int8]float32:
+ fastpathTV.EncMapInt8Float32V(*v, e)
+ case map[int8]float64:
+ fastpathTV.EncMapInt8Float64V(v, e)
+ case *map[int8]float64:
+ fastpathTV.EncMapInt8Float64V(*v, e)
+ case map[int8]bool:
+ fastpathTV.EncMapInt8BoolV(v, e)
+ case *map[int8]bool:
+ fastpathTV.EncMapInt8BoolV(*v, e)
+ case map[int16]interface{}:
+ fastpathTV.EncMapInt16IntfV(v, e)
+ case *map[int16]interface{}:
+ fastpathTV.EncMapInt16IntfV(*v, e)
+ case map[int16]string:
+ fastpathTV.EncMapInt16StringV(v, e)
+ case *map[int16]string:
+ fastpathTV.EncMapInt16StringV(*v, e)
+ case map[int16]uint:
+ fastpathTV.EncMapInt16UintV(v, e)
+ case *map[int16]uint:
+ fastpathTV.EncMapInt16UintV(*v, e)
+ case map[int16]uint8:
+ fastpathTV.EncMapInt16Uint8V(v, e)
+ case *map[int16]uint8:
+ fastpathTV.EncMapInt16Uint8V(*v, e)
+ case map[int16]uint16:
+ fastpathTV.EncMapInt16Uint16V(v, e)
+ case *map[int16]uint16:
+ fastpathTV.EncMapInt16Uint16V(*v, e)
+ case map[int16]uint32:
+ fastpathTV.EncMapInt16Uint32V(v, e)
+ case *map[int16]uint32:
+ fastpathTV.EncMapInt16Uint32V(*v, e)
+ case map[int16]uint64:
+ fastpathTV.EncMapInt16Uint64V(v, e)
+ case *map[int16]uint64:
+ fastpathTV.EncMapInt16Uint64V(*v, e)
+ case map[int16]uintptr:
+ fastpathTV.EncMapInt16UintptrV(v, e)
+ case *map[int16]uintptr:
+ fastpathTV.EncMapInt16UintptrV(*v, e)
+ case map[int16]int:
+ fastpathTV.EncMapInt16IntV(v, e)
+ case *map[int16]int:
+ fastpathTV.EncMapInt16IntV(*v, e)
+ case map[int16]int8:
+ fastpathTV.EncMapInt16Int8V(v, e)
+ case *map[int16]int8:
+ fastpathTV.EncMapInt16Int8V(*v, e)
+ case map[int16]int16:
+ fastpathTV.EncMapInt16Int16V(v, e)
+ case *map[int16]int16:
+ fastpathTV.EncMapInt16Int16V(*v, e)
+ case map[int16]int32:
+ fastpathTV.EncMapInt16Int32V(v, e)
+ case *map[int16]int32:
+ fastpathTV.EncMapInt16Int32V(*v, e)
+ case map[int16]int64:
+ fastpathTV.EncMapInt16Int64V(v, e)
+ case *map[int16]int64:
+ fastpathTV.EncMapInt16Int64V(*v, e)
+ case map[int16]float32:
+ fastpathTV.EncMapInt16Float32V(v, e)
+ case *map[int16]float32:
+ fastpathTV.EncMapInt16Float32V(*v, e)
+ case map[int16]float64:
+ fastpathTV.EncMapInt16Float64V(v, e)
+ case *map[int16]float64:
+ fastpathTV.EncMapInt16Float64V(*v, e)
+ case map[int16]bool:
+ fastpathTV.EncMapInt16BoolV(v, e)
+ case *map[int16]bool:
+ fastpathTV.EncMapInt16BoolV(*v, e)
+ case map[int32]interface{}:
+ fastpathTV.EncMapInt32IntfV(v, e)
+ case *map[int32]interface{}:
+ fastpathTV.EncMapInt32IntfV(*v, e)
+ case map[int32]string:
+ fastpathTV.EncMapInt32StringV(v, e)
+ case *map[int32]string:
+ fastpathTV.EncMapInt32StringV(*v, e)
+ case map[int32]uint:
+ fastpathTV.EncMapInt32UintV(v, e)
+ case *map[int32]uint:
+ fastpathTV.EncMapInt32UintV(*v, e)
+ case map[int32]uint8:
+ fastpathTV.EncMapInt32Uint8V(v, e)
+ case *map[int32]uint8:
+ fastpathTV.EncMapInt32Uint8V(*v, e)
+ case map[int32]uint16:
+ fastpathTV.EncMapInt32Uint16V(v, e)
+ case *map[int32]uint16:
+ fastpathTV.EncMapInt32Uint16V(*v, e)
+ case map[int32]uint32:
+ fastpathTV.EncMapInt32Uint32V(v, e)
+ case *map[int32]uint32:
+ fastpathTV.EncMapInt32Uint32V(*v, e)
+ case map[int32]uint64:
+ fastpathTV.EncMapInt32Uint64V(v, e)
+ case *map[int32]uint64:
+ fastpathTV.EncMapInt32Uint64V(*v, e)
+ case map[int32]uintptr:
+ fastpathTV.EncMapInt32UintptrV(v, e)
+ case *map[int32]uintptr:
+ fastpathTV.EncMapInt32UintptrV(*v, e)
+ case map[int32]int:
+ fastpathTV.EncMapInt32IntV(v, e)
+ case *map[int32]int:
+ fastpathTV.EncMapInt32IntV(*v, e)
+ case map[int32]int8:
+ fastpathTV.EncMapInt32Int8V(v, e)
+ case *map[int32]int8:
+ fastpathTV.EncMapInt32Int8V(*v, e)
+ case map[int32]int16:
+ fastpathTV.EncMapInt32Int16V(v, e)
+ case *map[int32]int16:
+ fastpathTV.EncMapInt32Int16V(*v, e)
+ case map[int32]int32:
+ fastpathTV.EncMapInt32Int32V(v, e)
+ case *map[int32]int32:
+ fastpathTV.EncMapInt32Int32V(*v, e)
+ case map[int32]int64:
+ fastpathTV.EncMapInt32Int64V(v, e)
+ case *map[int32]int64:
+ fastpathTV.EncMapInt32Int64V(*v, e)
+ case map[int32]float32:
+ fastpathTV.EncMapInt32Float32V(v, e)
+ case *map[int32]float32:
+ fastpathTV.EncMapInt32Float32V(*v, e)
+ case map[int32]float64:
+ fastpathTV.EncMapInt32Float64V(v, e)
+ case *map[int32]float64:
+ fastpathTV.EncMapInt32Float64V(*v, e)
+ case map[int32]bool:
+ fastpathTV.EncMapInt32BoolV(v, e)
+ case *map[int32]bool:
+ fastpathTV.EncMapInt32BoolV(*v, e)
+ case map[int64]interface{}:
+ fastpathTV.EncMapInt64IntfV(v, e)
+ case *map[int64]interface{}:
+ fastpathTV.EncMapInt64IntfV(*v, e)
+ case map[int64]string:
+ fastpathTV.EncMapInt64StringV(v, e)
+ case *map[int64]string:
+ fastpathTV.EncMapInt64StringV(*v, e)
+ case map[int64]uint:
+ fastpathTV.EncMapInt64UintV(v, e)
+ case *map[int64]uint:
+ fastpathTV.EncMapInt64UintV(*v, e)
+ case map[int64]uint8:
+ fastpathTV.EncMapInt64Uint8V(v, e)
+ case *map[int64]uint8:
+ fastpathTV.EncMapInt64Uint8V(*v, e)
+ case map[int64]uint16:
+ fastpathTV.EncMapInt64Uint16V(v, e)
+ case *map[int64]uint16:
+ fastpathTV.EncMapInt64Uint16V(*v, e)
+ case map[int64]uint32:
+ fastpathTV.EncMapInt64Uint32V(v, e)
+ case *map[int64]uint32:
+ fastpathTV.EncMapInt64Uint32V(*v, e)
+ case map[int64]uint64:
+ fastpathTV.EncMapInt64Uint64V(v, e)
+ case *map[int64]uint64:
+ fastpathTV.EncMapInt64Uint64V(*v, e)
+ case map[int64]uintptr:
+ fastpathTV.EncMapInt64UintptrV(v, e)
+ case *map[int64]uintptr:
+ fastpathTV.EncMapInt64UintptrV(*v, e)
+ case map[int64]int:
+ fastpathTV.EncMapInt64IntV(v, e)
+ case *map[int64]int:
+ fastpathTV.EncMapInt64IntV(*v, e)
+ case map[int64]int8:
+ fastpathTV.EncMapInt64Int8V(v, e)
+ case *map[int64]int8:
+ fastpathTV.EncMapInt64Int8V(*v, e)
+ case map[int64]int16:
+ fastpathTV.EncMapInt64Int16V(v, e)
+ case *map[int64]int16:
+ fastpathTV.EncMapInt64Int16V(*v, e)
+ case map[int64]int32:
+ fastpathTV.EncMapInt64Int32V(v, e)
+ case *map[int64]int32:
+ fastpathTV.EncMapInt64Int32V(*v, e)
+ case map[int64]int64:
+ fastpathTV.EncMapInt64Int64V(v, e)
+ case *map[int64]int64:
+ fastpathTV.EncMapInt64Int64V(*v, e)
+ case map[int64]float32:
+ fastpathTV.EncMapInt64Float32V(v, e)
+ case *map[int64]float32:
+ fastpathTV.EncMapInt64Float32V(*v, e)
+ case map[int64]float64:
+ fastpathTV.EncMapInt64Float64V(v, e)
+ case *map[int64]float64:
+ fastpathTV.EncMapInt64Float64V(*v, e)
+ case map[int64]bool:
+ fastpathTV.EncMapInt64BoolV(v, e)
+ case *map[int64]bool:
+ fastpathTV.EncMapInt64BoolV(*v, e)
+ case map[bool]interface{}:
+ fastpathTV.EncMapBoolIntfV(v, e)
+ case *map[bool]interface{}:
+ fastpathTV.EncMapBoolIntfV(*v, e)
+ case map[bool]string:
+ fastpathTV.EncMapBoolStringV(v, e)
+ case *map[bool]string:
+ fastpathTV.EncMapBoolStringV(*v, e)
+ case map[bool]uint:
+ fastpathTV.EncMapBoolUintV(v, e)
+ case *map[bool]uint:
+ fastpathTV.EncMapBoolUintV(*v, e)
+ case map[bool]uint8:
+ fastpathTV.EncMapBoolUint8V(v, e)
+ case *map[bool]uint8:
+ fastpathTV.EncMapBoolUint8V(*v, e)
+ case map[bool]uint16:
+ fastpathTV.EncMapBoolUint16V(v, e)
+ case *map[bool]uint16:
+ fastpathTV.EncMapBoolUint16V(*v, e)
+ case map[bool]uint32:
+ fastpathTV.EncMapBoolUint32V(v, e)
+ case *map[bool]uint32:
+ fastpathTV.EncMapBoolUint32V(*v, e)
+ case map[bool]uint64:
+ fastpathTV.EncMapBoolUint64V(v, e)
+ case *map[bool]uint64:
+ fastpathTV.EncMapBoolUint64V(*v, e)
+ case map[bool]uintptr:
+ fastpathTV.EncMapBoolUintptrV(v, e)
+ case *map[bool]uintptr:
+ fastpathTV.EncMapBoolUintptrV(*v, e)
+ case map[bool]int:
+ fastpathTV.EncMapBoolIntV(v, e)
+ case *map[bool]int:
+ fastpathTV.EncMapBoolIntV(*v, e)
+ case map[bool]int8:
+ fastpathTV.EncMapBoolInt8V(v, e)
+ case *map[bool]int8:
+ fastpathTV.EncMapBoolInt8V(*v, e)
+ case map[bool]int16:
+ fastpathTV.EncMapBoolInt16V(v, e)
+ case *map[bool]int16:
+ fastpathTV.EncMapBoolInt16V(*v, e)
+ case map[bool]int32:
+ fastpathTV.EncMapBoolInt32V(v, e)
+ case *map[bool]int32:
+ fastpathTV.EncMapBoolInt32V(*v, e)
+ case map[bool]int64:
+ fastpathTV.EncMapBoolInt64V(v, e)
+ case *map[bool]int64:
+ fastpathTV.EncMapBoolInt64V(*v, e)
+ case map[bool]float32:
+ fastpathTV.EncMapBoolFloat32V(v, e)
+ case *map[bool]float32:
+ fastpathTV.EncMapBoolFloat32V(*v, e)
+ case map[bool]float64:
+ fastpathTV.EncMapBoolFloat64V(v, e)
+ case *map[bool]float64:
+ fastpathTV.EncMapBoolFloat64V(*v, e)
+ case map[bool]bool:
+ fastpathTV.EncMapBoolBoolV(v, e)
+ case *map[bool]bool:
+ fastpathTV.EncMapBoolBoolV(*v, e)
+
+ default:
+ _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
+ return false
+ }
+ return true
+}
+
+// -- -- fast path functions
+
+func (e *Encoder) fastpathEncSliceIntfR(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceIntfV(rv2i(rv).([]interface{}), e)
+ } else {
+ fastpathTV.EncSliceIntfV(rv2i(rv).([]interface{}), e)
+ }
+}
+func (_ fastpathT) EncSliceIntfV(v []interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ e.encode(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ e.encode(v2)
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceIntfV(v []interface{}, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ e.encode(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ e.encode(v2)
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceStringR(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceStringV(rv2i(rv).([]string), e)
+ } else {
+ fastpathTV.EncSliceStringV(rv2i(rv).([]string), e)
+ }
+}
+func (_ fastpathT) EncSliceStringV(v []string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceStringV(v []string, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceFloat32V(rv2i(rv).([]float32), e)
+ } else {
+ fastpathTV.EncSliceFloat32V(rv2i(rv).([]float32), e)
+ }
+}
+func (_ fastpathT) EncSliceFloat32V(v []float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeFloat32(v2)
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceFloat32V(v []float32, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeFloat32(v2)
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceFloat64V(rv2i(rv).([]float64), e)
+ } else {
+ fastpathTV.EncSliceFloat64V(rv2i(rv).([]float64), e)
+ }
+}
+func (_ fastpathT) EncSliceFloat64V(v []float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeFloat64(v2)
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceFloat64V(v []float64, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeFloat64(v2)
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceUintR(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceUintV(rv2i(rv).([]uint), e)
+ } else {
+ fastpathTV.EncSliceUintV(rv2i(rv).([]uint), e)
+ }
+}
+func (_ fastpathT) EncSliceUintV(v []uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceUintV(v []uint, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceUint8R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceUint8V(rv2i(rv).([]uint8), e)
+ } else {
+ fastpathTV.EncSliceUint8V(rv2i(rv).([]uint8), e)
+ }
+}
+func (_ fastpathT) EncSliceUint8V(v []uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceUint8V(v []uint8, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceUint16R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceUint16V(rv2i(rv).([]uint16), e)
+ } else {
+ fastpathTV.EncSliceUint16V(rv2i(rv).([]uint16), e)
+ }
+}
+func (_ fastpathT) EncSliceUint16V(v []uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceUint16V(v []uint16, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceUint32R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceUint32V(rv2i(rv).([]uint32), e)
+ } else {
+ fastpathTV.EncSliceUint32V(rv2i(rv).([]uint32), e)
+ }
+}
+func (_ fastpathT) EncSliceUint32V(v []uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceUint32V(v []uint32, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceUint64R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceUint64V(rv2i(rv).([]uint64), e)
+ } else {
+ fastpathTV.EncSliceUint64V(rv2i(rv).([]uint64), e)
+ }
+}
+func (_ fastpathT) EncSliceUint64V(v []uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceUint64V(v []uint64, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceUintptrV(rv2i(rv).([]uintptr), e)
+ } else {
+ fastpathTV.EncSliceUintptrV(rv2i(rv).([]uintptr), e)
+ }
+}
+func (_ fastpathT) EncSliceUintptrV(v []uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ e.encode(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ e.encode(v2)
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceUintptrV(v []uintptr, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ e.encode(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ e.encode(v2)
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceIntR(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceIntV(rv2i(rv).([]int), e)
+ } else {
+ fastpathTV.EncSliceIntV(rv2i(rv).([]int), e)
+ }
+}
+func (_ fastpathT) EncSliceIntV(v []int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceIntV(v []int, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceInt8R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceInt8V(rv2i(rv).([]int8), e)
+ } else {
+ fastpathTV.EncSliceInt8V(rv2i(rv).([]int8), e)
+ }
+}
+func (_ fastpathT) EncSliceInt8V(v []int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceInt8V(v []int8, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceInt16R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceInt16V(rv2i(rv).([]int16), e)
+ } else {
+ fastpathTV.EncSliceInt16V(rv2i(rv).([]int16), e)
+ }
+}
+func (_ fastpathT) EncSliceInt16V(v []int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceInt16V(v []int16, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceInt32R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceInt32V(rv2i(rv).([]int32), e)
+ } else {
+ fastpathTV.EncSliceInt32V(rv2i(rv).([]int32), e)
+ }
+}
+func (_ fastpathT) EncSliceInt32V(v []int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceInt32V(v []int32, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceInt64R(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceInt64V(rv2i(rv).([]int64), e)
+ } else {
+ fastpathTV.EncSliceInt64V(rv2i(rv).([]int64), e)
+ }
+}
+func (_ fastpathT) EncSliceInt64V(v []int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceInt64V(v []int64, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncSliceBoolR(f *codecFnInfo, rv reflect.Value) {
+ if f.ti.mbs {
+ fastpathTV.EncAsMapSliceBoolV(rv2i(rv).([]bool), e)
+ } else {
+ fastpathTV.EncSliceBoolV(rv2i(rv).([]bool), e)
+ }
+}
+func (_ fastpathT) EncSliceBoolV(v []bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteArrayStart(len(v))
+ if esep {
+ for _, v2 := range v {
+ ee.WriteArrayElem()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeBool(v2)
+ }
+ }
+ ee.WriteArrayEnd()
+}
+func (_ fastpathT) EncAsMapSliceBoolV(v []bool, e *Encoder) {
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ if len(v)%2 == 1 {
+ e.errorf("mapBySlice requires even slice length, but got %v", len(v))
+ return
+ }
+ ee.WriteMapStart(len(v) / 2)
+ if esep {
+ for j, v2 := range v {
+ if j%2 == 0 {
+ ee.WriteMapElemKey()
+ } else {
+ ee.WriteMapElemValue()
+ }
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for _, v2 := range v {
+ ee.EncodeBool(v2)
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfIntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfIntfV(rv2i(rv).(map[interface{}]interface{}), e)
+}
+func (_ fastpathT) EncMapIntfIntfV(v map[interface{}]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfStringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfStringV(rv2i(rv).(map[interface{}]string), e)
+}
+func (_ fastpathT) EncMapIntfStringV(v map[interface{}]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfUintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfUintV(rv2i(rv).(map[interface{}]uint), e)
+}
+func (_ fastpathT) EncMapIntfUintV(v map[interface{}]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfUint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfUint8V(rv2i(rv).(map[interface{}]uint8), e)
+}
+func (_ fastpathT) EncMapIntfUint8V(v map[interface{}]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfUint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfUint16V(rv2i(rv).(map[interface{}]uint16), e)
+}
+func (_ fastpathT) EncMapIntfUint16V(v map[interface{}]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfUint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfUint32V(rv2i(rv).(map[interface{}]uint32), e)
+}
+func (_ fastpathT) EncMapIntfUint32V(v map[interface{}]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfUint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfUint64V(rv2i(rv).(map[interface{}]uint64), e)
+}
+func (_ fastpathT) EncMapIntfUint64V(v map[interface{}]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfUintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfUintptrV(rv2i(rv).(map[interface{}]uintptr), e)
+}
+func (_ fastpathT) EncMapIntfUintptrV(v map[interface{}]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfIntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfIntV(rv2i(rv).(map[interface{}]int), e)
+}
+func (_ fastpathT) EncMapIntfIntV(v map[interface{}]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfInt8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfInt8V(rv2i(rv).(map[interface{}]int8), e)
+}
+func (_ fastpathT) EncMapIntfInt8V(v map[interface{}]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfInt16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfInt16V(rv2i(rv).(map[interface{}]int16), e)
+}
+func (_ fastpathT) EncMapIntfInt16V(v map[interface{}]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfInt32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfInt32V(rv2i(rv).(map[interface{}]int32), e)
+}
+func (_ fastpathT) EncMapIntfInt32V(v map[interface{}]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfInt64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfInt64V(rv2i(rv).(map[interface{}]int64), e)
+}
+func (_ fastpathT) EncMapIntfInt64V(v map[interface{}]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfFloat32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfFloat32V(rv2i(rv).(map[interface{}]float32), e)
+}
+func (_ fastpathT) EncMapIntfFloat32V(v map[interface{}]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfFloat64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfFloat64V(rv2i(rv).(map[interface{}]float64), e)
+}
+func (_ fastpathT) EncMapIntfFloat64V(v map[interface{}]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntfBoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntfBoolV(rv2i(rv).(map[interface{}]bool), e)
+}
+func (_ fastpathT) EncMapIntfBoolV(v map[interface{}]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ var mksv []byte = make([]byte, 0, len(v)*16) // temporary byte slice for the encoding
+ e2 := NewEncoderBytes(&mksv, e.hh)
+ v2 := make([]bytesI, len(v))
+ var i, l int
+ var vp *bytesI
+ for k2, _ := range v {
+ l = len(mksv)
+ e2.MustEncode(k2)
+ vp = &v2[i]
+ vp.v = mksv[l:]
+ vp.i = k2
+ i++
+ }
+ sort.Sort(bytesISlice(v2))
+ if esep {
+ for j := range v2 {
+ ee.WriteMapElemKey()
+ e.asis(v2[j].v)
+ ee.WriteMapElemValue()
+ e.encode(v[v2[j].i])
+ }
+ } else {
+ for j := range v2 {
+ e.asis(v2[j].v)
+ e.encode(v[v2[j].i])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringIntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringIntfV(rv2i(rv).(map[string]interface{}), e)
+}
+func (_ fastpathT) EncMapStringIntfV(v map[string]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ e.encode(v[string(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ e.encode(v[string(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringStringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringStringV(rv2i(rv).(map[string]string), e)
+}
+func (_ fastpathT) EncMapStringStringV(v map[string]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[string(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeString(cUTF8, v[string(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringUintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringUintV(rv2i(rv).(map[string]uint), e)
+}
+func (_ fastpathT) EncMapStringUintV(v map[string]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringUint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringUint8V(rv2i(rv).(map[string]uint8), e)
+}
+func (_ fastpathT) EncMapStringUint8V(v map[string]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringUint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringUint16V(rv2i(rv).(map[string]uint16), e)
+}
+func (_ fastpathT) EncMapStringUint16V(v map[string]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringUint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringUint32V(rv2i(rv).(map[string]uint32), e)
+}
+func (_ fastpathT) EncMapStringUint32V(v map[string]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringUint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringUint64V(rv2i(rv).(map[string]uint64), e)
+}
+func (_ fastpathT) EncMapStringUint64V(v map[string]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringUintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringUintptrV(rv2i(rv).(map[string]uintptr), e)
+}
+func (_ fastpathT) EncMapStringUintptrV(v map[string]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ e.encode(v[string(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ e.encode(v[string(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringIntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringIntV(rv2i(rv).(map[string]int), e)
+}
+func (_ fastpathT) EncMapStringIntV(v map[string]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringInt8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringInt8V(rv2i(rv).(map[string]int8), e)
+}
+func (_ fastpathT) EncMapStringInt8V(v map[string]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringInt16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringInt16V(rv2i(rv).(map[string]int16), e)
+}
+func (_ fastpathT) EncMapStringInt16V(v map[string]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringInt32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringInt32V(rv2i(rv).(map[string]int32), e)
+}
+func (_ fastpathT) EncMapStringInt32V(v map[string]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringInt64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringInt64V(rv2i(rv).(map[string]int64), e)
+}
+func (_ fastpathT) EncMapStringInt64V(v map[string]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v[string(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringFloat32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringFloat32V(rv2i(rv).(map[string]float32), e)
+}
+func (_ fastpathT) EncMapStringFloat32V(v map[string]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[string(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeFloat32(v[string(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringFloat64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringFloat64V(rv2i(rv).(map[string]float64), e)
+}
+func (_ fastpathT) EncMapStringFloat64V(v map[string]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[string(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeFloat64(v[string(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapStringBoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapStringBoolV(rv2i(rv).(map[string]bool), e)
+}
+func (_ fastpathT) EncMapStringBoolV(v map[string]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]string, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = string(k)
+ i++
+ }
+ sort.Sort(stringSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[string(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeBool(v[string(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeString(cUTF8, k2)
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeString(cUTF8, k2)
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32IntfV(rv2i(rv).(map[float32]interface{}), e)
+}
+func (_ fastpathT) EncMapFloat32IntfV(v map[float32]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[float32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ e.encode(v[float32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32StringV(rv2i(rv).(map[float32]string), e)
+}
+func (_ fastpathT) EncMapFloat32StringV(v map[float32]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[float32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeString(cUTF8, v[float32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32UintV(rv2i(rv).(map[float32]uint), e)
+}
+func (_ fastpathT) EncMapFloat32UintV(v map[float32]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Uint8V(rv2i(rv).(map[float32]uint8), e)
+}
+func (_ fastpathT) EncMapFloat32Uint8V(v map[float32]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Uint16V(rv2i(rv).(map[float32]uint16), e)
+}
+func (_ fastpathT) EncMapFloat32Uint16V(v map[float32]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Uint32V(rv2i(rv).(map[float32]uint32), e)
+}
+func (_ fastpathT) EncMapFloat32Uint32V(v map[float32]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Uint64V(rv2i(rv).(map[float32]uint64), e)
+}
+func (_ fastpathT) EncMapFloat32Uint64V(v map[float32]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeUint(uint64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32UintptrV(rv2i(rv).(map[float32]uintptr), e)
+}
+func (_ fastpathT) EncMapFloat32UintptrV(v map[float32]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[float32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ e.encode(v[float32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32IntV(rv2i(rv).(map[float32]int), e)
+}
+func (_ fastpathT) EncMapFloat32IntV(v map[float32]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Int8V(rv2i(rv).(map[float32]int8), e)
+}
+func (_ fastpathT) EncMapFloat32Int8V(v map[float32]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Int16V(rv2i(rv).(map[float32]int16), e)
+}
+func (_ fastpathT) EncMapFloat32Int16V(v map[float32]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Int32V(rv2i(rv).(map[float32]int32), e)
+}
+func (_ fastpathT) EncMapFloat32Int32V(v map[float32]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Int64V(rv2i(rv).(map[float32]int64), e)
+}
+func (_ fastpathT) EncMapFloat32Int64V(v map[float32]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeInt(int64(v[float32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Float32V(rv2i(rv).(map[float32]float32), e)
+}
+func (_ fastpathT) EncMapFloat32Float32V(v map[float32]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[float32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeFloat32(v[float32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32Float64V(rv2i(rv).(map[float32]float64), e)
+}
+func (_ fastpathT) EncMapFloat32Float64V(v map[float32]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[float32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeFloat64(v[float32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat32BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat32BoolV(rv2i(rv).(map[float32]bool), e)
+}
+func (_ fastpathT) EncMapFloat32BoolV(v map[float32]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(float32(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[float32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat32(float32(k2))
+ ee.EncodeBool(v[float32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat32(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat32(k2)
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64IntfV(rv2i(rv).(map[float64]interface{}), e)
+}
+func (_ fastpathT) EncMapFloat64IntfV(v map[float64]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[float64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ e.encode(v[float64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64StringV(rv2i(rv).(map[float64]string), e)
+}
+func (_ fastpathT) EncMapFloat64StringV(v map[float64]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[float64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeString(cUTF8, v[float64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64UintV(rv2i(rv).(map[float64]uint), e)
+}
+func (_ fastpathT) EncMapFloat64UintV(v map[float64]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Uint8V(rv2i(rv).(map[float64]uint8), e)
+}
+func (_ fastpathT) EncMapFloat64Uint8V(v map[float64]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Uint16V(rv2i(rv).(map[float64]uint16), e)
+}
+func (_ fastpathT) EncMapFloat64Uint16V(v map[float64]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Uint32V(rv2i(rv).(map[float64]uint32), e)
+}
+func (_ fastpathT) EncMapFloat64Uint32V(v map[float64]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Uint64V(rv2i(rv).(map[float64]uint64), e)
+}
+func (_ fastpathT) EncMapFloat64Uint64V(v map[float64]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeUint(uint64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64UintptrV(rv2i(rv).(map[float64]uintptr), e)
+}
+func (_ fastpathT) EncMapFloat64UintptrV(v map[float64]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[float64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ e.encode(v[float64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64IntV(rv2i(rv).(map[float64]int), e)
+}
+func (_ fastpathT) EncMapFloat64IntV(v map[float64]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Int8V(rv2i(rv).(map[float64]int8), e)
+}
+func (_ fastpathT) EncMapFloat64Int8V(v map[float64]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Int16V(rv2i(rv).(map[float64]int16), e)
+}
+func (_ fastpathT) EncMapFloat64Int16V(v map[float64]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Int32V(rv2i(rv).(map[float64]int32), e)
+}
+func (_ fastpathT) EncMapFloat64Int32V(v map[float64]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Int64V(rv2i(rv).(map[float64]int64), e)
+}
+func (_ fastpathT) EncMapFloat64Int64V(v map[float64]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeInt(int64(v[float64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Float32V(rv2i(rv).(map[float64]float32), e)
+}
+func (_ fastpathT) EncMapFloat64Float32V(v map[float64]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[float64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeFloat32(v[float64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64Float64V(rv2i(rv).(map[float64]float64), e)
+}
+func (_ fastpathT) EncMapFloat64Float64V(v map[float64]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[float64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeFloat64(v[float64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapFloat64BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapFloat64BoolV(rv2i(rv).(map[float64]bool), e)
+}
+func (_ fastpathT) EncMapFloat64BoolV(v map[float64]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]float64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = float64(k)
+ i++
+ }
+ sort.Sort(floatSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(float64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[float64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeFloat64(float64(k2))
+ ee.EncodeBool(v[float64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeFloat64(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeFloat64(k2)
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintIntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintIntfV(rv2i(rv).(map[uint]interface{}), e)
+}
+func (_ fastpathT) EncMapUintIntfV(v map[uint]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ e.encode(v[uint(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintStringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintStringV(rv2i(rv).(map[uint]string), e)
+}
+func (_ fastpathT) EncMapUintStringV(v map[uint]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[uint(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeString(cUTF8, v[uint(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintUintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintUintV(rv2i(rv).(map[uint]uint), e)
+}
+func (_ fastpathT) EncMapUintUintV(v map[uint]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintUint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintUint8V(rv2i(rv).(map[uint]uint8), e)
+}
+func (_ fastpathT) EncMapUintUint8V(v map[uint]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintUint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintUint16V(rv2i(rv).(map[uint]uint16), e)
+}
+func (_ fastpathT) EncMapUintUint16V(v map[uint]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintUint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintUint32V(rv2i(rv).(map[uint]uint32), e)
+}
+func (_ fastpathT) EncMapUintUint32V(v map[uint]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintUint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintUint64V(rv2i(rv).(map[uint]uint64), e)
+}
+func (_ fastpathT) EncMapUintUint64V(v map[uint]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeUint(uint64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintUintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintUintptrV(rv2i(rv).(map[uint]uintptr), e)
+}
+func (_ fastpathT) EncMapUintUintptrV(v map[uint]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ e.encode(v[uint(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintIntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintIntV(rv2i(rv).(map[uint]int), e)
+}
+func (_ fastpathT) EncMapUintIntV(v map[uint]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintInt8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintInt8V(rv2i(rv).(map[uint]int8), e)
+}
+func (_ fastpathT) EncMapUintInt8V(v map[uint]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintInt16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintInt16V(rv2i(rv).(map[uint]int16), e)
+}
+func (_ fastpathT) EncMapUintInt16V(v map[uint]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintInt32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintInt32V(rv2i(rv).(map[uint]int32), e)
+}
+func (_ fastpathT) EncMapUintInt32V(v map[uint]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintInt64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintInt64V(rv2i(rv).(map[uint]int64), e)
+}
+func (_ fastpathT) EncMapUintInt64V(v map[uint]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeInt(int64(v[uint(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintFloat32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintFloat32V(rv2i(rv).(map[uint]float32), e)
+}
+func (_ fastpathT) EncMapUintFloat32V(v map[uint]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[uint(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeFloat32(v[uint(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintFloat64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintFloat64V(rv2i(rv).(map[uint]float64), e)
+}
+func (_ fastpathT) EncMapUintFloat64V(v map[uint]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[uint(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeFloat64(v[uint(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintBoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintBoolV(rv2i(rv).(map[uint]bool), e)
+}
+func (_ fastpathT) EncMapUintBoolV(v map[uint]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[uint(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint(k2)))
+ ee.EncodeBool(v[uint(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8IntfV(rv2i(rv).(map[uint8]interface{}), e)
+}
+func (_ fastpathT) EncMapUint8IntfV(v map[uint8]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ e.encode(v[uint8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8StringV(rv2i(rv).(map[uint8]string), e)
+}
+func (_ fastpathT) EncMapUint8StringV(v map[uint8]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[uint8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeString(cUTF8, v[uint8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8UintV(rv2i(rv).(map[uint8]uint), e)
+}
+func (_ fastpathT) EncMapUint8UintV(v map[uint8]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Uint8V(rv2i(rv).(map[uint8]uint8), e)
+}
+func (_ fastpathT) EncMapUint8Uint8V(v map[uint8]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Uint16V(rv2i(rv).(map[uint8]uint16), e)
+}
+func (_ fastpathT) EncMapUint8Uint16V(v map[uint8]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Uint32V(rv2i(rv).(map[uint8]uint32), e)
+}
+func (_ fastpathT) EncMapUint8Uint32V(v map[uint8]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Uint64V(rv2i(rv).(map[uint8]uint64), e)
+}
+func (_ fastpathT) EncMapUint8Uint64V(v map[uint8]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeUint(uint64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8UintptrV(rv2i(rv).(map[uint8]uintptr), e)
+}
+func (_ fastpathT) EncMapUint8UintptrV(v map[uint8]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ e.encode(v[uint8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8IntV(rv2i(rv).(map[uint8]int), e)
+}
+func (_ fastpathT) EncMapUint8IntV(v map[uint8]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Int8V(rv2i(rv).(map[uint8]int8), e)
+}
+func (_ fastpathT) EncMapUint8Int8V(v map[uint8]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Int16V(rv2i(rv).(map[uint8]int16), e)
+}
+func (_ fastpathT) EncMapUint8Int16V(v map[uint8]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Int32V(rv2i(rv).(map[uint8]int32), e)
+}
+func (_ fastpathT) EncMapUint8Int32V(v map[uint8]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Int64V(rv2i(rv).(map[uint8]int64), e)
+}
+func (_ fastpathT) EncMapUint8Int64V(v map[uint8]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeInt(int64(v[uint8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Float32V(rv2i(rv).(map[uint8]float32), e)
+}
+func (_ fastpathT) EncMapUint8Float32V(v map[uint8]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[uint8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeFloat32(v[uint8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8Float64V(rv2i(rv).(map[uint8]float64), e)
+}
+func (_ fastpathT) EncMapUint8Float64V(v map[uint8]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[uint8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeFloat64(v[uint8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint8BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint8BoolV(rv2i(rv).(map[uint8]bool), e)
+}
+func (_ fastpathT) EncMapUint8BoolV(v map[uint8]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[uint8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint8(k2)))
+ ee.EncodeBool(v[uint8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16IntfV(rv2i(rv).(map[uint16]interface{}), e)
+}
+func (_ fastpathT) EncMapUint16IntfV(v map[uint16]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ e.encode(v[uint16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16StringV(rv2i(rv).(map[uint16]string), e)
+}
+func (_ fastpathT) EncMapUint16StringV(v map[uint16]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[uint16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeString(cUTF8, v[uint16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16UintV(rv2i(rv).(map[uint16]uint), e)
+}
+func (_ fastpathT) EncMapUint16UintV(v map[uint16]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Uint8V(rv2i(rv).(map[uint16]uint8), e)
+}
+func (_ fastpathT) EncMapUint16Uint8V(v map[uint16]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Uint16V(rv2i(rv).(map[uint16]uint16), e)
+}
+func (_ fastpathT) EncMapUint16Uint16V(v map[uint16]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Uint32V(rv2i(rv).(map[uint16]uint32), e)
+}
+func (_ fastpathT) EncMapUint16Uint32V(v map[uint16]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Uint64V(rv2i(rv).(map[uint16]uint64), e)
+}
+func (_ fastpathT) EncMapUint16Uint64V(v map[uint16]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeUint(uint64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16UintptrV(rv2i(rv).(map[uint16]uintptr), e)
+}
+func (_ fastpathT) EncMapUint16UintptrV(v map[uint16]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ e.encode(v[uint16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16IntV(rv2i(rv).(map[uint16]int), e)
+}
+func (_ fastpathT) EncMapUint16IntV(v map[uint16]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Int8V(rv2i(rv).(map[uint16]int8), e)
+}
+func (_ fastpathT) EncMapUint16Int8V(v map[uint16]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Int16V(rv2i(rv).(map[uint16]int16), e)
+}
+func (_ fastpathT) EncMapUint16Int16V(v map[uint16]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Int32V(rv2i(rv).(map[uint16]int32), e)
+}
+func (_ fastpathT) EncMapUint16Int32V(v map[uint16]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Int64V(rv2i(rv).(map[uint16]int64), e)
+}
+func (_ fastpathT) EncMapUint16Int64V(v map[uint16]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeInt(int64(v[uint16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Float32V(rv2i(rv).(map[uint16]float32), e)
+}
+func (_ fastpathT) EncMapUint16Float32V(v map[uint16]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[uint16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeFloat32(v[uint16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16Float64V(rv2i(rv).(map[uint16]float64), e)
+}
+func (_ fastpathT) EncMapUint16Float64V(v map[uint16]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[uint16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeFloat64(v[uint16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint16BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint16BoolV(rv2i(rv).(map[uint16]bool), e)
+}
+func (_ fastpathT) EncMapUint16BoolV(v map[uint16]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[uint16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint16(k2)))
+ ee.EncodeBool(v[uint16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32IntfV(rv2i(rv).(map[uint32]interface{}), e)
+}
+func (_ fastpathT) EncMapUint32IntfV(v map[uint32]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ e.encode(v[uint32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32StringV(rv2i(rv).(map[uint32]string), e)
+}
+func (_ fastpathT) EncMapUint32StringV(v map[uint32]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[uint32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeString(cUTF8, v[uint32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32UintV(rv2i(rv).(map[uint32]uint), e)
+}
+func (_ fastpathT) EncMapUint32UintV(v map[uint32]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Uint8V(rv2i(rv).(map[uint32]uint8), e)
+}
+func (_ fastpathT) EncMapUint32Uint8V(v map[uint32]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Uint16V(rv2i(rv).(map[uint32]uint16), e)
+}
+func (_ fastpathT) EncMapUint32Uint16V(v map[uint32]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Uint32V(rv2i(rv).(map[uint32]uint32), e)
+}
+func (_ fastpathT) EncMapUint32Uint32V(v map[uint32]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Uint64V(rv2i(rv).(map[uint32]uint64), e)
+}
+func (_ fastpathT) EncMapUint32Uint64V(v map[uint32]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeUint(uint64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32UintptrV(rv2i(rv).(map[uint32]uintptr), e)
+}
+func (_ fastpathT) EncMapUint32UintptrV(v map[uint32]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ e.encode(v[uint32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32IntV(rv2i(rv).(map[uint32]int), e)
+}
+func (_ fastpathT) EncMapUint32IntV(v map[uint32]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Int8V(rv2i(rv).(map[uint32]int8), e)
+}
+func (_ fastpathT) EncMapUint32Int8V(v map[uint32]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Int16V(rv2i(rv).(map[uint32]int16), e)
+}
+func (_ fastpathT) EncMapUint32Int16V(v map[uint32]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Int32V(rv2i(rv).(map[uint32]int32), e)
+}
+func (_ fastpathT) EncMapUint32Int32V(v map[uint32]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Int64V(rv2i(rv).(map[uint32]int64), e)
+}
+func (_ fastpathT) EncMapUint32Int64V(v map[uint32]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeInt(int64(v[uint32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Float32V(rv2i(rv).(map[uint32]float32), e)
+}
+func (_ fastpathT) EncMapUint32Float32V(v map[uint32]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[uint32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeFloat32(v[uint32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32Float64V(rv2i(rv).(map[uint32]float64), e)
+}
+func (_ fastpathT) EncMapUint32Float64V(v map[uint32]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[uint32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeFloat64(v[uint32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint32BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint32BoolV(rv2i(rv).(map[uint32]bool), e)
+}
+func (_ fastpathT) EncMapUint32BoolV(v map[uint32]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[uint32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint32(k2)))
+ ee.EncodeBool(v[uint32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64IntfV(rv2i(rv).(map[uint64]interface{}), e)
+}
+func (_ fastpathT) EncMapUint64IntfV(v map[uint64]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ e.encode(v[uint64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64StringV(rv2i(rv).(map[uint64]string), e)
+}
+func (_ fastpathT) EncMapUint64StringV(v map[uint64]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[uint64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeString(cUTF8, v[uint64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64UintV(rv2i(rv).(map[uint64]uint), e)
+}
+func (_ fastpathT) EncMapUint64UintV(v map[uint64]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Uint8V(rv2i(rv).(map[uint64]uint8), e)
+}
+func (_ fastpathT) EncMapUint64Uint8V(v map[uint64]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Uint16V(rv2i(rv).(map[uint64]uint16), e)
+}
+func (_ fastpathT) EncMapUint64Uint16V(v map[uint64]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Uint32V(rv2i(rv).(map[uint64]uint32), e)
+}
+func (_ fastpathT) EncMapUint64Uint32V(v map[uint64]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Uint64V(rv2i(rv).(map[uint64]uint64), e)
+}
+func (_ fastpathT) EncMapUint64Uint64V(v map[uint64]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeUint(uint64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64UintptrV(rv2i(rv).(map[uint64]uintptr), e)
+}
+func (_ fastpathT) EncMapUint64UintptrV(v map[uint64]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[uint64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ e.encode(v[uint64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64IntV(rv2i(rv).(map[uint64]int), e)
+}
+func (_ fastpathT) EncMapUint64IntV(v map[uint64]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Int8V(rv2i(rv).(map[uint64]int8), e)
+}
+func (_ fastpathT) EncMapUint64Int8V(v map[uint64]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Int16V(rv2i(rv).(map[uint64]int16), e)
+}
+func (_ fastpathT) EncMapUint64Int16V(v map[uint64]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Int32V(rv2i(rv).(map[uint64]int32), e)
+}
+func (_ fastpathT) EncMapUint64Int32V(v map[uint64]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Int64V(rv2i(rv).(map[uint64]int64), e)
+}
+func (_ fastpathT) EncMapUint64Int64V(v map[uint64]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeInt(int64(v[uint64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Float32V(rv2i(rv).(map[uint64]float32), e)
+}
+func (_ fastpathT) EncMapUint64Float32V(v map[uint64]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[uint64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeFloat32(v[uint64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64Float64V(rv2i(rv).(map[uint64]float64), e)
+}
+func (_ fastpathT) EncMapUint64Float64V(v map[uint64]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[uint64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeFloat64(v[uint64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUint64BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUint64BoolV(rv2i(rv).(map[uint64]bool), e)
+}
+func (_ fastpathT) EncMapUint64BoolV(v map[uint64]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[uint64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeUint(uint64(uint64(k2)))
+ ee.EncodeBool(v[uint64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeUint(uint64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeUint(uint64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrIntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrIntfV(rv2i(rv).(map[uintptr]interface{}), e)
+}
+func (_ fastpathT) EncMapUintptrIntfV(v map[uintptr]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[uintptr(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ e.encode(v[uintptr(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrStringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrStringV(rv2i(rv).(map[uintptr]string), e)
+}
+func (_ fastpathT) EncMapUintptrStringV(v map[uintptr]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[uintptr(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeString(cUTF8, v[uintptr(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrUintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrUintV(rv2i(rv).(map[uintptr]uint), e)
+}
+func (_ fastpathT) EncMapUintptrUintV(v map[uintptr]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrUint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrUint8V(rv2i(rv).(map[uintptr]uint8), e)
+}
+func (_ fastpathT) EncMapUintptrUint8V(v map[uintptr]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrUint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrUint16V(rv2i(rv).(map[uintptr]uint16), e)
+}
+func (_ fastpathT) EncMapUintptrUint16V(v map[uintptr]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrUint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrUint32V(rv2i(rv).(map[uintptr]uint32), e)
+}
+func (_ fastpathT) EncMapUintptrUint32V(v map[uintptr]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrUint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrUint64V(rv2i(rv).(map[uintptr]uint64), e)
+}
+func (_ fastpathT) EncMapUintptrUint64V(v map[uintptr]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeUint(uint64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrUintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrUintptrV(rv2i(rv).(map[uintptr]uintptr), e)
+}
+func (_ fastpathT) EncMapUintptrUintptrV(v map[uintptr]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[uintptr(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ e.encode(v[uintptr(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrIntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrIntV(rv2i(rv).(map[uintptr]int), e)
+}
+func (_ fastpathT) EncMapUintptrIntV(v map[uintptr]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrInt8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrInt8V(rv2i(rv).(map[uintptr]int8), e)
+}
+func (_ fastpathT) EncMapUintptrInt8V(v map[uintptr]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrInt16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrInt16V(rv2i(rv).(map[uintptr]int16), e)
+}
+func (_ fastpathT) EncMapUintptrInt16V(v map[uintptr]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrInt32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrInt32V(rv2i(rv).(map[uintptr]int32), e)
+}
+func (_ fastpathT) EncMapUintptrInt32V(v map[uintptr]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrInt64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrInt64V(rv2i(rv).(map[uintptr]int64), e)
+}
+func (_ fastpathT) EncMapUintptrInt64V(v map[uintptr]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeInt(int64(v[uintptr(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrFloat32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrFloat32V(rv2i(rv).(map[uintptr]float32), e)
+}
+func (_ fastpathT) EncMapUintptrFloat32V(v map[uintptr]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[uintptr(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeFloat32(v[uintptr(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrFloat64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrFloat64V(rv2i(rv).(map[uintptr]float64), e)
+}
+func (_ fastpathT) EncMapUintptrFloat64V(v map[uintptr]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[uintptr(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeFloat64(v[uintptr(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapUintptrBoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapUintptrBoolV(rv2i(rv).(map[uintptr]bool), e)
+}
+func (_ fastpathT) EncMapUintptrBoolV(v map[uintptr]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]uint64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = uint64(k)
+ i++
+ }
+ sort.Sort(uintSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ e.encode(uintptr(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[uintptr(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ e.encode(uintptr(k2))
+ ee.EncodeBool(v[uintptr(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ e.encode(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ e.encode(k2)
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntIntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntIntfV(rv2i(rv).(map[int]interface{}), e)
+}
+func (_ fastpathT) EncMapIntIntfV(v map[int]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ e.encode(v[int(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntStringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntStringV(rv2i(rv).(map[int]string), e)
+}
+func (_ fastpathT) EncMapIntStringV(v map[int]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[int(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeString(cUTF8, v[int(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntUintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntUintV(rv2i(rv).(map[int]uint), e)
+}
+func (_ fastpathT) EncMapIntUintV(v map[int]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntUint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntUint8V(rv2i(rv).(map[int]uint8), e)
+}
+func (_ fastpathT) EncMapIntUint8V(v map[int]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntUint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntUint16V(rv2i(rv).(map[int]uint16), e)
+}
+func (_ fastpathT) EncMapIntUint16V(v map[int]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntUint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntUint32V(rv2i(rv).(map[int]uint32), e)
+}
+func (_ fastpathT) EncMapIntUint32V(v map[int]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntUint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntUint64V(rv2i(rv).(map[int]uint64), e)
+}
+func (_ fastpathT) EncMapIntUint64V(v map[int]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeUint(uint64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntUintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntUintptrV(rv2i(rv).(map[int]uintptr), e)
+}
+func (_ fastpathT) EncMapIntUintptrV(v map[int]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ e.encode(v[int(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntIntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntIntV(rv2i(rv).(map[int]int), e)
+}
+func (_ fastpathT) EncMapIntIntV(v map[int]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntInt8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntInt8V(rv2i(rv).(map[int]int8), e)
+}
+func (_ fastpathT) EncMapIntInt8V(v map[int]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntInt16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntInt16V(rv2i(rv).(map[int]int16), e)
+}
+func (_ fastpathT) EncMapIntInt16V(v map[int]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntInt32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntInt32V(rv2i(rv).(map[int]int32), e)
+}
+func (_ fastpathT) EncMapIntInt32V(v map[int]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntInt64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntInt64V(rv2i(rv).(map[int]int64), e)
+}
+func (_ fastpathT) EncMapIntInt64V(v map[int]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeInt(int64(v[int(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntFloat32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntFloat32V(rv2i(rv).(map[int]float32), e)
+}
+func (_ fastpathT) EncMapIntFloat32V(v map[int]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[int(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeFloat32(v[int(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntFloat64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntFloat64V(rv2i(rv).(map[int]float64), e)
+}
+func (_ fastpathT) EncMapIntFloat64V(v map[int]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[int(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeFloat64(v[int(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapIntBoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapIntBoolV(rv2i(rv).(map[int]bool), e)
+}
+func (_ fastpathT) EncMapIntBoolV(v map[int]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[int(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int(k2)))
+ ee.EncodeBool(v[int(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8IntfV(rv2i(rv).(map[int8]interface{}), e)
+}
+func (_ fastpathT) EncMapInt8IntfV(v map[int8]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ e.encode(v[int8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8StringV(rv2i(rv).(map[int8]string), e)
+}
+func (_ fastpathT) EncMapInt8StringV(v map[int8]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[int8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeString(cUTF8, v[int8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8UintV(rv2i(rv).(map[int8]uint), e)
+}
+func (_ fastpathT) EncMapInt8UintV(v map[int8]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Uint8V(rv2i(rv).(map[int8]uint8), e)
+}
+func (_ fastpathT) EncMapInt8Uint8V(v map[int8]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Uint16V(rv2i(rv).(map[int8]uint16), e)
+}
+func (_ fastpathT) EncMapInt8Uint16V(v map[int8]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Uint32V(rv2i(rv).(map[int8]uint32), e)
+}
+func (_ fastpathT) EncMapInt8Uint32V(v map[int8]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Uint64V(rv2i(rv).(map[int8]uint64), e)
+}
+func (_ fastpathT) EncMapInt8Uint64V(v map[int8]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeUint(uint64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8UintptrV(rv2i(rv).(map[int8]uintptr), e)
+}
+func (_ fastpathT) EncMapInt8UintptrV(v map[int8]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ e.encode(v[int8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8IntV(rv2i(rv).(map[int8]int), e)
+}
+func (_ fastpathT) EncMapInt8IntV(v map[int8]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Int8V(rv2i(rv).(map[int8]int8), e)
+}
+func (_ fastpathT) EncMapInt8Int8V(v map[int8]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Int16V(rv2i(rv).(map[int8]int16), e)
+}
+func (_ fastpathT) EncMapInt8Int16V(v map[int8]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Int32V(rv2i(rv).(map[int8]int32), e)
+}
+func (_ fastpathT) EncMapInt8Int32V(v map[int8]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Int64V(rv2i(rv).(map[int8]int64), e)
+}
+func (_ fastpathT) EncMapInt8Int64V(v map[int8]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeInt(int64(v[int8(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Float32V(rv2i(rv).(map[int8]float32), e)
+}
+func (_ fastpathT) EncMapInt8Float32V(v map[int8]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[int8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeFloat32(v[int8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8Float64V(rv2i(rv).(map[int8]float64), e)
+}
+func (_ fastpathT) EncMapInt8Float64V(v map[int8]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[int8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeFloat64(v[int8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt8BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt8BoolV(rv2i(rv).(map[int8]bool), e)
+}
+func (_ fastpathT) EncMapInt8BoolV(v map[int8]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int8(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[int8(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int8(k2)))
+ ee.EncodeBool(v[int8(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16IntfV(rv2i(rv).(map[int16]interface{}), e)
+}
+func (_ fastpathT) EncMapInt16IntfV(v map[int16]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ e.encode(v[int16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16StringV(rv2i(rv).(map[int16]string), e)
+}
+func (_ fastpathT) EncMapInt16StringV(v map[int16]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[int16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeString(cUTF8, v[int16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16UintV(rv2i(rv).(map[int16]uint), e)
+}
+func (_ fastpathT) EncMapInt16UintV(v map[int16]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Uint8V(rv2i(rv).(map[int16]uint8), e)
+}
+func (_ fastpathT) EncMapInt16Uint8V(v map[int16]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Uint16V(rv2i(rv).(map[int16]uint16), e)
+}
+func (_ fastpathT) EncMapInt16Uint16V(v map[int16]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Uint32V(rv2i(rv).(map[int16]uint32), e)
+}
+func (_ fastpathT) EncMapInt16Uint32V(v map[int16]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Uint64V(rv2i(rv).(map[int16]uint64), e)
+}
+func (_ fastpathT) EncMapInt16Uint64V(v map[int16]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeUint(uint64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16UintptrV(rv2i(rv).(map[int16]uintptr), e)
+}
+func (_ fastpathT) EncMapInt16UintptrV(v map[int16]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ e.encode(v[int16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16IntV(rv2i(rv).(map[int16]int), e)
+}
+func (_ fastpathT) EncMapInt16IntV(v map[int16]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Int8V(rv2i(rv).(map[int16]int8), e)
+}
+func (_ fastpathT) EncMapInt16Int8V(v map[int16]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Int16V(rv2i(rv).(map[int16]int16), e)
+}
+func (_ fastpathT) EncMapInt16Int16V(v map[int16]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Int32V(rv2i(rv).(map[int16]int32), e)
+}
+func (_ fastpathT) EncMapInt16Int32V(v map[int16]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Int64V(rv2i(rv).(map[int16]int64), e)
+}
+func (_ fastpathT) EncMapInt16Int64V(v map[int16]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeInt(int64(v[int16(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Float32V(rv2i(rv).(map[int16]float32), e)
+}
+func (_ fastpathT) EncMapInt16Float32V(v map[int16]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[int16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeFloat32(v[int16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16Float64V(rv2i(rv).(map[int16]float64), e)
+}
+func (_ fastpathT) EncMapInt16Float64V(v map[int16]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[int16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeFloat64(v[int16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt16BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt16BoolV(rv2i(rv).(map[int16]bool), e)
+}
+func (_ fastpathT) EncMapInt16BoolV(v map[int16]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int16(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[int16(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int16(k2)))
+ ee.EncodeBool(v[int16(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32IntfV(rv2i(rv).(map[int32]interface{}), e)
+}
+func (_ fastpathT) EncMapInt32IntfV(v map[int32]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ e.encode(v[int32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32StringV(rv2i(rv).(map[int32]string), e)
+}
+func (_ fastpathT) EncMapInt32StringV(v map[int32]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[int32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeString(cUTF8, v[int32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32UintV(rv2i(rv).(map[int32]uint), e)
+}
+func (_ fastpathT) EncMapInt32UintV(v map[int32]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Uint8V(rv2i(rv).(map[int32]uint8), e)
+}
+func (_ fastpathT) EncMapInt32Uint8V(v map[int32]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Uint16V(rv2i(rv).(map[int32]uint16), e)
+}
+func (_ fastpathT) EncMapInt32Uint16V(v map[int32]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Uint32V(rv2i(rv).(map[int32]uint32), e)
+}
+func (_ fastpathT) EncMapInt32Uint32V(v map[int32]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Uint64V(rv2i(rv).(map[int32]uint64), e)
+}
+func (_ fastpathT) EncMapInt32Uint64V(v map[int32]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeUint(uint64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32UintptrV(rv2i(rv).(map[int32]uintptr), e)
+}
+func (_ fastpathT) EncMapInt32UintptrV(v map[int32]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ e.encode(v[int32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32IntV(rv2i(rv).(map[int32]int), e)
+}
+func (_ fastpathT) EncMapInt32IntV(v map[int32]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Int8V(rv2i(rv).(map[int32]int8), e)
+}
+func (_ fastpathT) EncMapInt32Int8V(v map[int32]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Int16V(rv2i(rv).(map[int32]int16), e)
+}
+func (_ fastpathT) EncMapInt32Int16V(v map[int32]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Int32V(rv2i(rv).(map[int32]int32), e)
+}
+func (_ fastpathT) EncMapInt32Int32V(v map[int32]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Int64V(rv2i(rv).(map[int32]int64), e)
+}
+func (_ fastpathT) EncMapInt32Int64V(v map[int32]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeInt(int64(v[int32(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Float32V(rv2i(rv).(map[int32]float32), e)
+}
+func (_ fastpathT) EncMapInt32Float32V(v map[int32]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[int32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeFloat32(v[int32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32Float64V(rv2i(rv).(map[int32]float64), e)
+}
+func (_ fastpathT) EncMapInt32Float64V(v map[int32]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[int32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeFloat64(v[int32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt32BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt32BoolV(rv2i(rv).(map[int32]bool), e)
+}
+func (_ fastpathT) EncMapInt32BoolV(v map[int32]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int32(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[int32(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int32(k2)))
+ ee.EncodeBool(v[int32(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64IntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64IntfV(rv2i(rv).(map[int64]interface{}), e)
+}
+func (_ fastpathT) EncMapInt64IntfV(v map[int64]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ e.encode(v[int64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64StringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64StringV(rv2i(rv).(map[int64]string), e)
+}
+func (_ fastpathT) EncMapInt64StringV(v map[int64]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[int64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeString(cUTF8, v[int64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64UintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64UintV(rv2i(rv).(map[int64]uint), e)
+}
+func (_ fastpathT) EncMapInt64UintV(v map[int64]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Uint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Uint8V(rv2i(rv).(map[int64]uint8), e)
+}
+func (_ fastpathT) EncMapInt64Uint8V(v map[int64]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Uint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Uint16V(rv2i(rv).(map[int64]uint16), e)
+}
+func (_ fastpathT) EncMapInt64Uint16V(v map[int64]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Uint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Uint32V(rv2i(rv).(map[int64]uint32), e)
+}
+func (_ fastpathT) EncMapInt64Uint32V(v map[int64]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Uint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Uint64V(rv2i(rv).(map[int64]uint64), e)
+}
+func (_ fastpathT) EncMapInt64Uint64V(v map[int64]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeUint(uint64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64UintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64UintptrV(rv2i(rv).(map[int64]uintptr), e)
+}
+func (_ fastpathT) EncMapInt64UintptrV(v map[int64]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ e.encode(v[int64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ e.encode(v[int64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64IntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64IntV(rv2i(rv).(map[int64]int), e)
+}
+func (_ fastpathT) EncMapInt64IntV(v map[int64]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Int8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Int8V(rv2i(rv).(map[int64]int8), e)
+}
+func (_ fastpathT) EncMapInt64Int8V(v map[int64]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Int16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Int16V(rv2i(rv).(map[int64]int16), e)
+}
+func (_ fastpathT) EncMapInt64Int16V(v map[int64]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Int32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Int32V(rv2i(rv).(map[int64]int32), e)
+}
+func (_ fastpathT) EncMapInt64Int32V(v map[int64]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Int64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Int64V(rv2i(rv).(map[int64]int64), e)
+}
+func (_ fastpathT) EncMapInt64Int64V(v map[int64]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeInt(int64(v[int64(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Float32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Float32V(rv2i(rv).(map[int64]float32), e)
+}
+func (_ fastpathT) EncMapInt64Float32V(v map[int64]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[int64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeFloat32(v[int64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64Float64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64Float64V(rv2i(rv).(map[int64]float64), e)
+}
+func (_ fastpathT) EncMapInt64Float64V(v map[int64]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[int64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeFloat64(v[int64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapInt64BoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapInt64BoolV(rv2i(rv).(map[int64]bool), e)
+}
+func (_ fastpathT) EncMapInt64BoolV(v map[int64]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]int64, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = int64(k)
+ i++
+ }
+ sort.Sort(intSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(int64(k2)))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[int64(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeInt(int64(int64(k2)))
+ ee.EncodeBool(v[int64(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeInt(int64(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeInt(int64(k2))
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolIntfR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolIntfV(rv2i(rv).(map[bool]interface{}), e)
+}
+func (_ fastpathT) EncMapBoolIntfV(v map[bool]interface{}, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[bool(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ e.encode(v[bool(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolStringR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolStringV(rv2i(rv).(map[bool]string), e)
+}
+func (_ fastpathT) EncMapBoolStringV(v map[bool]string, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v[bool(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeString(cUTF8, v[bool(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeString(cUTF8, v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeString(cUTF8, v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolUintR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolUintV(rv2i(rv).(map[bool]uint), e)
+}
+func (_ fastpathT) EncMapBoolUintV(v map[bool]uint, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolUint8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolUint8V(rv2i(rv).(map[bool]uint8), e)
+}
+func (_ fastpathT) EncMapBoolUint8V(v map[bool]uint8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolUint16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolUint16V(rv2i(rv).(map[bool]uint16), e)
+}
+func (_ fastpathT) EncMapBoolUint16V(v map[bool]uint16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolUint32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolUint32V(rv2i(rv).(map[bool]uint32), e)
+}
+func (_ fastpathT) EncMapBoolUint32V(v map[bool]uint32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolUint64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolUint64V(rv2i(rv).(map[bool]uint64), e)
+}
+func (_ fastpathT) EncMapBoolUint64V(v map[bool]uint64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeUint(uint64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeUint(uint64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeUint(uint64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolUintptrR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolUintptrV(rv2i(rv).(map[bool]uintptr), e)
+}
+func (_ fastpathT) EncMapBoolUintptrV(v map[bool]uintptr, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ e.encode(v[bool(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ e.encode(v[bool(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ e.encode(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ e.encode(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolIntR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolIntV(rv2i(rv).(map[bool]int), e)
+}
+func (_ fastpathT) EncMapBoolIntV(v map[bool]int, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolInt8R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolInt8V(rv2i(rv).(map[bool]int8), e)
+}
+func (_ fastpathT) EncMapBoolInt8V(v map[bool]int8, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolInt16R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolInt16V(rv2i(rv).(map[bool]int16), e)
+}
+func (_ fastpathT) EncMapBoolInt16V(v map[bool]int16, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolInt32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolInt32V(rv2i(rv).(map[bool]int32), e)
+}
+func (_ fastpathT) EncMapBoolInt32V(v map[bool]int32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolInt64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolInt64V(rv2i(rv).(map[bool]int64), e)
+}
+func (_ fastpathT) EncMapBoolInt64V(v map[bool]int64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeInt(int64(v[bool(k2)]))
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeInt(int64(v2))
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeInt(int64(v2))
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolFloat32R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolFloat32V(rv2i(rv).(map[bool]float32), e)
+}
+func (_ fastpathT) EncMapBoolFloat32V(v map[bool]float32, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v[bool(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeFloat32(v[bool(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat32(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeFloat32(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolFloat64R(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolFloat64V(rv2i(rv).(map[bool]float64), e)
+}
+func (_ fastpathT) EncMapBoolFloat64V(v map[bool]float64, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v[bool(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeFloat64(v[bool(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeFloat64(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeFloat64(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+func (e *Encoder) fastpathEncMapBoolBoolR(f *codecFnInfo, rv reflect.Value) {
+ fastpathTV.EncMapBoolBoolV(rv2i(rv).(map[bool]bool), e)
+}
+func (_ fastpathT) EncMapBoolBoolV(v map[bool]bool, e *Encoder) {
+ if v == nil {
+ e.e.EncodeNil()
+ return
+ }
+ ee, esep := e.e, e.hh.hasElemSeparators()
+ ee.WriteMapStart(len(v))
+ if e.h.Canonical {
+ v2 := make([]bool, len(v))
+ var i int
+ for k, _ := range v {
+ v2[i] = bool(k)
+ i++
+ }
+ sort.Sort(boolSlice(v2))
+ if esep {
+ for _, k2 := range v2 {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(bool(k2))
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v[bool(k2)])
+ }
+ } else {
+ for _, k2 := range v2 {
+ ee.EncodeBool(bool(k2))
+ ee.EncodeBool(v[bool(k2)])
+ }
+ }
+ } else {
+ if esep {
+ for k2, v2 := range v {
+ ee.WriteMapElemKey()
+ ee.EncodeBool(k2)
+ ee.WriteMapElemValue()
+ ee.EncodeBool(v2)
+ }
+ } else {
+ for k2, v2 := range v {
+ ee.EncodeBool(k2)
+ ee.EncodeBool(v2)
+ }
+ }
+ }
+ ee.WriteMapEnd()
+}
+
+// -- decode
+
+// -- -- fast path type switch
+func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool {
+ var changed bool
+ switch v := iv.(type) {
+
+ case []interface{}:
+ var v2 []interface{}
+ v2, changed = fastpathTV.DecSliceIntfV(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]interface{}:
+ var v2 []interface{}
+ v2, changed = fastpathTV.DecSliceIntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []string:
+ var v2 []string
+ v2, changed = fastpathTV.DecSliceStringV(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]string:
+ var v2 []string
+ v2, changed = fastpathTV.DecSliceStringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []float32:
+ var v2 []float32
+ v2, changed = fastpathTV.DecSliceFloat32V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]float32:
+ var v2 []float32
+ v2, changed = fastpathTV.DecSliceFloat32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []float64:
+ var v2 []float64
+ v2, changed = fastpathTV.DecSliceFloat64V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]float64:
+ var v2 []float64
+ v2, changed = fastpathTV.DecSliceFloat64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []uint:
+ var v2 []uint
+ v2, changed = fastpathTV.DecSliceUintV(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]uint:
+ var v2 []uint
+ v2, changed = fastpathTV.DecSliceUintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []uint16:
+ var v2 []uint16
+ v2, changed = fastpathTV.DecSliceUint16V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]uint16:
+ var v2 []uint16
+ v2, changed = fastpathTV.DecSliceUint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []uint32:
+ var v2 []uint32
+ v2, changed = fastpathTV.DecSliceUint32V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]uint32:
+ var v2 []uint32
+ v2, changed = fastpathTV.DecSliceUint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []uint64:
+ var v2 []uint64
+ v2, changed = fastpathTV.DecSliceUint64V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]uint64:
+ var v2 []uint64
+ v2, changed = fastpathTV.DecSliceUint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []uintptr:
+ var v2 []uintptr
+ v2, changed = fastpathTV.DecSliceUintptrV(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]uintptr:
+ var v2 []uintptr
+ v2, changed = fastpathTV.DecSliceUintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []int:
+ var v2 []int
+ v2, changed = fastpathTV.DecSliceIntV(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]int:
+ var v2 []int
+ v2, changed = fastpathTV.DecSliceIntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []int8:
+ var v2 []int8
+ v2, changed = fastpathTV.DecSliceInt8V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]int8:
+ var v2 []int8
+ v2, changed = fastpathTV.DecSliceInt8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []int16:
+ var v2 []int16
+ v2, changed = fastpathTV.DecSliceInt16V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]int16:
+ var v2 []int16
+ v2, changed = fastpathTV.DecSliceInt16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []int32:
+ var v2 []int32
+ v2, changed = fastpathTV.DecSliceInt32V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]int32:
+ var v2 []int32
+ v2, changed = fastpathTV.DecSliceInt32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []int64:
+ var v2 []int64
+ v2, changed = fastpathTV.DecSliceInt64V(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]int64:
+ var v2 []int64
+ v2, changed = fastpathTV.DecSliceInt64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case []bool:
+ var v2 []bool
+ v2, changed = fastpathTV.DecSliceBoolV(v, false, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ case *[]bool:
+ var v2 []bool
+ v2, changed = fastpathTV.DecSliceBoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+
+ case map[interface{}]interface{}:
+ fastpathTV.DecMapIntfIntfV(v, false, d)
+ case *map[interface{}]interface{}:
+ var v2 map[interface{}]interface{}
+ v2, changed = fastpathTV.DecMapIntfIntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]string:
+ fastpathTV.DecMapIntfStringV(v, false, d)
+ case *map[interface{}]string:
+ var v2 map[interface{}]string
+ v2, changed = fastpathTV.DecMapIntfStringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]uint:
+ fastpathTV.DecMapIntfUintV(v, false, d)
+ case *map[interface{}]uint:
+ var v2 map[interface{}]uint
+ v2, changed = fastpathTV.DecMapIntfUintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]uint8:
+ fastpathTV.DecMapIntfUint8V(v, false, d)
+ case *map[interface{}]uint8:
+ var v2 map[interface{}]uint8
+ v2, changed = fastpathTV.DecMapIntfUint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]uint16:
+ fastpathTV.DecMapIntfUint16V(v, false, d)
+ case *map[interface{}]uint16:
+ var v2 map[interface{}]uint16
+ v2, changed = fastpathTV.DecMapIntfUint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]uint32:
+ fastpathTV.DecMapIntfUint32V(v, false, d)
+ case *map[interface{}]uint32:
+ var v2 map[interface{}]uint32
+ v2, changed = fastpathTV.DecMapIntfUint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]uint64:
+ fastpathTV.DecMapIntfUint64V(v, false, d)
+ case *map[interface{}]uint64:
+ var v2 map[interface{}]uint64
+ v2, changed = fastpathTV.DecMapIntfUint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]uintptr:
+ fastpathTV.DecMapIntfUintptrV(v, false, d)
+ case *map[interface{}]uintptr:
+ var v2 map[interface{}]uintptr
+ v2, changed = fastpathTV.DecMapIntfUintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]int:
+ fastpathTV.DecMapIntfIntV(v, false, d)
+ case *map[interface{}]int:
+ var v2 map[interface{}]int
+ v2, changed = fastpathTV.DecMapIntfIntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]int8:
+ fastpathTV.DecMapIntfInt8V(v, false, d)
+ case *map[interface{}]int8:
+ var v2 map[interface{}]int8
+ v2, changed = fastpathTV.DecMapIntfInt8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]int16:
+ fastpathTV.DecMapIntfInt16V(v, false, d)
+ case *map[interface{}]int16:
+ var v2 map[interface{}]int16
+ v2, changed = fastpathTV.DecMapIntfInt16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]int32:
+ fastpathTV.DecMapIntfInt32V(v, false, d)
+ case *map[interface{}]int32:
+ var v2 map[interface{}]int32
+ v2, changed = fastpathTV.DecMapIntfInt32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]int64:
+ fastpathTV.DecMapIntfInt64V(v, false, d)
+ case *map[interface{}]int64:
+ var v2 map[interface{}]int64
+ v2, changed = fastpathTV.DecMapIntfInt64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]float32:
+ fastpathTV.DecMapIntfFloat32V(v, false, d)
+ case *map[interface{}]float32:
+ var v2 map[interface{}]float32
+ v2, changed = fastpathTV.DecMapIntfFloat32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]float64:
+ fastpathTV.DecMapIntfFloat64V(v, false, d)
+ case *map[interface{}]float64:
+ var v2 map[interface{}]float64
+ v2, changed = fastpathTV.DecMapIntfFloat64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[interface{}]bool:
+ fastpathTV.DecMapIntfBoolV(v, false, d)
+ case *map[interface{}]bool:
+ var v2 map[interface{}]bool
+ v2, changed = fastpathTV.DecMapIntfBoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]interface{}:
+ fastpathTV.DecMapStringIntfV(v, false, d)
+ case *map[string]interface{}:
+ var v2 map[string]interface{}
+ v2, changed = fastpathTV.DecMapStringIntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]string:
+ fastpathTV.DecMapStringStringV(v, false, d)
+ case *map[string]string:
+ var v2 map[string]string
+ v2, changed = fastpathTV.DecMapStringStringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]uint:
+ fastpathTV.DecMapStringUintV(v, false, d)
+ case *map[string]uint:
+ var v2 map[string]uint
+ v2, changed = fastpathTV.DecMapStringUintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]uint8:
+ fastpathTV.DecMapStringUint8V(v, false, d)
+ case *map[string]uint8:
+ var v2 map[string]uint8
+ v2, changed = fastpathTV.DecMapStringUint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]uint16:
+ fastpathTV.DecMapStringUint16V(v, false, d)
+ case *map[string]uint16:
+ var v2 map[string]uint16
+ v2, changed = fastpathTV.DecMapStringUint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]uint32:
+ fastpathTV.DecMapStringUint32V(v, false, d)
+ case *map[string]uint32:
+ var v2 map[string]uint32
+ v2, changed = fastpathTV.DecMapStringUint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]uint64:
+ fastpathTV.DecMapStringUint64V(v, false, d)
+ case *map[string]uint64:
+ var v2 map[string]uint64
+ v2, changed = fastpathTV.DecMapStringUint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]uintptr:
+ fastpathTV.DecMapStringUintptrV(v, false, d)
+ case *map[string]uintptr:
+ var v2 map[string]uintptr
+ v2, changed = fastpathTV.DecMapStringUintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]int:
+ fastpathTV.DecMapStringIntV(v, false, d)
+ case *map[string]int:
+ var v2 map[string]int
+ v2, changed = fastpathTV.DecMapStringIntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]int8:
+ fastpathTV.DecMapStringInt8V(v, false, d)
+ case *map[string]int8:
+ var v2 map[string]int8
+ v2, changed = fastpathTV.DecMapStringInt8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]int16:
+ fastpathTV.DecMapStringInt16V(v, false, d)
+ case *map[string]int16:
+ var v2 map[string]int16
+ v2, changed = fastpathTV.DecMapStringInt16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]int32:
+ fastpathTV.DecMapStringInt32V(v, false, d)
+ case *map[string]int32:
+ var v2 map[string]int32
+ v2, changed = fastpathTV.DecMapStringInt32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]int64:
+ fastpathTV.DecMapStringInt64V(v, false, d)
+ case *map[string]int64:
+ var v2 map[string]int64
+ v2, changed = fastpathTV.DecMapStringInt64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]float32:
+ fastpathTV.DecMapStringFloat32V(v, false, d)
+ case *map[string]float32:
+ var v2 map[string]float32
+ v2, changed = fastpathTV.DecMapStringFloat32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]float64:
+ fastpathTV.DecMapStringFloat64V(v, false, d)
+ case *map[string]float64:
+ var v2 map[string]float64
+ v2, changed = fastpathTV.DecMapStringFloat64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[string]bool:
+ fastpathTV.DecMapStringBoolV(v, false, d)
+ case *map[string]bool:
+ var v2 map[string]bool
+ v2, changed = fastpathTV.DecMapStringBoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]interface{}:
+ fastpathTV.DecMapFloat32IntfV(v, false, d)
+ case *map[float32]interface{}:
+ var v2 map[float32]interface{}
+ v2, changed = fastpathTV.DecMapFloat32IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]string:
+ fastpathTV.DecMapFloat32StringV(v, false, d)
+ case *map[float32]string:
+ var v2 map[float32]string
+ v2, changed = fastpathTV.DecMapFloat32StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]uint:
+ fastpathTV.DecMapFloat32UintV(v, false, d)
+ case *map[float32]uint:
+ var v2 map[float32]uint
+ v2, changed = fastpathTV.DecMapFloat32UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]uint8:
+ fastpathTV.DecMapFloat32Uint8V(v, false, d)
+ case *map[float32]uint8:
+ var v2 map[float32]uint8
+ v2, changed = fastpathTV.DecMapFloat32Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]uint16:
+ fastpathTV.DecMapFloat32Uint16V(v, false, d)
+ case *map[float32]uint16:
+ var v2 map[float32]uint16
+ v2, changed = fastpathTV.DecMapFloat32Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]uint32:
+ fastpathTV.DecMapFloat32Uint32V(v, false, d)
+ case *map[float32]uint32:
+ var v2 map[float32]uint32
+ v2, changed = fastpathTV.DecMapFloat32Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]uint64:
+ fastpathTV.DecMapFloat32Uint64V(v, false, d)
+ case *map[float32]uint64:
+ var v2 map[float32]uint64
+ v2, changed = fastpathTV.DecMapFloat32Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]uintptr:
+ fastpathTV.DecMapFloat32UintptrV(v, false, d)
+ case *map[float32]uintptr:
+ var v2 map[float32]uintptr
+ v2, changed = fastpathTV.DecMapFloat32UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]int:
+ fastpathTV.DecMapFloat32IntV(v, false, d)
+ case *map[float32]int:
+ var v2 map[float32]int
+ v2, changed = fastpathTV.DecMapFloat32IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]int8:
+ fastpathTV.DecMapFloat32Int8V(v, false, d)
+ case *map[float32]int8:
+ var v2 map[float32]int8
+ v2, changed = fastpathTV.DecMapFloat32Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]int16:
+ fastpathTV.DecMapFloat32Int16V(v, false, d)
+ case *map[float32]int16:
+ var v2 map[float32]int16
+ v2, changed = fastpathTV.DecMapFloat32Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]int32:
+ fastpathTV.DecMapFloat32Int32V(v, false, d)
+ case *map[float32]int32:
+ var v2 map[float32]int32
+ v2, changed = fastpathTV.DecMapFloat32Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]int64:
+ fastpathTV.DecMapFloat32Int64V(v, false, d)
+ case *map[float32]int64:
+ var v2 map[float32]int64
+ v2, changed = fastpathTV.DecMapFloat32Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]float32:
+ fastpathTV.DecMapFloat32Float32V(v, false, d)
+ case *map[float32]float32:
+ var v2 map[float32]float32
+ v2, changed = fastpathTV.DecMapFloat32Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]float64:
+ fastpathTV.DecMapFloat32Float64V(v, false, d)
+ case *map[float32]float64:
+ var v2 map[float32]float64
+ v2, changed = fastpathTV.DecMapFloat32Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float32]bool:
+ fastpathTV.DecMapFloat32BoolV(v, false, d)
+ case *map[float32]bool:
+ var v2 map[float32]bool
+ v2, changed = fastpathTV.DecMapFloat32BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]interface{}:
+ fastpathTV.DecMapFloat64IntfV(v, false, d)
+ case *map[float64]interface{}:
+ var v2 map[float64]interface{}
+ v2, changed = fastpathTV.DecMapFloat64IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]string:
+ fastpathTV.DecMapFloat64StringV(v, false, d)
+ case *map[float64]string:
+ var v2 map[float64]string
+ v2, changed = fastpathTV.DecMapFloat64StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]uint:
+ fastpathTV.DecMapFloat64UintV(v, false, d)
+ case *map[float64]uint:
+ var v2 map[float64]uint
+ v2, changed = fastpathTV.DecMapFloat64UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]uint8:
+ fastpathTV.DecMapFloat64Uint8V(v, false, d)
+ case *map[float64]uint8:
+ var v2 map[float64]uint8
+ v2, changed = fastpathTV.DecMapFloat64Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]uint16:
+ fastpathTV.DecMapFloat64Uint16V(v, false, d)
+ case *map[float64]uint16:
+ var v2 map[float64]uint16
+ v2, changed = fastpathTV.DecMapFloat64Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]uint32:
+ fastpathTV.DecMapFloat64Uint32V(v, false, d)
+ case *map[float64]uint32:
+ var v2 map[float64]uint32
+ v2, changed = fastpathTV.DecMapFloat64Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]uint64:
+ fastpathTV.DecMapFloat64Uint64V(v, false, d)
+ case *map[float64]uint64:
+ var v2 map[float64]uint64
+ v2, changed = fastpathTV.DecMapFloat64Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]uintptr:
+ fastpathTV.DecMapFloat64UintptrV(v, false, d)
+ case *map[float64]uintptr:
+ var v2 map[float64]uintptr
+ v2, changed = fastpathTV.DecMapFloat64UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]int:
+ fastpathTV.DecMapFloat64IntV(v, false, d)
+ case *map[float64]int:
+ var v2 map[float64]int
+ v2, changed = fastpathTV.DecMapFloat64IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]int8:
+ fastpathTV.DecMapFloat64Int8V(v, false, d)
+ case *map[float64]int8:
+ var v2 map[float64]int8
+ v2, changed = fastpathTV.DecMapFloat64Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]int16:
+ fastpathTV.DecMapFloat64Int16V(v, false, d)
+ case *map[float64]int16:
+ var v2 map[float64]int16
+ v2, changed = fastpathTV.DecMapFloat64Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]int32:
+ fastpathTV.DecMapFloat64Int32V(v, false, d)
+ case *map[float64]int32:
+ var v2 map[float64]int32
+ v2, changed = fastpathTV.DecMapFloat64Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]int64:
+ fastpathTV.DecMapFloat64Int64V(v, false, d)
+ case *map[float64]int64:
+ var v2 map[float64]int64
+ v2, changed = fastpathTV.DecMapFloat64Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]float32:
+ fastpathTV.DecMapFloat64Float32V(v, false, d)
+ case *map[float64]float32:
+ var v2 map[float64]float32
+ v2, changed = fastpathTV.DecMapFloat64Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]float64:
+ fastpathTV.DecMapFloat64Float64V(v, false, d)
+ case *map[float64]float64:
+ var v2 map[float64]float64
+ v2, changed = fastpathTV.DecMapFloat64Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[float64]bool:
+ fastpathTV.DecMapFloat64BoolV(v, false, d)
+ case *map[float64]bool:
+ var v2 map[float64]bool
+ v2, changed = fastpathTV.DecMapFloat64BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]interface{}:
+ fastpathTV.DecMapUintIntfV(v, false, d)
+ case *map[uint]interface{}:
+ var v2 map[uint]interface{}
+ v2, changed = fastpathTV.DecMapUintIntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]string:
+ fastpathTV.DecMapUintStringV(v, false, d)
+ case *map[uint]string:
+ var v2 map[uint]string
+ v2, changed = fastpathTV.DecMapUintStringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]uint:
+ fastpathTV.DecMapUintUintV(v, false, d)
+ case *map[uint]uint:
+ var v2 map[uint]uint
+ v2, changed = fastpathTV.DecMapUintUintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]uint8:
+ fastpathTV.DecMapUintUint8V(v, false, d)
+ case *map[uint]uint8:
+ var v2 map[uint]uint8
+ v2, changed = fastpathTV.DecMapUintUint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]uint16:
+ fastpathTV.DecMapUintUint16V(v, false, d)
+ case *map[uint]uint16:
+ var v2 map[uint]uint16
+ v2, changed = fastpathTV.DecMapUintUint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]uint32:
+ fastpathTV.DecMapUintUint32V(v, false, d)
+ case *map[uint]uint32:
+ var v2 map[uint]uint32
+ v2, changed = fastpathTV.DecMapUintUint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]uint64:
+ fastpathTV.DecMapUintUint64V(v, false, d)
+ case *map[uint]uint64:
+ var v2 map[uint]uint64
+ v2, changed = fastpathTV.DecMapUintUint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]uintptr:
+ fastpathTV.DecMapUintUintptrV(v, false, d)
+ case *map[uint]uintptr:
+ var v2 map[uint]uintptr
+ v2, changed = fastpathTV.DecMapUintUintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]int:
+ fastpathTV.DecMapUintIntV(v, false, d)
+ case *map[uint]int:
+ var v2 map[uint]int
+ v2, changed = fastpathTV.DecMapUintIntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]int8:
+ fastpathTV.DecMapUintInt8V(v, false, d)
+ case *map[uint]int8:
+ var v2 map[uint]int8
+ v2, changed = fastpathTV.DecMapUintInt8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]int16:
+ fastpathTV.DecMapUintInt16V(v, false, d)
+ case *map[uint]int16:
+ var v2 map[uint]int16
+ v2, changed = fastpathTV.DecMapUintInt16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]int32:
+ fastpathTV.DecMapUintInt32V(v, false, d)
+ case *map[uint]int32:
+ var v2 map[uint]int32
+ v2, changed = fastpathTV.DecMapUintInt32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]int64:
+ fastpathTV.DecMapUintInt64V(v, false, d)
+ case *map[uint]int64:
+ var v2 map[uint]int64
+ v2, changed = fastpathTV.DecMapUintInt64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]float32:
+ fastpathTV.DecMapUintFloat32V(v, false, d)
+ case *map[uint]float32:
+ var v2 map[uint]float32
+ v2, changed = fastpathTV.DecMapUintFloat32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]float64:
+ fastpathTV.DecMapUintFloat64V(v, false, d)
+ case *map[uint]float64:
+ var v2 map[uint]float64
+ v2, changed = fastpathTV.DecMapUintFloat64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint]bool:
+ fastpathTV.DecMapUintBoolV(v, false, d)
+ case *map[uint]bool:
+ var v2 map[uint]bool
+ v2, changed = fastpathTV.DecMapUintBoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]interface{}:
+ fastpathTV.DecMapUint8IntfV(v, false, d)
+ case *map[uint8]interface{}:
+ var v2 map[uint8]interface{}
+ v2, changed = fastpathTV.DecMapUint8IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]string:
+ fastpathTV.DecMapUint8StringV(v, false, d)
+ case *map[uint8]string:
+ var v2 map[uint8]string
+ v2, changed = fastpathTV.DecMapUint8StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]uint:
+ fastpathTV.DecMapUint8UintV(v, false, d)
+ case *map[uint8]uint:
+ var v2 map[uint8]uint
+ v2, changed = fastpathTV.DecMapUint8UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]uint8:
+ fastpathTV.DecMapUint8Uint8V(v, false, d)
+ case *map[uint8]uint8:
+ var v2 map[uint8]uint8
+ v2, changed = fastpathTV.DecMapUint8Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]uint16:
+ fastpathTV.DecMapUint8Uint16V(v, false, d)
+ case *map[uint8]uint16:
+ var v2 map[uint8]uint16
+ v2, changed = fastpathTV.DecMapUint8Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]uint32:
+ fastpathTV.DecMapUint8Uint32V(v, false, d)
+ case *map[uint8]uint32:
+ var v2 map[uint8]uint32
+ v2, changed = fastpathTV.DecMapUint8Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]uint64:
+ fastpathTV.DecMapUint8Uint64V(v, false, d)
+ case *map[uint8]uint64:
+ var v2 map[uint8]uint64
+ v2, changed = fastpathTV.DecMapUint8Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]uintptr:
+ fastpathTV.DecMapUint8UintptrV(v, false, d)
+ case *map[uint8]uintptr:
+ var v2 map[uint8]uintptr
+ v2, changed = fastpathTV.DecMapUint8UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]int:
+ fastpathTV.DecMapUint8IntV(v, false, d)
+ case *map[uint8]int:
+ var v2 map[uint8]int
+ v2, changed = fastpathTV.DecMapUint8IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]int8:
+ fastpathTV.DecMapUint8Int8V(v, false, d)
+ case *map[uint8]int8:
+ var v2 map[uint8]int8
+ v2, changed = fastpathTV.DecMapUint8Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]int16:
+ fastpathTV.DecMapUint8Int16V(v, false, d)
+ case *map[uint8]int16:
+ var v2 map[uint8]int16
+ v2, changed = fastpathTV.DecMapUint8Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]int32:
+ fastpathTV.DecMapUint8Int32V(v, false, d)
+ case *map[uint8]int32:
+ var v2 map[uint8]int32
+ v2, changed = fastpathTV.DecMapUint8Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]int64:
+ fastpathTV.DecMapUint8Int64V(v, false, d)
+ case *map[uint8]int64:
+ var v2 map[uint8]int64
+ v2, changed = fastpathTV.DecMapUint8Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]float32:
+ fastpathTV.DecMapUint8Float32V(v, false, d)
+ case *map[uint8]float32:
+ var v2 map[uint8]float32
+ v2, changed = fastpathTV.DecMapUint8Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]float64:
+ fastpathTV.DecMapUint8Float64V(v, false, d)
+ case *map[uint8]float64:
+ var v2 map[uint8]float64
+ v2, changed = fastpathTV.DecMapUint8Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint8]bool:
+ fastpathTV.DecMapUint8BoolV(v, false, d)
+ case *map[uint8]bool:
+ var v2 map[uint8]bool
+ v2, changed = fastpathTV.DecMapUint8BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]interface{}:
+ fastpathTV.DecMapUint16IntfV(v, false, d)
+ case *map[uint16]interface{}:
+ var v2 map[uint16]interface{}
+ v2, changed = fastpathTV.DecMapUint16IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]string:
+ fastpathTV.DecMapUint16StringV(v, false, d)
+ case *map[uint16]string:
+ var v2 map[uint16]string
+ v2, changed = fastpathTV.DecMapUint16StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]uint:
+ fastpathTV.DecMapUint16UintV(v, false, d)
+ case *map[uint16]uint:
+ var v2 map[uint16]uint
+ v2, changed = fastpathTV.DecMapUint16UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]uint8:
+ fastpathTV.DecMapUint16Uint8V(v, false, d)
+ case *map[uint16]uint8:
+ var v2 map[uint16]uint8
+ v2, changed = fastpathTV.DecMapUint16Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]uint16:
+ fastpathTV.DecMapUint16Uint16V(v, false, d)
+ case *map[uint16]uint16:
+ var v2 map[uint16]uint16
+ v2, changed = fastpathTV.DecMapUint16Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]uint32:
+ fastpathTV.DecMapUint16Uint32V(v, false, d)
+ case *map[uint16]uint32:
+ var v2 map[uint16]uint32
+ v2, changed = fastpathTV.DecMapUint16Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]uint64:
+ fastpathTV.DecMapUint16Uint64V(v, false, d)
+ case *map[uint16]uint64:
+ var v2 map[uint16]uint64
+ v2, changed = fastpathTV.DecMapUint16Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]uintptr:
+ fastpathTV.DecMapUint16UintptrV(v, false, d)
+ case *map[uint16]uintptr:
+ var v2 map[uint16]uintptr
+ v2, changed = fastpathTV.DecMapUint16UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]int:
+ fastpathTV.DecMapUint16IntV(v, false, d)
+ case *map[uint16]int:
+ var v2 map[uint16]int
+ v2, changed = fastpathTV.DecMapUint16IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]int8:
+ fastpathTV.DecMapUint16Int8V(v, false, d)
+ case *map[uint16]int8:
+ var v2 map[uint16]int8
+ v2, changed = fastpathTV.DecMapUint16Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]int16:
+ fastpathTV.DecMapUint16Int16V(v, false, d)
+ case *map[uint16]int16:
+ var v2 map[uint16]int16
+ v2, changed = fastpathTV.DecMapUint16Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]int32:
+ fastpathTV.DecMapUint16Int32V(v, false, d)
+ case *map[uint16]int32:
+ var v2 map[uint16]int32
+ v2, changed = fastpathTV.DecMapUint16Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]int64:
+ fastpathTV.DecMapUint16Int64V(v, false, d)
+ case *map[uint16]int64:
+ var v2 map[uint16]int64
+ v2, changed = fastpathTV.DecMapUint16Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]float32:
+ fastpathTV.DecMapUint16Float32V(v, false, d)
+ case *map[uint16]float32:
+ var v2 map[uint16]float32
+ v2, changed = fastpathTV.DecMapUint16Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]float64:
+ fastpathTV.DecMapUint16Float64V(v, false, d)
+ case *map[uint16]float64:
+ var v2 map[uint16]float64
+ v2, changed = fastpathTV.DecMapUint16Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint16]bool:
+ fastpathTV.DecMapUint16BoolV(v, false, d)
+ case *map[uint16]bool:
+ var v2 map[uint16]bool
+ v2, changed = fastpathTV.DecMapUint16BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]interface{}:
+ fastpathTV.DecMapUint32IntfV(v, false, d)
+ case *map[uint32]interface{}:
+ var v2 map[uint32]interface{}
+ v2, changed = fastpathTV.DecMapUint32IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]string:
+ fastpathTV.DecMapUint32StringV(v, false, d)
+ case *map[uint32]string:
+ var v2 map[uint32]string
+ v2, changed = fastpathTV.DecMapUint32StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]uint:
+ fastpathTV.DecMapUint32UintV(v, false, d)
+ case *map[uint32]uint:
+ var v2 map[uint32]uint
+ v2, changed = fastpathTV.DecMapUint32UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]uint8:
+ fastpathTV.DecMapUint32Uint8V(v, false, d)
+ case *map[uint32]uint8:
+ var v2 map[uint32]uint8
+ v2, changed = fastpathTV.DecMapUint32Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]uint16:
+ fastpathTV.DecMapUint32Uint16V(v, false, d)
+ case *map[uint32]uint16:
+ var v2 map[uint32]uint16
+ v2, changed = fastpathTV.DecMapUint32Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]uint32:
+ fastpathTV.DecMapUint32Uint32V(v, false, d)
+ case *map[uint32]uint32:
+ var v2 map[uint32]uint32
+ v2, changed = fastpathTV.DecMapUint32Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]uint64:
+ fastpathTV.DecMapUint32Uint64V(v, false, d)
+ case *map[uint32]uint64:
+ var v2 map[uint32]uint64
+ v2, changed = fastpathTV.DecMapUint32Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]uintptr:
+ fastpathTV.DecMapUint32UintptrV(v, false, d)
+ case *map[uint32]uintptr:
+ var v2 map[uint32]uintptr
+ v2, changed = fastpathTV.DecMapUint32UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]int:
+ fastpathTV.DecMapUint32IntV(v, false, d)
+ case *map[uint32]int:
+ var v2 map[uint32]int
+ v2, changed = fastpathTV.DecMapUint32IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]int8:
+ fastpathTV.DecMapUint32Int8V(v, false, d)
+ case *map[uint32]int8:
+ var v2 map[uint32]int8
+ v2, changed = fastpathTV.DecMapUint32Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]int16:
+ fastpathTV.DecMapUint32Int16V(v, false, d)
+ case *map[uint32]int16:
+ var v2 map[uint32]int16
+ v2, changed = fastpathTV.DecMapUint32Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]int32:
+ fastpathTV.DecMapUint32Int32V(v, false, d)
+ case *map[uint32]int32:
+ var v2 map[uint32]int32
+ v2, changed = fastpathTV.DecMapUint32Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]int64:
+ fastpathTV.DecMapUint32Int64V(v, false, d)
+ case *map[uint32]int64:
+ var v2 map[uint32]int64
+ v2, changed = fastpathTV.DecMapUint32Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]float32:
+ fastpathTV.DecMapUint32Float32V(v, false, d)
+ case *map[uint32]float32:
+ var v2 map[uint32]float32
+ v2, changed = fastpathTV.DecMapUint32Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]float64:
+ fastpathTV.DecMapUint32Float64V(v, false, d)
+ case *map[uint32]float64:
+ var v2 map[uint32]float64
+ v2, changed = fastpathTV.DecMapUint32Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint32]bool:
+ fastpathTV.DecMapUint32BoolV(v, false, d)
+ case *map[uint32]bool:
+ var v2 map[uint32]bool
+ v2, changed = fastpathTV.DecMapUint32BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]interface{}:
+ fastpathTV.DecMapUint64IntfV(v, false, d)
+ case *map[uint64]interface{}:
+ var v2 map[uint64]interface{}
+ v2, changed = fastpathTV.DecMapUint64IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]string:
+ fastpathTV.DecMapUint64StringV(v, false, d)
+ case *map[uint64]string:
+ var v2 map[uint64]string
+ v2, changed = fastpathTV.DecMapUint64StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]uint:
+ fastpathTV.DecMapUint64UintV(v, false, d)
+ case *map[uint64]uint:
+ var v2 map[uint64]uint
+ v2, changed = fastpathTV.DecMapUint64UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]uint8:
+ fastpathTV.DecMapUint64Uint8V(v, false, d)
+ case *map[uint64]uint8:
+ var v2 map[uint64]uint8
+ v2, changed = fastpathTV.DecMapUint64Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]uint16:
+ fastpathTV.DecMapUint64Uint16V(v, false, d)
+ case *map[uint64]uint16:
+ var v2 map[uint64]uint16
+ v2, changed = fastpathTV.DecMapUint64Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]uint32:
+ fastpathTV.DecMapUint64Uint32V(v, false, d)
+ case *map[uint64]uint32:
+ var v2 map[uint64]uint32
+ v2, changed = fastpathTV.DecMapUint64Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]uint64:
+ fastpathTV.DecMapUint64Uint64V(v, false, d)
+ case *map[uint64]uint64:
+ var v2 map[uint64]uint64
+ v2, changed = fastpathTV.DecMapUint64Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]uintptr:
+ fastpathTV.DecMapUint64UintptrV(v, false, d)
+ case *map[uint64]uintptr:
+ var v2 map[uint64]uintptr
+ v2, changed = fastpathTV.DecMapUint64UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]int:
+ fastpathTV.DecMapUint64IntV(v, false, d)
+ case *map[uint64]int:
+ var v2 map[uint64]int
+ v2, changed = fastpathTV.DecMapUint64IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]int8:
+ fastpathTV.DecMapUint64Int8V(v, false, d)
+ case *map[uint64]int8:
+ var v2 map[uint64]int8
+ v2, changed = fastpathTV.DecMapUint64Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]int16:
+ fastpathTV.DecMapUint64Int16V(v, false, d)
+ case *map[uint64]int16:
+ var v2 map[uint64]int16
+ v2, changed = fastpathTV.DecMapUint64Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]int32:
+ fastpathTV.DecMapUint64Int32V(v, false, d)
+ case *map[uint64]int32:
+ var v2 map[uint64]int32
+ v2, changed = fastpathTV.DecMapUint64Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]int64:
+ fastpathTV.DecMapUint64Int64V(v, false, d)
+ case *map[uint64]int64:
+ var v2 map[uint64]int64
+ v2, changed = fastpathTV.DecMapUint64Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]float32:
+ fastpathTV.DecMapUint64Float32V(v, false, d)
+ case *map[uint64]float32:
+ var v2 map[uint64]float32
+ v2, changed = fastpathTV.DecMapUint64Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]float64:
+ fastpathTV.DecMapUint64Float64V(v, false, d)
+ case *map[uint64]float64:
+ var v2 map[uint64]float64
+ v2, changed = fastpathTV.DecMapUint64Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uint64]bool:
+ fastpathTV.DecMapUint64BoolV(v, false, d)
+ case *map[uint64]bool:
+ var v2 map[uint64]bool
+ v2, changed = fastpathTV.DecMapUint64BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]interface{}:
+ fastpathTV.DecMapUintptrIntfV(v, false, d)
+ case *map[uintptr]interface{}:
+ var v2 map[uintptr]interface{}
+ v2, changed = fastpathTV.DecMapUintptrIntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]string:
+ fastpathTV.DecMapUintptrStringV(v, false, d)
+ case *map[uintptr]string:
+ var v2 map[uintptr]string
+ v2, changed = fastpathTV.DecMapUintptrStringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]uint:
+ fastpathTV.DecMapUintptrUintV(v, false, d)
+ case *map[uintptr]uint:
+ var v2 map[uintptr]uint
+ v2, changed = fastpathTV.DecMapUintptrUintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]uint8:
+ fastpathTV.DecMapUintptrUint8V(v, false, d)
+ case *map[uintptr]uint8:
+ var v2 map[uintptr]uint8
+ v2, changed = fastpathTV.DecMapUintptrUint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]uint16:
+ fastpathTV.DecMapUintptrUint16V(v, false, d)
+ case *map[uintptr]uint16:
+ var v2 map[uintptr]uint16
+ v2, changed = fastpathTV.DecMapUintptrUint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]uint32:
+ fastpathTV.DecMapUintptrUint32V(v, false, d)
+ case *map[uintptr]uint32:
+ var v2 map[uintptr]uint32
+ v2, changed = fastpathTV.DecMapUintptrUint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]uint64:
+ fastpathTV.DecMapUintptrUint64V(v, false, d)
+ case *map[uintptr]uint64:
+ var v2 map[uintptr]uint64
+ v2, changed = fastpathTV.DecMapUintptrUint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]uintptr:
+ fastpathTV.DecMapUintptrUintptrV(v, false, d)
+ case *map[uintptr]uintptr:
+ var v2 map[uintptr]uintptr
+ v2, changed = fastpathTV.DecMapUintptrUintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]int:
+ fastpathTV.DecMapUintptrIntV(v, false, d)
+ case *map[uintptr]int:
+ var v2 map[uintptr]int
+ v2, changed = fastpathTV.DecMapUintptrIntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]int8:
+ fastpathTV.DecMapUintptrInt8V(v, false, d)
+ case *map[uintptr]int8:
+ var v2 map[uintptr]int8
+ v2, changed = fastpathTV.DecMapUintptrInt8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]int16:
+ fastpathTV.DecMapUintptrInt16V(v, false, d)
+ case *map[uintptr]int16:
+ var v2 map[uintptr]int16
+ v2, changed = fastpathTV.DecMapUintptrInt16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]int32:
+ fastpathTV.DecMapUintptrInt32V(v, false, d)
+ case *map[uintptr]int32:
+ var v2 map[uintptr]int32
+ v2, changed = fastpathTV.DecMapUintptrInt32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]int64:
+ fastpathTV.DecMapUintptrInt64V(v, false, d)
+ case *map[uintptr]int64:
+ var v2 map[uintptr]int64
+ v2, changed = fastpathTV.DecMapUintptrInt64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]float32:
+ fastpathTV.DecMapUintptrFloat32V(v, false, d)
+ case *map[uintptr]float32:
+ var v2 map[uintptr]float32
+ v2, changed = fastpathTV.DecMapUintptrFloat32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]float64:
+ fastpathTV.DecMapUintptrFloat64V(v, false, d)
+ case *map[uintptr]float64:
+ var v2 map[uintptr]float64
+ v2, changed = fastpathTV.DecMapUintptrFloat64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[uintptr]bool:
+ fastpathTV.DecMapUintptrBoolV(v, false, d)
+ case *map[uintptr]bool:
+ var v2 map[uintptr]bool
+ v2, changed = fastpathTV.DecMapUintptrBoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]interface{}:
+ fastpathTV.DecMapIntIntfV(v, false, d)
+ case *map[int]interface{}:
+ var v2 map[int]interface{}
+ v2, changed = fastpathTV.DecMapIntIntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]string:
+ fastpathTV.DecMapIntStringV(v, false, d)
+ case *map[int]string:
+ var v2 map[int]string
+ v2, changed = fastpathTV.DecMapIntStringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]uint:
+ fastpathTV.DecMapIntUintV(v, false, d)
+ case *map[int]uint:
+ var v2 map[int]uint
+ v2, changed = fastpathTV.DecMapIntUintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]uint8:
+ fastpathTV.DecMapIntUint8V(v, false, d)
+ case *map[int]uint8:
+ var v2 map[int]uint8
+ v2, changed = fastpathTV.DecMapIntUint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]uint16:
+ fastpathTV.DecMapIntUint16V(v, false, d)
+ case *map[int]uint16:
+ var v2 map[int]uint16
+ v2, changed = fastpathTV.DecMapIntUint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]uint32:
+ fastpathTV.DecMapIntUint32V(v, false, d)
+ case *map[int]uint32:
+ var v2 map[int]uint32
+ v2, changed = fastpathTV.DecMapIntUint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]uint64:
+ fastpathTV.DecMapIntUint64V(v, false, d)
+ case *map[int]uint64:
+ var v2 map[int]uint64
+ v2, changed = fastpathTV.DecMapIntUint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]uintptr:
+ fastpathTV.DecMapIntUintptrV(v, false, d)
+ case *map[int]uintptr:
+ var v2 map[int]uintptr
+ v2, changed = fastpathTV.DecMapIntUintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]int:
+ fastpathTV.DecMapIntIntV(v, false, d)
+ case *map[int]int:
+ var v2 map[int]int
+ v2, changed = fastpathTV.DecMapIntIntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]int8:
+ fastpathTV.DecMapIntInt8V(v, false, d)
+ case *map[int]int8:
+ var v2 map[int]int8
+ v2, changed = fastpathTV.DecMapIntInt8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]int16:
+ fastpathTV.DecMapIntInt16V(v, false, d)
+ case *map[int]int16:
+ var v2 map[int]int16
+ v2, changed = fastpathTV.DecMapIntInt16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]int32:
+ fastpathTV.DecMapIntInt32V(v, false, d)
+ case *map[int]int32:
+ var v2 map[int]int32
+ v2, changed = fastpathTV.DecMapIntInt32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]int64:
+ fastpathTV.DecMapIntInt64V(v, false, d)
+ case *map[int]int64:
+ var v2 map[int]int64
+ v2, changed = fastpathTV.DecMapIntInt64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]float32:
+ fastpathTV.DecMapIntFloat32V(v, false, d)
+ case *map[int]float32:
+ var v2 map[int]float32
+ v2, changed = fastpathTV.DecMapIntFloat32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]float64:
+ fastpathTV.DecMapIntFloat64V(v, false, d)
+ case *map[int]float64:
+ var v2 map[int]float64
+ v2, changed = fastpathTV.DecMapIntFloat64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int]bool:
+ fastpathTV.DecMapIntBoolV(v, false, d)
+ case *map[int]bool:
+ var v2 map[int]bool
+ v2, changed = fastpathTV.DecMapIntBoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]interface{}:
+ fastpathTV.DecMapInt8IntfV(v, false, d)
+ case *map[int8]interface{}:
+ var v2 map[int8]interface{}
+ v2, changed = fastpathTV.DecMapInt8IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]string:
+ fastpathTV.DecMapInt8StringV(v, false, d)
+ case *map[int8]string:
+ var v2 map[int8]string
+ v2, changed = fastpathTV.DecMapInt8StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]uint:
+ fastpathTV.DecMapInt8UintV(v, false, d)
+ case *map[int8]uint:
+ var v2 map[int8]uint
+ v2, changed = fastpathTV.DecMapInt8UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]uint8:
+ fastpathTV.DecMapInt8Uint8V(v, false, d)
+ case *map[int8]uint8:
+ var v2 map[int8]uint8
+ v2, changed = fastpathTV.DecMapInt8Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]uint16:
+ fastpathTV.DecMapInt8Uint16V(v, false, d)
+ case *map[int8]uint16:
+ var v2 map[int8]uint16
+ v2, changed = fastpathTV.DecMapInt8Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]uint32:
+ fastpathTV.DecMapInt8Uint32V(v, false, d)
+ case *map[int8]uint32:
+ var v2 map[int8]uint32
+ v2, changed = fastpathTV.DecMapInt8Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]uint64:
+ fastpathTV.DecMapInt8Uint64V(v, false, d)
+ case *map[int8]uint64:
+ var v2 map[int8]uint64
+ v2, changed = fastpathTV.DecMapInt8Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]uintptr:
+ fastpathTV.DecMapInt8UintptrV(v, false, d)
+ case *map[int8]uintptr:
+ var v2 map[int8]uintptr
+ v2, changed = fastpathTV.DecMapInt8UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]int:
+ fastpathTV.DecMapInt8IntV(v, false, d)
+ case *map[int8]int:
+ var v2 map[int8]int
+ v2, changed = fastpathTV.DecMapInt8IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]int8:
+ fastpathTV.DecMapInt8Int8V(v, false, d)
+ case *map[int8]int8:
+ var v2 map[int8]int8
+ v2, changed = fastpathTV.DecMapInt8Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]int16:
+ fastpathTV.DecMapInt8Int16V(v, false, d)
+ case *map[int8]int16:
+ var v2 map[int8]int16
+ v2, changed = fastpathTV.DecMapInt8Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]int32:
+ fastpathTV.DecMapInt8Int32V(v, false, d)
+ case *map[int8]int32:
+ var v2 map[int8]int32
+ v2, changed = fastpathTV.DecMapInt8Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]int64:
+ fastpathTV.DecMapInt8Int64V(v, false, d)
+ case *map[int8]int64:
+ var v2 map[int8]int64
+ v2, changed = fastpathTV.DecMapInt8Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]float32:
+ fastpathTV.DecMapInt8Float32V(v, false, d)
+ case *map[int8]float32:
+ var v2 map[int8]float32
+ v2, changed = fastpathTV.DecMapInt8Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]float64:
+ fastpathTV.DecMapInt8Float64V(v, false, d)
+ case *map[int8]float64:
+ var v2 map[int8]float64
+ v2, changed = fastpathTV.DecMapInt8Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int8]bool:
+ fastpathTV.DecMapInt8BoolV(v, false, d)
+ case *map[int8]bool:
+ var v2 map[int8]bool
+ v2, changed = fastpathTV.DecMapInt8BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]interface{}:
+ fastpathTV.DecMapInt16IntfV(v, false, d)
+ case *map[int16]interface{}:
+ var v2 map[int16]interface{}
+ v2, changed = fastpathTV.DecMapInt16IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]string:
+ fastpathTV.DecMapInt16StringV(v, false, d)
+ case *map[int16]string:
+ var v2 map[int16]string
+ v2, changed = fastpathTV.DecMapInt16StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]uint:
+ fastpathTV.DecMapInt16UintV(v, false, d)
+ case *map[int16]uint:
+ var v2 map[int16]uint
+ v2, changed = fastpathTV.DecMapInt16UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]uint8:
+ fastpathTV.DecMapInt16Uint8V(v, false, d)
+ case *map[int16]uint8:
+ var v2 map[int16]uint8
+ v2, changed = fastpathTV.DecMapInt16Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]uint16:
+ fastpathTV.DecMapInt16Uint16V(v, false, d)
+ case *map[int16]uint16:
+ var v2 map[int16]uint16
+ v2, changed = fastpathTV.DecMapInt16Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]uint32:
+ fastpathTV.DecMapInt16Uint32V(v, false, d)
+ case *map[int16]uint32:
+ var v2 map[int16]uint32
+ v2, changed = fastpathTV.DecMapInt16Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]uint64:
+ fastpathTV.DecMapInt16Uint64V(v, false, d)
+ case *map[int16]uint64:
+ var v2 map[int16]uint64
+ v2, changed = fastpathTV.DecMapInt16Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]uintptr:
+ fastpathTV.DecMapInt16UintptrV(v, false, d)
+ case *map[int16]uintptr:
+ var v2 map[int16]uintptr
+ v2, changed = fastpathTV.DecMapInt16UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]int:
+ fastpathTV.DecMapInt16IntV(v, false, d)
+ case *map[int16]int:
+ var v2 map[int16]int
+ v2, changed = fastpathTV.DecMapInt16IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]int8:
+ fastpathTV.DecMapInt16Int8V(v, false, d)
+ case *map[int16]int8:
+ var v2 map[int16]int8
+ v2, changed = fastpathTV.DecMapInt16Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]int16:
+ fastpathTV.DecMapInt16Int16V(v, false, d)
+ case *map[int16]int16:
+ var v2 map[int16]int16
+ v2, changed = fastpathTV.DecMapInt16Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]int32:
+ fastpathTV.DecMapInt16Int32V(v, false, d)
+ case *map[int16]int32:
+ var v2 map[int16]int32
+ v2, changed = fastpathTV.DecMapInt16Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]int64:
+ fastpathTV.DecMapInt16Int64V(v, false, d)
+ case *map[int16]int64:
+ var v2 map[int16]int64
+ v2, changed = fastpathTV.DecMapInt16Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]float32:
+ fastpathTV.DecMapInt16Float32V(v, false, d)
+ case *map[int16]float32:
+ var v2 map[int16]float32
+ v2, changed = fastpathTV.DecMapInt16Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]float64:
+ fastpathTV.DecMapInt16Float64V(v, false, d)
+ case *map[int16]float64:
+ var v2 map[int16]float64
+ v2, changed = fastpathTV.DecMapInt16Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int16]bool:
+ fastpathTV.DecMapInt16BoolV(v, false, d)
+ case *map[int16]bool:
+ var v2 map[int16]bool
+ v2, changed = fastpathTV.DecMapInt16BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]interface{}:
+ fastpathTV.DecMapInt32IntfV(v, false, d)
+ case *map[int32]interface{}:
+ var v2 map[int32]interface{}
+ v2, changed = fastpathTV.DecMapInt32IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]string:
+ fastpathTV.DecMapInt32StringV(v, false, d)
+ case *map[int32]string:
+ var v2 map[int32]string
+ v2, changed = fastpathTV.DecMapInt32StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]uint:
+ fastpathTV.DecMapInt32UintV(v, false, d)
+ case *map[int32]uint:
+ var v2 map[int32]uint
+ v2, changed = fastpathTV.DecMapInt32UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]uint8:
+ fastpathTV.DecMapInt32Uint8V(v, false, d)
+ case *map[int32]uint8:
+ var v2 map[int32]uint8
+ v2, changed = fastpathTV.DecMapInt32Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]uint16:
+ fastpathTV.DecMapInt32Uint16V(v, false, d)
+ case *map[int32]uint16:
+ var v2 map[int32]uint16
+ v2, changed = fastpathTV.DecMapInt32Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]uint32:
+ fastpathTV.DecMapInt32Uint32V(v, false, d)
+ case *map[int32]uint32:
+ var v2 map[int32]uint32
+ v2, changed = fastpathTV.DecMapInt32Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]uint64:
+ fastpathTV.DecMapInt32Uint64V(v, false, d)
+ case *map[int32]uint64:
+ var v2 map[int32]uint64
+ v2, changed = fastpathTV.DecMapInt32Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]uintptr:
+ fastpathTV.DecMapInt32UintptrV(v, false, d)
+ case *map[int32]uintptr:
+ var v2 map[int32]uintptr
+ v2, changed = fastpathTV.DecMapInt32UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]int:
+ fastpathTV.DecMapInt32IntV(v, false, d)
+ case *map[int32]int:
+ var v2 map[int32]int
+ v2, changed = fastpathTV.DecMapInt32IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]int8:
+ fastpathTV.DecMapInt32Int8V(v, false, d)
+ case *map[int32]int8:
+ var v2 map[int32]int8
+ v2, changed = fastpathTV.DecMapInt32Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]int16:
+ fastpathTV.DecMapInt32Int16V(v, false, d)
+ case *map[int32]int16:
+ var v2 map[int32]int16
+ v2, changed = fastpathTV.DecMapInt32Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]int32:
+ fastpathTV.DecMapInt32Int32V(v, false, d)
+ case *map[int32]int32:
+ var v2 map[int32]int32
+ v2, changed = fastpathTV.DecMapInt32Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]int64:
+ fastpathTV.DecMapInt32Int64V(v, false, d)
+ case *map[int32]int64:
+ var v2 map[int32]int64
+ v2, changed = fastpathTV.DecMapInt32Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]float32:
+ fastpathTV.DecMapInt32Float32V(v, false, d)
+ case *map[int32]float32:
+ var v2 map[int32]float32
+ v2, changed = fastpathTV.DecMapInt32Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]float64:
+ fastpathTV.DecMapInt32Float64V(v, false, d)
+ case *map[int32]float64:
+ var v2 map[int32]float64
+ v2, changed = fastpathTV.DecMapInt32Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int32]bool:
+ fastpathTV.DecMapInt32BoolV(v, false, d)
+ case *map[int32]bool:
+ var v2 map[int32]bool
+ v2, changed = fastpathTV.DecMapInt32BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]interface{}:
+ fastpathTV.DecMapInt64IntfV(v, false, d)
+ case *map[int64]interface{}:
+ var v2 map[int64]interface{}
+ v2, changed = fastpathTV.DecMapInt64IntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]string:
+ fastpathTV.DecMapInt64StringV(v, false, d)
+ case *map[int64]string:
+ var v2 map[int64]string
+ v2, changed = fastpathTV.DecMapInt64StringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]uint:
+ fastpathTV.DecMapInt64UintV(v, false, d)
+ case *map[int64]uint:
+ var v2 map[int64]uint
+ v2, changed = fastpathTV.DecMapInt64UintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]uint8:
+ fastpathTV.DecMapInt64Uint8V(v, false, d)
+ case *map[int64]uint8:
+ var v2 map[int64]uint8
+ v2, changed = fastpathTV.DecMapInt64Uint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]uint16:
+ fastpathTV.DecMapInt64Uint16V(v, false, d)
+ case *map[int64]uint16:
+ var v2 map[int64]uint16
+ v2, changed = fastpathTV.DecMapInt64Uint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]uint32:
+ fastpathTV.DecMapInt64Uint32V(v, false, d)
+ case *map[int64]uint32:
+ var v2 map[int64]uint32
+ v2, changed = fastpathTV.DecMapInt64Uint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]uint64:
+ fastpathTV.DecMapInt64Uint64V(v, false, d)
+ case *map[int64]uint64:
+ var v2 map[int64]uint64
+ v2, changed = fastpathTV.DecMapInt64Uint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]uintptr:
+ fastpathTV.DecMapInt64UintptrV(v, false, d)
+ case *map[int64]uintptr:
+ var v2 map[int64]uintptr
+ v2, changed = fastpathTV.DecMapInt64UintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]int:
+ fastpathTV.DecMapInt64IntV(v, false, d)
+ case *map[int64]int:
+ var v2 map[int64]int
+ v2, changed = fastpathTV.DecMapInt64IntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]int8:
+ fastpathTV.DecMapInt64Int8V(v, false, d)
+ case *map[int64]int8:
+ var v2 map[int64]int8
+ v2, changed = fastpathTV.DecMapInt64Int8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]int16:
+ fastpathTV.DecMapInt64Int16V(v, false, d)
+ case *map[int64]int16:
+ var v2 map[int64]int16
+ v2, changed = fastpathTV.DecMapInt64Int16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]int32:
+ fastpathTV.DecMapInt64Int32V(v, false, d)
+ case *map[int64]int32:
+ var v2 map[int64]int32
+ v2, changed = fastpathTV.DecMapInt64Int32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]int64:
+ fastpathTV.DecMapInt64Int64V(v, false, d)
+ case *map[int64]int64:
+ var v2 map[int64]int64
+ v2, changed = fastpathTV.DecMapInt64Int64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]float32:
+ fastpathTV.DecMapInt64Float32V(v, false, d)
+ case *map[int64]float32:
+ var v2 map[int64]float32
+ v2, changed = fastpathTV.DecMapInt64Float32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]float64:
+ fastpathTV.DecMapInt64Float64V(v, false, d)
+ case *map[int64]float64:
+ var v2 map[int64]float64
+ v2, changed = fastpathTV.DecMapInt64Float64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[int64]bool:
+ fastpathTV.DecMapInt64BoolV(v, false, d)
+ case *map[int64]bool:
+ var v2 map[int64]bool
+ v2, changed = fastpathTV.DecMapInt64BoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]interface{}:
+ fastpathTV.DecMapBoolIntfV(v, false, d)
+ case *map[bool]interface{}:
+ var v2 map[bool]interface{}
+ v2, changed = fastpathTV.DecMapBoolIntfV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]string:
+ fastpathTV.DecMapBoolStringV(v, false, d)
+ case *map[bool]string:
+ var v2 map[bool]string
+ v2, changed = fastpathTV.DecMapBoolStringV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]uint:
+ fastpathTV.DecMapBoolUintV(v, false, d)
+ case *map[bool]uint:
+ var v2 map[bool]uint
+ v2, changed = fastpathTV.DecMapBoolUintV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]uint8:
+ fastpathTV.DecMapBoolUint8V(v, false, d)
+ case *map[bool]uint8:
+ var v2 map[bool]uint8
+ v2, changed = fastpathTV.DecMapBoolUint8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]uint16:
+ fastpathTV.DecMapBoolUint16V(v, false, d)
+ case *map[bool]uint16:
+ var v2 map[bool]uint16
+ v2, changed = fastpathTV.DecMapBoolUint16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]uint32:
+ fastpathTV.DecMapBoolUint32V(v, false, d)
+ case *map[bool]uint32:
+ var v2 map[bool]uint32
+ v2, changed = fastpathTV.DecMapBoolUint32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]uint64:
+ fastpathTV.DecMapBoolUint64V(v, false, d)
+ case *map[bool]uint64:
+ var v2 map[bool]uint64
+ v2, changed = fastpathTV.DecMapBoolUint64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]uintptr:
+ fastpathTV.DecMapBoolUintptrV(v, false, d)
+ case *map[bool]uintptr:
+ var v2 map[bool]uintptr
+ v2, changed = fastpathTV.DecMapBoolUintptrV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]int:
+ fastpathTV.DecMapBoolIntV(v, false, d)
+ case *map[bool]int:
+ var v2 map[bool]int
+ v2, changed = fastpathTV.DecMapBoolIntV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]int8:
+ fastpathTV.DecMapBoolInt8V(v, false, d)
+ case *map[bool]int8:
+ var v2 map[bool]int8
+ v2, changed = fastpathTV.DecMapBoolInt8V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]int16:
+ fastpathTV.DecMapBoolInt16V(v, false, d)
+ case *map[bool]int16:
+ var v2 map[bool]int16
+ v2, changed = fastpathTV.DecMapBoolInt16V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]int32:
+ fastpathTV.DecMapBoolInt32V(v, false, d)
+ case *map[bool]int32:
+ var v2 map[bool]int32
+ v2, changed = fastpathTV.DecMapBoolInt32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]int64:
+ fastpathTV.DecMapBoolInt64V(v, false, d)
+ case *map[bool]int64:
+ var v2 map[bool]int64
+ v2, changed = fastpathTV.DecMapBoolInt64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]float32:
+ fastpathTV.DecMapBoolFloat32V(v, false, d)
+ case *map[bool]float32:
+ var v2 map[bool]float32
+ v2, changed = fastpathTV.DecMapBoolFloat32V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]float64:
+ fastpathTV.DecMapBoolFloat64V(v, false, d)
+ case *map[bool]float64:
+ var v2 map[bool]float64
+ v2, changed = fastpathTV.DecMapBoolFloat64V(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ case map[bool]bool:
+ fastpathTV.DecMapBoolBoolV(v, false, d)
+ case *map[bool]bool:
+ var v2 map[bool]bool
+ v2, changed = fastpathTV.DecMapBoolBoolV(*v, true, d)
+ if changed {
+ *v = v2
+ }
+ default:
+ _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
+ return false
+ }
+ return true
+}
+
+func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool {
+ switch v := iv.(type) {
+
+ case *[]interface{}:
+ *v = nil
+ case *[]string:
+ *v = nil
+ case *[]float32:
+ *v = nil
+ case *[]float64:
+ *v = nil
+ case *[]uint:
+ *v = nil
+ case *[]uint8:
+ *v = nil
+ case *[]uint16:
+ *v = nil
+ case *[]uint32:
+ *v = nil
+ case *[]uint64:
+ *v = nil
+ case *[]uintptr:
+ *v = nil
+ case *[]int:
+ *v = nil
+ case *[]int8:
+ *v = nil
+ case *[]int16:
+ *v = nil
+ case *[]int32:
+ *v = nil
+ case *[]int64:
+ *v = nil
+ case *[]bool:
+ *v = nil
+
+ case *map[interface{}]interface{}:
+ *v = nil
+ case *map[interface{}]string:
+ *v = nil
+ case *map[interface{}]uint:
+ *v = nil
+ case *map[interface{}]uint8:
+ *v = nil
+ case *map[interface{}]uint16:
+ *v = nil
+ case *map[interface{}]uint32:
+ *v = nil
+ case *map[interface{}]uint64:
+ *v = nil
+ case *map[interface{}]uintptr:
+ *v = nil
+ case *map[interface{}]int:
+ *v = nil
+ case *map[interface{}]int8:
+ *v = nil
+ case *map[interface{}]int16:
+ *v = nil
+ case *map[interface{}]int32:
+ *v = nil
+ case *map[interface{}]int64:
+ *v = nil
+ case *map[interface{}]float32:
+ *v = nil
+ case *map[interface{}]float64:
+ *v = nil
+ case *map[interface{}]bool:
+ *v = nil
+ case *map[string]interface{}:
+ *v = nil
+ case *map[string]string:
+ *v = nil
+ case *map[string]uint:
+ *v = nil
+ case *map[string]uint8:
+ *v = nil
+ case *map[string]uint16:
+ *v = nil
+ case *map[string]uint32:
+ *v = nil
+ case *map[string]uint64:
+ *v = nil
+ case *map[string]uintptr:
+ *v = nil
+ case *map[string]int:
+ *v = nil
+ case *map[string]int8:
+ *v = nil
+ case *map[string]int16:
+ *v = nil
+ case *map[string]int32:
+ *v = nil
+ case *map[string]int64:
+ *v = nil
+ case *map[string]float32:
+ *v = nil
+ case *map[string]float64:
+ *v = nil
+ case *map[string]bool:
+ *v = nil
+ case *map[float32]interface{}:
+ *v = nil
+ case *map[float32]string:
+ *v = nil
+ case *map[float32]uint:
+ *v = nil
+ case *map[float32]uint8:
+ *v = nil
+ case *map[float32]uint16:
+ *v = nil
+ case *map[float32]uint32:
+ *v = nil
+ case *map[float32]uint64:
+ *v = nil
+ case *map[float32]uintptr:
+ *v = nil
+ case *map[float32]int:
+ *v = nil
+ case *map[float32]int8:
+ *v = nil
+ case *map[float32]int16:
+ *v = nil
+ case *map[float32]int32:
+ *v = nil
+ case *map[float32]int64:
+ *v = nil
+ case *map[float32]float32:
+ *v = nil
+ case *map[float32]float64:
+ *v = nil
+ case *map[float32]bool:
+ *v = nil
+ case *map[float64]interface{}:
+ *v = nil
+ case *map[float64]string:
+ *v = nil
+ case *map[float64]uint:
+ *v = nil
+ case *map[float64]uint8:
+ *v = nil
+ case *map[float64]uint16:
+ *v = nil
+ case *map[float64]uint32:
+ *v = nil
+ case *map[float64]uint64:
+ *v = nil
+ case *map[float64]uintptr:
+ *v = nil
+ case *map[float64]int:
+ *v = nil
+ case *map[float64]int8:
+ *v = nil
+ case *map[float64]int16:
+ *v = nil
+ case *map[float64]int32:
+ *v = nil
+ case *map[float64]int64:
+ *v = nil
+ case *map[float64]float32:
+ *v = nil
+ case *map[float64]float64:
+ *v = nil
+ case *map[float64]bool:
+ *v = nil
+ case *map[uint]interface{}:
+ *v = nil
+ case *map[uint]string:
+ *v = nil
+ case *map[uint]uint:
+ *v = nil
+ case *map[uint]uint8:
+ *v = nil
+ case *map[uint]uint16:
+ *v = nil
+ case *map[uint]uint32:
+ *v = nil
+ case *map[uint]uint64:
+ *v = nil
+ case *map[uint]uintptr:
+ *v = nil
+ case *map[uint]int:
+ *v = nil
+ case *map[uint]int8:
+ *v = nil
+ case *map[uint]int16:
+ *v = nil
+ case *map[uint]int32:
+ *v = nil
+ case *map[uint]int64:
+ *v = nil
+ case *map[uint]float32:
+ *v = nil
+ case *map[uint]float64:
+ *v = nil
+ case *map[uint]bool:
+ *v = nil
+ case *map[uint8]interface{}:
+ *v = nil
+ case *map[uint8]string:
+ *v = nil
+ case *map[uint8]uint:
+ *v = nil
+ case *map[uint8]uint8:
+ *v = nil
+ case *map[uint8]uint16:
+ *v = nil
+ case *map[uint8]uint32:
+ *v = nil
+ case *map[uint8]uint64:
+ *v = nil
+ case *map[uint8]uintptr:
+ *v = nil
+ case *map[uint8]int:
+ *v = nil
+ case *map[uint8]int8:
+ *v = nil
+ case *map[uint8]int16:
+ *v = nil
+ case *map[uint8]int32:
+ *v = nil
+ case *map[uint8]int64:
+ *v = nil
+ case *map[uint8]float32:
+ *v = nil
+ case *map[uint8]float64:
+ *v = nil
+ case *map[uint8]bool:
+ *v = nil
+ case *map[uint16]interface{}:
+ *v = nil
+ case *map[uint16]string:
+ *v = nil
+ case *map[uint16]uint:
+ *v = nil
+ case *map[uint16]uint8:
+ *v = nil
+ case *map[uint16]uint16:
+ *v = nil
+ case *map[uint16]uint32:
+ *v = nil
+ case *map[uint16]uint64:
+ *v = nil
+ case *map[uint16]uintptr:
+ *v = nil
+ case *map[uint16]int:
+ *v = nil
+ case *map[uint16]int8:
+ *v = nil
+ case *map[uint16]int16:
+ *v = nil
+ case *map[uint16]int32:
+ *v = nil
+ case *map[uint16]int64:
+ *v = nil
+ case *map[uint16]float32:
+ *v = nil
+ case *map[uint16]float64:
+ *v = nil
+ case *map[uint16]bool:
+ *v = nil
+ case *map[uint32]interface{}:
+ *v = nil
+ case *map[uint32]string:
+ *v = nil
+ case *map[uint32]uint:
+ *v = nil
+ case *map[uint32]uint8:
+ *v = nil
+ case *map[uint32]uint16:
+ *v = nil
+ case *map[uint32]uint32:
+ *v = nil
+ case *map[uint32]uint64:
+ *v = nil
+ case *map[uint32]uintptr:
+ *v = nil
+ case *map[uint32]int:
+ *v = nil
+ case *map[uint32]int8:
+ *v = nil
+ case *map[uint32]int16:
+ *v = nil
+ case *map[uint32]int32:
+ *v = nil
+ case *map[uint32]int64:
+ *v = nil
+ case *map[uint32]float32:
+ *v = nil
+ case *map[uint32]float64:
+ *v = nil
+ case *map[uint32]bool:
+ *v = nil
+ case *map[uint64]interface{}:
+ *v = nil
+ case *map[uint64]string:
+ *v = nil
+ case *map[uint64]uint:
+ *v = nil
+ case *map[uint64]uint8:
+ *v = nil
+ case *map[uint64]uint16:
+ *v = nil
+ case *map[uint64]uint32:
+ *v = nil
+ case *map[uint64]uint64:
+ *v = nil
+ case *map[uint64]uintptr:
+ *v = nil
+ case *map[uint64]int:
+ *v = nil
+ case *map[uint64]int8:
+ *v = nil
+ case *map[uint64]int16:
+ *v = nil
+ case *map[uint64]int32:
+ *v = nil
+ case *map[uint64]int64:
+ *v = nil
+ case *map[uint64]float32:
+ *v = nil
+ case *map[uint64]float64:
+ *v = nil
+ case *map[uint64]bool:
+ *v = nil
+ case *map[uintptr]interface{}:
+ *v = nil
+ case *map[uintptr]string:
+ *v = nil
+ case *map[uintptr]uint:
+ *v = nil
+ case *map[uintptr]uint8:
+ *v = nil
+ case *map[uintptr]uint16:
+ *v = nil
+ case *map[uintptr]uint32:
+ *v = nil
+ case *map[uintptr]uint64:
+ *v = nil
+ case *map[uintptr]uintptr:
+ *v = nil
+ case *map[uintptr]int:
+ *v = nil
+ case *map[uintptr]int8:
+ *v = nil
+ case *map[uintptr]int16:
+ *v = nil
+ case *map[uintptr]int32:
+ *v = nil
+ case *map[uintptr]int64:
+ *v = nil
+ case *map[uintptr]float32:
+ *v = nil
+ case *map[uintptr]float64:
+ *v = nil
+ case *map[uintptr]bool:
+ *v = nil
+ case *map[int]interface{}:
+ *v = nil
+ case *map[int]string:
+ *v = nil
+ case *map[int]uint:
+ *v = nil
+ case *map[int]uint8:
+ *v = nil
+ case *map[int]uint16:
+ *v = nil
+ case *map[int]uint32:
+ *v = nil
+ case *map[int]uint64:
+ *v = nil
+ case *map[int]uintptr:
+ *v = nil
+ case *map[int]int:
+ *v = nil
+ case *map[int]int8:
+ *v = nil
+ case *map[int]int16:
+ *v = nil
+ case *map[int]int32:
+ *v = nil
+ case *map[int]int64:
+ *v = nil
+ case *map[int]float32:
+ *v = nil
+ case *map[int]float64:
+ *v = nil
+ case *map[int]bool:
+ *v = nil
+ case *map[int8]interface{}:
+ *v = nil
+ case *map[int8]string:
+ *v = nil
+ case *map[int8]uint:
+ *v = nil
+ case *map[int8]uint8:
+ *v = nil
+ case *map[int8]uint16:
+ *v = nil
+ case *map[int8]uint32:
+ *v = nil
+ case *map[int8]uint64:
+ *v = nil
+ case *map[int8]uintptr:
+ *v = nil
+ case *map[int8]int:
+ *v = nil
+ case *map[int8]int8:
+ *v = nil
+ case *map[int8]int16:
+ *v = nil
+ case *map[int8]int32:
+ *v = nil
+ case *map[int8]int64:
+ *v = nil
+ case *map[int8]float32:
+ *v = nil
+ case *map[int8]float64:
+ *v = nil
+ case *map[int8]bool:
+ *v = nil
+ case *map[int16]interface{}:
+ *v = nil
+ case *map[int16]string:
+ *v = nil
+ case *map[int16]uint:
+ *v = nil
+ case *map[int16]uint8:
+ *v = nil
+ case *map[int16]uint16:
+ *v = nil
+ case *map[int16]uint32:
+ *v = nil
+ case *map[int16]uint64:
+ *v = nil
+ case *map[int16]uintptr:
+ *v = nil
+ case *map[int16]int:
+ *v = nil
+ case *map[int16]int8:
+ *v = nil
+ case *map[int16]int16:
+ *v = nil
+ case *map[int16]int32:
+ *v = nil
+ case *map[int16]int64:
+ *v = nil
+ case *map[int16]float32:
+ *v = nil
+ case *map[int16]float64:
+ *v = nil
+ case *map[int16]bool:
+ *v = nil
+ case *map[int32]interface{}:
+ *v = nil
+ case *map[int32]string:
+ *v = nil
+ case *map[int32]uint:
+ *v = nil
+ case *map[int32]uint8:
+ *v = nil
+ case *map[int32]uint16:
+ *v = nil
+ case *map[int32]uint32:
+ *v = nil
+ case *map[int32]uint64:
+ *v = nil
+ case *map[int32]uintptr:
+ *v = nil
+ case *map[int32]int:
+ *v = nil
+ case *map[int32]int8:
+ *v = nil
+ case *map[int32]int16:
+ *v = nil
+ case *map[int32]int32:
+ *v = nil
+ case *map[int32]int64:
+ *v = nil
+ case *map[int32]float32:
+ *v = nil
+ case *map[int32]float64:
+ *v = nil
+ case *map[int32]bool:
+ *v = nil
+ case *map[int64]interface{}:
+ *v = nil
+ case *map[int64]string:
+ *v = nil
+ case *map[int64]uint:
+ *v = nil
+ case *map[int64]uint8:
+ *v = nil
+ case *map[int64]uint16:
+ *v = nil
+ case *map[int64]uint32:
+ *v = nil
+ case *map[int64]uint64:
+ *v = nil
+ case *map[int64]uintptr:
+ *v = nil
+ case *map[int64]int:
+ *v = nil
+ case *map[int64]int8:
+ *v = nil
+ case *map[int64]int16:
+ *v = nil
+ case *map[int64]int32:
+ *v = nil
+ case *map[int64]int64:
+ *v = nil
+ case *map[int64]float32:
+ *v = nil
+ case *map[int64]float64:
+ *v = nil
+ case *map[int64]bool:
+ *v = nil
+ case *map[bool]interface{}:
+ *v = nil
+ case *map[bool]string:
+ *v = nil
+ case *map[bool]uint:
+ *v = nil
+ case *map[bool]uint8:
+ *v = nil
+ case *map[bool]uint16:
+ *v = nil
+ case *map[bool]uint32:
+ *v = nil
+ case *map[bool]uint64:
+ *v = nil
+ case *map[bool]uintptr:
+ *v = nil
+ case *map[bool]int:
+ *v = nil
+ case *map[bool]int8:
+ *v = nil
+ case *map[bool]int16:
+ *v = nil
+ case *map[bool]int32:
+ *v = nil
+ case *map[bool]int64:
+ *v = nil
+ case *map[bool]float32:
+ *v = nil
+ case *map[bool]float64:
+ *v = nil
+ case *map[bool]bool:
+ *v = nil
+ default:
+ _ = v // workaround https://github.com/golang/go/issues/12927 seen in go1.4
+ return false
+ }
+ return true
+}
+
+// -- -- fast path functions
+
+func (d *Decoder) fastpathDecSliceIntfR(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]interface{})
+ v, changed := fastpathTV.DecSliceIntfV(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]interface{})
+ v2, changed := fastpathTV.DecSliceIntfV(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceIntfX(vp *[]interface{}, d *Decoder) {
+ v, changed := f.DecSliceIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceIntfV(v []interface{}, canChange bool, d *Decoder) (_ []interface{}, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []interface{}{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 16)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]interface{}, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 16)
+ } else {
+ xlen = 8
+ }
+ v = make([]interface{}, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, nil)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = nil
+ } else {
+ d.decode(&v[j])
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]interface{}, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceStringR(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]string)
+ v, changed := fastpathTV.DecSliceStringV(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]string)
+ v2, changed := fastpathTV.DecSliceStringV(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceStringX(vp *[]string, d *Decoder) {
+ v, changed := f.DecSliceStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceStringV(v []string, canChange bool, d *Decoder) (_ []string, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []string{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 16)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]string, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 16)
+ } else {
+ xlen = 8
+ }
+ v = make([]string, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, "")
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = ""
+ } else {
+ v[j] = dd.DecodeString()
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]string, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]float32)
+ v, changed := fastpathTV.DecSliceFloat32V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]float32)
+ v2, changed := fastpathTV.DecSliceFloat32V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceFloat32X(vp *[]float32, d *Decoder) {
+ v, changed := f.DecSliceFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceFloat32V(v []float32, canChange bool, d *Decoder) (_ []float32, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []float32{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 4)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]float32, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 4)
+ } else {
+ xlen = 8
+ }
+ v = make([]float32, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]float32, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]float64)
+ v, changed := fastpathTV.DecSliceFloat64V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]float64)
+ v2, changed := fastpathTV.DecSliceFloat64V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceFloat64X(vp *[]float64, d *Decoder) {
+ v, changed := f.DecSliceFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceFloat64V(v []float64, canChange bool, d *Decoder) (_ []float64, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []float64{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]float64, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ } else {
+ xlen = 8
+ }
+ v = make([]float64, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = dd.DecodeFloat64()
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]float64, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceUintR(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]uint)
+ v, changed := fastpathTV.DecSliceUintV(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]uint)
+ v2, changed := fastpathTV.DecSliceUintV(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceUintX(vp *[]uint, d *Decoder) {
+ v, changed := f.DecSliceUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceUintV(v []uint, canChange bool, d *Decoder) (_ []uint, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []uint{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]uint, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ } else {
+ xlen = 8
+ }
+ v = make([]uint, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]uint, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceUint8R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]uint8)
+ v, changed := fastpathTV.DecSliceUint8V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]uint8)
+ v2, changed := fastpathTV.DecSliceUint8V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceUint8X(vp *[]uint8, d *Decoder) {
+ v, changed := f.DecSliceUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceUint8V(v []uint8, canChange bool, d *Decoder) (_ []uint8, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []uint8{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 1)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]uint8, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 1)
+ } else {
+ xlen = 8
+ }
+ v = make([]uint8, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]uint8, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceUint16R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]uint16)
+ v, changed := fastpathTV.DecSliceUint16V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]uint16)
+ v2, changed := fastpathTV.DecSliceUint16V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceUint16X(vp *[]uint16, d *Decoder) {
+ v, changed := f.DecSliceUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceUint16V(v []uint16, canChange bool, d *Decoder) (_ []uint16, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []uint16{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 2)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]uint16, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 2)
+ } else {
+ xlen = 8
+ }
+ v = make([]uint16, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]uint16, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceUint32R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]uint32)
+ v, changed := fastpathTV.DecSliceUint32V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]uint32)
+ v2, changed := fastpathTV.DecSliceUint32V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceUint32X(vp *[]uint32, d *Decoder) {
+ v, changed := f.DecSliceUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceUint32V(v []uint32, canChange bool, d *Decoder) (_ []uint32, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []uint32{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 4)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]uint32, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 4)
+ } else {
+ xlen = 8
+ }
+ v = make([]uint32, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]uint32, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceUint64R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]uint64)
+ v, changed := fastpathTV.DecSliceUint64V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]uint64)
+ v2, changed := fastpathTV.DecSliceUint64V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceUint64X(vp *[]uint64, d *Decoder) {
+ v, changed := f.DecSliceUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceUint64V(v []uint64, canChange bool, d *Decoder) (_ []uint64, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []uint64{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]uint64, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ } else {
+ xlen = 8
+ }
+ v = make([]uint64, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = dd.DecodeUint64()
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]uint64, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]uintptr)
+ v, changed := fastpathTV.DecSliceUintptrV(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]uintptr)
+ v2, changed := fastpathTV.DecSliceUintptrV(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceUintptrX(vp *[]uintptr, d *Decoder) {
+ v, changed := f.DecSliceUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceUintptrV(v []uintptr, canChange bool, d *Decoder) (_ []uintptr, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []uintptr{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]uintptr, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ } else {
+ xlen = 8
+ }
+ v = make([]uintptr, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]uintptr, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceIntR(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]int)
+ v, changed := fastpathTV.DecSliceIntV(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]int)
+ v2, changed := fastpathTV.DecSliceIntV(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceIntX(vp *[]int, d *Decoder) {
+ v, changed := f.DecSliceIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceIntV(v []int, canChange bool, d *Decoder) (_ []int, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []int{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]int, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ } else {
+ xlen = 8
+ }
+ v = make([]int, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]int, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceInt8R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]int8)
+ v, changed := fastpathTV.DecSliceInt8V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]int8)
+ v2, changed := fastpathTV.DecSliceInt8V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceInt8X(vp *[]int8, d *Decoder) {
+ v, changed := f.DecSliceInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceInt8V(v []int8, canChange bool, d *Decoder) (_ []int8, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []int8{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 1)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]int8, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 1)
+ } else {
+ xlen = 8
+ }
+ v = make([]int8, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]int8, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceInt16R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]int16)
+ v, changed := fastpathTV.DecSliceInt16V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]int16)
+ v2, changed := fastpathTV.DecSliceInt16V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceInt16X(vp *[]int16, d *Decoder) {
+ v, changed := f.DecSliceInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceInt16V(v []int16, canChange bool, d *Decoder) (_ []int16, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []int16{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 2)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]int16, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 2)
+ } else {
+ xlen = 8
+ }
+ v = make([]int16, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]int16, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceInt32R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]int32)
+ v, changed := fastpathTV.DecSliceInt32V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]int32)
+ v2, changed := fastpathTV.DecSliceInt32V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceInt32X(vp *[]int32, d *Decoder) {
+ v, changed := f.DecSliceInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceInt32V(v []int32, canChange bool, d *Decoder) (_ []int32, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []int32{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 4)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]int32, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 4)
+ } else {
+ xlen = 8
+ }
+ v = make([]int32, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]int32, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceInt64R(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]int64)
+ v, changed := fastpathTV.DecSliceInt64V(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]int64)
+ v2, changed := fastpathTV.DecSliceInt64V(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceInt64X(vp *[]int64, d *Decoder) {
+ v, changed := f.DecSliceInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceInt64V(v []int64, canChange bool, d *Decoder) (_ []int64, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []int64{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]int64, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 8)
+ } else {
+ xlen = 8
+ }
+ v = make([]int64, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, 0)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = 0
+ } else {
+ v[j] = dd.DecodeInt64()
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]int64, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecSliceBoolR(f *codecFnInfo, rv reflect.Value) {
+ if array := f.seq == seqTypeArray; !array && rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*[]bool)
+ v, changed := fastpathTV.DecSliceBoolV(*vp, !array, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ v := rv2i(rv).([]bool)
+ v2, changed := fastpathTV.DecSliceBoolV(v, !array, d)
+ if changed && len(v) > 0 && len(v2) > 0 && !(len(v2) == len(v) && &v2[0] == &v[0]) {
+ copy(v, v2)
+ }
+ }
+}
+func (f fastpathT) DecSliceBoolX(vp *[]bool, d *Decoder) {
+ v, changed := f.DecSliceBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecSliceBoolV(v []bool, canChange bool, d *Decoder) (_ []bool, changed bool) {
+ dd := d.d
+ slh, containerLenS := d.decSliceHelperStart()
+ if containerLenS == 0 {
+ if canChange {
+ if v == nil {
+ v = []bool{}
+ } else if len(v) != 0 {
+ v = v[:0]
+ }
+ changed = true
+ }
+ slh.End()
+ return v, changed
+ }
+ hasLen := containerLenS > 0
+ var xlen int
+ if hasLen && canChange {
+ if containerLenS > cap(v) {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 1)
+ if xlen <= cap(v) {
+ v = v[:xlen]
+ } else {
+ v = make([]bool, xlen)
+ }
+ changed = true
+ } else if containerLenS != len(v) {
+ v = v[:containerLenS]
+ changed = true
+ }
+ }
+ j := 0
+ for ; (hasLen && j < containerLenS) || !(hasLen || dd.CheckBreak()); j++ {
+ if j == 0 && len(v) == 0 && canChange {
+ if hasLen {
+ xlen = decInferLen(containerLenS, d.h.MaxInitLen, 1)
+ } else {
+ xlen = 8
+ }
+ v = make([]bool, xlen)
+ changed = true
+ }
+ // if indefinite, etc, then expand the slice if necessary
+ var decodeIntoBlank bool
+ if j >= len(v) {
+ if canChange {
+ v = append(v, false)
+ changed = true
+ } else {
+ d.arrayCannotExpand(len(v), j+1)
+ decodeIntoBlank = true
+ }
+ }
+ slh.ElemContainerState(j)
+ if decodeIntoBlank {
+ d.swallow()
+ } else if dd.TryDecodeAsNil() {
+ v[j] = false
+ } else {
+ v[j] = dd.DecodeBool()
+ }
+ }
+ if canChange {
+ if j < len(v) {
+ v = v[:j]
+ changed = true
+ } else if j == 0 && v == nil {
+ v = make([]bool, 0)
+ changed = true
+ }
+ }
+ slh.End()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfIntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]interface{})
+ v, changed := fastpathTV.DecMapIntfIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfIntfV(rv2i(rv).(map[interface{}]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfIntfX(vp *map[interface{}]interface{}, d *Decoder) {
+ v, changed := f.DecMapIntfIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfIntfV(v map[interface{}]interface{}, canChange bool,
+ d *Decoder) (_ map[interface{}]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 32)
+ v = make(map[interface{}]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk interface{}
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfStringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]string)
+ v, changed := fastpathTV.DecMapIntfStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfStringV(rv2i(rv).(map[interface{}]string), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfStringX(vp *map[interface{}]string, d *Decoder) {
+ v, changed := f.DecMapIntfStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfStringV(v map[interface{}]string, canChange bool,
+ d *Decoder) (_ map[interface{}]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 32)
+ v = make(map[interface{}]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfUintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]uint)
+ v, changed := fastpathTV.DecMapIntfUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfUintV(rv2i(rv).(map[interface{}]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfUintX(vp *map[interface{}]uint, d *Decoder) {
+ v, changed := f.DecMapIntfUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfUintV(v map[interface{}]uint, canChange bool,
+ d *Decoder) (_ map[interface{}]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[interface{}]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfUint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]uint8)
+ v, changed := fastpathTV.DecMapIntfUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfUint8V(rv2i(rv).(map[interface{}]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfUint8X(vp *map[interface{}]uint8, d *Decoder) {
+ v, changed := f.DecMapIntfUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfUint8V(v map[interface{}]uint8, canChange bool,
+ d *Decoder) (_ map[interface{}]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[interface{}]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfUint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]uint16)
+ v, changed := fastpathTV.DecMapIntfUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfUint16V(rv2i(rv).(map[interface{}]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfUint16X(vp *map[interface{}]uint16, d *Decoder) {
+ v, changed := f.DecMapIntfUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfUint16V(v map[interface{}]uint16, canChange bool,
+ d *Decoder) (_ map[interface{}]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[interface{}]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfUint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]uint32)
+ v, changed := fastpathTV.DecMapIntfUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfUint32V(rv2i(rv).(map[interface{}]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfUint32X(vp *map[interface{}]uint32, d *Decoder) {
+ v, changed := f.DecMapIntfUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfUint32V(v map[interface{}]uint32, canChange bool,
+ d *Decoder) (_ map[interface{}]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[interface{}]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfUint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]uint64)
+ v, changed := fastpathTV.DecMapIntfUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfUint64V(rv2i(rv).(map[interface{}]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfUint64X(vp *map[interface{}]uint64, d *Decoder) {
+ v, changed := f.DecMapIntfUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfUint64V(v map[interface{}]uint64, canChange bool,
+ d *Decoder) (_ map[interface{}]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[interface{}]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]uintptr)
+ v, changed := fastpathTV.DecMapIntfUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfUintptrV(rv2i(rv).(map[interface{}]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfUintptrX(vp *map[interface{}]uintptr, d *Decoder) {
+ v, changed := f.DecMapIntfUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfUintptrV(v map[interface{}]uintptr, canChange bool,
+ d *Decoder) (_ map[interface{}]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[interface{}]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfIntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]int)
+ v, changed := fastpathTV.DecMapIntfIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfIntV(rv2i(rv).(map[interface{}]int), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfIntX(vp *map[interface{}]int, d *Decoder) {
+ v, changed := f.DecMapIntfIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfIntV(v map[interface{}]int, canChange bool,
+ d *Decoder) (_ map[interface{}]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[interface{}]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfInt8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]int8)
+ v, changed := fastpathTV.DecMapIntfInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfInt8V(rv2i(rv).(map[interface{}]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfInt8X(vp *map[interface{}]int8, d *Decoder) {
+ v, changed := f.DecMapIntfInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfInt8V(v map[interface{}]int8, canChange bool,
+ d *Decoder) (_ map[interface{}]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[interface{}]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfInt16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]int16)
+ v, changed := fastpathTV.DecMapIntfInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfInt16V(rv2i(rv).(map[interface{}]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfInt16X(vp *map[interface{}]int16, d *Decoder) {
+ v, changed := f.DecMapIntfInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfInt16V(v map[interface{}]int16, canChange bool,
+ d *Decoder) (_ map[interface{}]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[interface{}]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfInt32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]int32)
+ v, changed := fastpathTV.DecMapIntfInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfInt32V(rv2i(rv).(map[interface{}]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfInt32X(vp *map[interface{}]int32, d *Decoder) {
+ v, changed := f.DecMapIntfInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfInt32V(v map[interface{}]int32, canChange bool,
+ d *Decoder) (_ map[interface{}]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[interface{}]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfInt64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]int64)
+ v, changed := fastpathTV.DecMapIntfInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfInt64V(rv2i(rv).(map[interface{}]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfInt64X(vp *map[interface{}]int64, d *Decoder) {
+ v, changed := f.DecMapIntfInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfInt64V(v map[interface{}]int64, canChange bool,
+ d *Decoder) (_ map[interface{}]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[interface{}]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]float32)
+ v, changed := fastpathTV.DecMapIntfFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfFloat32V(rv2i(rv).(map[interface{}]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfFloat32X(vp *map[interface{}]float32, d *Decoder) {
+ v, changed := f.DecMapIntfFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfFloat32V(v map[interface{}]float32, canChange bool,
+ d *Decoder) (_ map[interface{}]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[interface{}]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]float64)
+ v, changed := fastpathTV.DecMapIntfFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfFloat64V(rv2i(rv).(map[interface{}]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfFloat64X(vp *map[interface{}]float64, d *Decoder) {
+ v, changed := f.DecMapIntfFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfFloat64V(v map[interface{}]float64, canChange bool,
+ d *Decoder) (_ map[interface{}]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[interface{}]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntfBoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[interface{}]bool)
+ v, changed := fastpathTV.DecMapIntfBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntfBoolV(rv2i(rv).(map[interface{}]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapIntfBoolX(vp *map[interface{}]bool, d *Decoder) {
+ v, changed := f.DecMapIntfBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntfBoolV(v map[interface{}]bool, canChange bool,
+ d *Decoder) (_ map[interface{}]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[interface{}]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk interface{}
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = nil
+ d.decode(&mk)
+ if bv, bok := mk.([]byte); bok {
+ mk = d.string(bv)
+ }
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringIntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]interface{})
+ v, changed := fastpathTV.DecMapStringIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringIntfV(rv2i(rv).(map[string]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapStringIntfX(vp *map[string]interface{}, d *Decoder) {
+ v, changed := f.DecMapStringIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringIntfV(v map[string]interface{}, canChange bool,
+ d *Decoder) (_ map[string]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 32)
+ v = make(map[string]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk string
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringStringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]string)
+ v, changed := fastpathTV.DecMapStringStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringStringV(rv2i(rv).(map[string]string), false, d)
+ }
+}
+func (f fastpathT) DecMapStringStringX(vp *map[string]string, d *Decoder) {
+ v, changed := f.DecMapStringStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringStringV(v map[string]string, canChange bool,
+ d *Decoder) (_ map[string]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 32)
+ v = make(map[string]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringUintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]uint)
+ v, changed := fastpathTV.DecMapStringUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringUintV(rv2i(rv).(map[string]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapStringUintX(vp *map[string]uint, d *Decoder) {
+ v, changed := f.DecMapStringUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringUintV(v map[string]uint, canChange bool,
+ d *Decoder) (_ map[string]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[string]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringUint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]uint8)
+ v, changed := fastpathTV.DecMapStringUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringUint8V(rv2i(rv).(map[string]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapStringUint8X(vp *map[string]uint8, d *Decoder) {
+ v, changed := f.DecMapStringUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringUint8V(v map[string]uint8, canChange bool,
+ d *Decoder) (_ map[string]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[string]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringUint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]uint16)
+ v, changed := fastpathTV.DecMapStringUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringUint16V(rv2i(rv).(map[string]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapStringUint16X(vp *map[string]uint16, d *Decoder) {
+ v, changed := f.DecMapStringUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringUint16V(v map[string]uint16, canChange bool,
+ d *Decoder) (_ map[string]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[string]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringUint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]uint32)
+ v, changed := fastpathTV.DecMapStringUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringUint32V(rv2i(rv).(map[string]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapStringUint32X(vp *map[string]uint32, d *Decoder) {
+ v, changed := f.DecMapStringUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringUint32V(v map[string]uint32, canChange bool,
+ d *Decoder) (_ map[string]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[string]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringUint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]uint64)
+ v, changed := fastpathTV.DecMapStringUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringUint64V(rv2i(rv).(map[string]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapStringUint64X(vp *map[string]uint64, d *Decoder) {
+ v, changed := f.DecMapStringUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringUint64V(v map[string]uint64, canChange bool,
+ d *Decoder) (_ map[string]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[string]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]uintptr)
+ v, changed := fastpathTV.DecMapStringUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringUintptrV(rv2i(rv).(map[string]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapStringUintptrX(vp *map[string]uintptr, d *Decoder) {
+ v, changed := f.DecMapStringUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringUintptrV(v map[string]uintptr, canChange bool,
+ d *Decoder) (_ map[string]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[string]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringIntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]int)
+ v, changed := fastpathTV.DecMapStringIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringIntV(rv2i(rv).(map[string]int), false, d)
+ }
+}
+func (f fastpathT) DecMapStringIntX(vp *map[string]int, d *Decoder) {
+ v, changed := f.DecMapStringIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringIntV(v map[string]int, canChange bool,
+ d *Decoder) (_ map[string]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[string]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringInt8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]int8)
+ v, changed := fastpathTV.DecMapStringInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringInt8V(rv2i(rv).(map[string]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapStringInt8X(vp *map[string]int8, d *Decoder) {
+ v, changed := f.DecMapStringInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringInt8V(v map[string]int8, canChange bool,
+ d *Decoder) (_ map[string]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[string]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringInt16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]int16)
+ v, changed := fastpathTV.DecMapStringInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringInt16V(rv2i(rv).(map[string]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapStringInt16X(vp *map[string]int16, d *Decoder) {
+ v, changed := f.DecMapStringInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringInt16V(v map[string]int16, canChange bool,
+ d *Decoder) (_ map[string]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[string]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringInt32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]int32)
+ v, changed := fastpathTV.DecMapStringInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringInt32V(rv2i(rv).(map[string]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapStringInt32X(vp *map[string]int32, d *Decoder) {
+ v, changed := f.DecMapStringInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringInt32V(v map[string]int32, canChange bool,
+ d *Decoder) (_ map[string]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[string]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringInt64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]int64)
+ v, changed := fastpathTV.DecMapStringInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringInt64V(rv2i(rv).(map[string]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapStringInt64X(vp *map[string]int64, d *Decoder) {
+ v, changed := f.DecMapStringInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringInt64V(v map[string]int64, canChange bool,
+ d *Decoder) (_ map[string]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[string]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]float32)
+ v, changed := fastpathTV.DecMapStringFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringFloat32V(rv2i(rv).(map[string]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapStringFloat32X(vp *map[string]float32, d *Decoder) {
+ v, changed := f.DecMapStringFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringFloat32V(v map[string]float32, canChange bool,
+ d *Decoder) (_ map[string]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[string]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]float64)
+ v, changed := fastpathTV.DecMapStringFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringFloat64V(rv2i(rv).(map[string]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapStringFloat64X(vp *map[string]float64, d *Decoder) {
+ v, changed := f.DecMapStringFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringFloat64V(v map[string]float64, canChange bool,
+ d *Decoder) (_ map[string]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[string]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapStringBoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[string]bool)
+ v, changed := fastpathTV.DecMapStringBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapStringBoolV(rv2i(rv).(map[string]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapStringBoolX(vp *map[string]bool, d *Decoder) {
+ v, changed := f.DecMapStringBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapStringBoolV(v map[string]bool, canChange bool,
+ d *Decoder) (_ map[string]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[string]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk string
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeString()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]interface{})
+ v, changed := fastpathTV.DecMapFloat32IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32IntfV(rv2i(rv).(map[float32]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32IntfX(vp *map[float32]interface{}, d *Decoder) {
+ v, changed := f.DecMapFloat32IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32IntfV(v map[float32]interface{}, canChange bool,
+ d *Decoder) (_ map[float32]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[float32]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk float32
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]string)
+ v, changed := fastpathTV.DecMapFloat32StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32StringV(rv2i(rv).(map[float32]string), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32StringX(vp *map[float32]string, d *Decoder) {
+ v, changed := f.DecMapFloat32StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32StringV(v map[float32]string, canChange bool,
+ d *Decoder) (_ map[float32]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[float32]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]uint)
+ v, changed := fastpathTV.DecMapFloat32UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32UintV(rv2i(rv).(map[float32]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32UintX(vp *map[float32]uint, d *Decoder) {
+ v, changed := f.DecMapFloat32UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32UintV(v map[float32]uint, canChange bool,
+ d *Decoder) (_ map[float32]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float32]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]uint8)
+ v, changed := fastpathTV.DecMapFloat32Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Uint8V(rv2i(rv).(map[float32]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Uint8X(vp *map[float32]uint8, d *Decoder) {
+ v, changed := f.DecMapFloat32Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Uint8V(v map[float32]uint8, canChange bool,
+ d *Decoder) (_ map[float32]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[float32]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]uint16)
+ v, changed := fastpathTV.DecMapFloat32Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Uint16V(rv2i(rv).(map[float32]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Uint16X(vp *map[float32]uint16, d *Decoder) {
+ v, changed := f.DecMapFloat32Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Uint16V(v map[float32]uint16, canChange bool,
+ d *Decoder) (_ map[float32]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[float32]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]uint32)
+ v, changed := fastpathTV.DecMapFloat32Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Uint32V(rv2i(rv).(map[float32]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Uint32X(vp *map[float32]uint32, d *Decoder) {
+ v, changed := f.DecMapFloat32Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Uint32V(v map[float32]uint32, canChange bool,
+ d *Decoder) (_ map[float32]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[float32]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]uint64)
+ v, changed := fastpathTV.DecMapFloat32Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Uint64V(rv2i(rv).(map[float32]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Uint64X(vp *map[float32]uint64, d *Decoder) {
+ v, changed := f.DecMapFloat32Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Uint64V(v map[float32]uint64, canChange bool,
+ d *Decoder) (_ map[float32]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float32]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]uintptr)
+ v, changed := fastpathTV.DecMapFloat32UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32UintptrV(rv2i(rv).(map[float32]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32UintptrX(vp *map[float32]uintptr, d *Decoder) {
+ v, changed := f.DecMapFloat32UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32UintptrV(v map[float32]uintptr, canChange bool,
+ d *Decoder) (_ map[float32]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float32]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]int)
+ v, changed := fastpathTV.DecMapFloat32IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32IntV(rv2i(rv).(map[float32]int), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32IntX(vp *map[float32]int, d *Decoder) {
+ v, changed := f.DecMapFloat32IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32IntV(v map[float32]int, canChange bool,
+ d *Decoder) (_ map[float32]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float32]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]int8)
+ v, changed := fastpathTV.DecMapFloat32Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Int8V(rv2i(rv).(map[float32]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Int8X(vp *map[float32]int8, d *Decoder) {
+ v, changed := f.DecMapFloat32Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Int8V(v map[float32]int8, canChange bool,
+ d *Decoder) (_ map[float32]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[float32]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]int16)
+ v, changed := fastpathTV.DecMapFloat32Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Int16V(rv2i(rv).(map[float32]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Int16X(vp *map[float32]int16, d *Decoder) {
+ v, changed := f.DecMapFloat32Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Int16V(v map[float32]int16, canChange bool,
+ d *Decoder) (_ map[float32]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[float32]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]int32)
+ v, changed := fastpathTV.DecMapFloat32Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Int32V(rv2i(rv).(map[float32]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Int32X(vp *map[float32]int32, d *Decoder) {
+ v, changed := f.DecMapFloat32Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Int32V(v map[float32]int32, canChange bool,
+ d *Decoder) (_ map[float32]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[float32]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]int64)
+ v, changed := fastpathTV.DecMapFloat32Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Int64V(rv2i(rv).(map[float32]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Int64X(vp *map[float32]int64, d *Decoder) {
+ v, changed := f.DecMapFloat32Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Int64V(v map[float32]int64, canChange bool,
+ d *Decoder) (_ map[float32]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float32]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]float32)
+ v, changed := fastpathTV.DecMapFloat32Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Float32V(rv2i(rv).(map[float32]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Float32X(vp *map[float32]float32, d *Decoder) {
+ v, changed := f.DecMapFloat32Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Float32V(v map[float32]float32, canChange bool,
+ d *Decoder) (_ map[float32]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[float32]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]float64)
+ v, changed := fastpathTV.DecMapFloat32Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32Float64V(rv2i(rv).(map[float32]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32Float64X(vp *map[float32]float64, d *Decoder) {
+ v, changed := f.DecMapFloat32Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32Float64V(v map[float32]float64, canChange bool,
+ d *Decoder) (_ map[float32]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float32]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat32BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float32]bool)
+ v, changed := fastpathTV.DecMapFloat32BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat32BoolV(rv2i(rv).(map[float32]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat32BoolX(vp *map[float32]bool, d *Decoder) {
+ v, changed := f.DecMapFloat32BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat32BoolV(v map[float32]bool, canChange bool,
+ d *Decoder) (_ map[float32]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[float32]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float32
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]interface{})
+ v, changed := fastpathTV.DecMapFloat64IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64IntfV(rv2i(rv).(map[float64]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64IntfX(vp *map[float64]interface{}, d *Decoder) {
+ v, changed := f.DecMapFloat64IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64IntfV(v map[float64]interface{}, canChange bool,
+ d *Decoder) (_ map[float64]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[float64]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk float64
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]string)
+ v, changed := fastpathTV.DecMapFloat64StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64StringV(rv2i(rv).(map[float64]string), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64StringX(vp *map[float64]string, d *Decoder) {
+ v, changed := f.DecMapFloat64StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64StringV(v map[float64]string, canChange bool,
+ d *Decoder) (_ map[float64]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[float64]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]uint)
+ v, changed := fastpathTV.DecMapFloat64UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64UintV(rv2i(rv).(map[float64]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64UintX(vp *map[float64]uint, d *Decoder) {
+ v, changed := f.DecMapFloat64UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64UintV(v map[float64]uint, canChange bool,
+ d *Decoder) (_ map[float64]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[float64]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]uint8)
+ v, changed := fastpathTV.DecMapFloat64Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Uint8V(rv2i(rv).(map[float64]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Uint8X(vp *map[float64]uint8, d *Decoder) {
+ v, changed := f.DecMapFloat64Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Uint8V(v map[float64]uint8, canChange bool,
+ d *Decoder) (_ map[float64]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[float64]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]uint16)
+ v, changed := fastpathTV.DecMapFloat64Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Uint16V(rv2i(rv).(map[float64]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Uint16X(vp *map[float64]uint16, d *Decoder) {
+ v, changed := f.DecMapFloat64Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Uint16V(v map[float64]uint16, canChange bool,
+ d *Decoder) (_ map[float64]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[float64]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]uint32)
+ v, changed := fastpathTV.DecMapFloat64Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Uint32V(rv2i(rv).(map[float64]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Uint32X(vp *map[float64]uint32, d *Decoder) {
+ v, changed := f.DecMapFloat64Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Uint32V(v map[float64]uint32, canChange bool,
+ d *Decoder) (_ map[float64]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float64]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]uint64)
+ v, changed := fastpathTV.DecMapFloat64Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Uint64V(rv2i(rv).(map[float64]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Uint64X(vp *map[float64]uint64, d *Decoder) {
+ v, changed := f.DecMapFloat64Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Uint64V(v map[float64]uint64, canChange bool,
+ d *Decoder) (_ map[float64]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[float64]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]uintptr)
+ v, changed := fastpathTV.DecMapFloat64UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64UintptrV(rv2i(rv).(map[float64]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64UintptrX(vp *map[float64]uintptr, d *Decoder) {
+ v, changed := f.DecMapFloat64UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64UintptrV(v map[float64]uintptr, canChange bool,
+ d *Decoder) (_ map[float64]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[float64]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]int)
+ v, changed := fastpathTV.DecMapFloat64IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64IntV(rv2i(rv).(map[float64]int), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64IntX(vp *map[float64]int, d *Decoder) {
+ v, changed := f.DecMapFloat64IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64IntV(v map[float64]int, canChange bool,
+ d *Decoder) (_ map[float64]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[float64]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]int8)
+ v, changed := fastpathTV.DecMapFloat64Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Int8V(rv2i(rv).(map[float64]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Int8X(vp *map[float64]int8, d *Decoder) {
+ v, changed := f.DecMapFloat64Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Int8V(v map[float64]int8, canChange bool,
+ d *Decoder) (_ map[float64]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[float64]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]int16)
+ v, changed := fastpathTV.DecMapFloat64Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Int16V(rv2i(rv).(map[float64]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Int16X(vp *map[float64]int16, d *Decoder) {
+ v, changed := f.DecMapFloat64Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Int16V(v map[float64]int16, canChange bool,
+ d *Decoder) (_ map[float64]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[float64]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]int32)
+ v, changed := fastpathTV.DecMapFloat64Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Int32V(rv2i(rv).(map[float64]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Int32X(vp *map[float64]int32, d *Decoder) {
+ v, changed := f.DecMapFloat64Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Int32V(v map[float64]int32, canChange bool,
+ d *Decoder) (_ map[float64]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float64]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]int64)
+ v, changed := fastpathTV.DecMapFloat64Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Int64V(rv2i(rv).(map[float64]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Int64X(vp *map[float64]int64, d *Decoder) {
+ v, changed := f.DecMapFloat64Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Int64V(v map[float64]int64, canChange bool,
+ d *Decoder) (_ map[float64]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[float64]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]float32)
+ v, changed := fastpathTV.DecMapFloat64Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Float32V(rv2i(rv).(map[float64]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Float32X(vp *map[float64]float32, d *Decoder) {
+ v, changed := f.DecMapFloat64Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Float32V(v map[float64]float32, canChange bool,
+ d *Decoder) (_ map[float64]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[float64]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]float64)
+ v, changed := fastpathTV.DecMapFloat64Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64Float64V(rv2i(rv).(map[float64]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64Float64X(vp *map[float64]float64, d *Decoder) {
+ v, changed := f.DecMapFloat64Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64Float64V(v map[float64]float64, canChange bool,
+ d *Decoder) (_ map[float64]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[float64]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapFloat64BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[float64]bool)
+ v, changed := fastpathTV.DecMapFloat64BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapFloat64BoolV(rv2i(rv).(map[float64]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapFloat64BoolX(vp *map[float64]bool, d *Decoder) {
+ v, changed := f.DecMapFloat64BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapFloat64BoolV(v map[float64]bool, canChange bool,
+ d *Decoder) (_ map[float64]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[float64]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk float64
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeFloat64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintIntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]interface{})
+ v, changed := fastpathTV.DecMapUintIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintIntfV(rv2i(rv).(map[uint]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapUintIntfX(vp *map[uint]interface{}, d *Decoder) {
+ v, changed := f.DecMapUintIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintIntfV(v map[uint]interface{}, canChange bool,
+ d *Decoder) (_ map[uint]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[uint]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk uint
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintStringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]string)
+ v, changed := fastpathTV.DecMapUintStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintStringV(rv2i(rv).(map[uint]string), false, d)
+ }
+}
+func (f fastpathT) DecMapUintStringX(vp *map[uint]string, d *Decoder) {
+ v, changed := f.DecMapUintStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintStringV(v map[uint]string, canChange bool,
+ d *Decoder) (_ map[uint]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[uint]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintUintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]uint)
+ v, changed := fastpathTV.DecMapUintUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintUintV(rv2i(rv).(map[uint]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapUintUintX(vp *map[uint]uint, d *Decoder) {
+ v, changed := f.DecMapUintUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintUintV(v map[uint]uint, canChange bool,
+ d *Decoder) (_ map[uint]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintUint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]uint8)
+ v, changed := fastpathTV.DecMapUintUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintUint8V(rv2i(rv).(map[uint]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapUintUint8X(vp *map[uint]uint8, d *Decoder) {
+ v, changed := f.DecMapUintUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintUint8V(v map[uint]uint8, canChange bool,
+ d *Decoder) (_ map[uint]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintUint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]uint16)
+ v, changed := fastpathTV.DecMapUintUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintUint16V(rv2i(rv).(map[uint]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapUintUint16X(vp *map[uint]uint16, d *Decoder) {
+ v, changed := f.DecMapUintUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintUint16V(v map[uint]uint16, canChange bool,
+ d *Decoder) (_ map[uint]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintUint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]uint32)
+ v, changed := fastpathTV.DecMapUintUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintUint32V(rv2i(rv).(map[uint]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapUintUint32X(vp *map[uint]uint32, d *Decoder) {
+ v, changed := f.DecMapUintUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintUint32V(v map[uint]uint32, canChange bool,
+ d *Decoder) (_ map[uint]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintUint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]uint64)
+ v, changed := fastpathTV.DecMapUintUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintUint64V(rv2i(rv).(map[uint]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapUintUint64X(vp *map[uint]uint64, d *Decoder) {
+ v, changed := f.DecMapUintUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintUint64V(v map[uint]uint64, canChange bool,
+ d *Decoder) (_ map[uint]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]uintptr)
+ v, changed := fastpathTV.DecMapUintUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintUintptrV(rv2i(rv).(map[uint]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapUintUintptrX(vp *map[uint]uintptr, d *Decoder) {
+ v, changed := f.DecMapUintUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintUintptrV(v map[uint]uintptr, canChange bool,
+ d *Decoder) (_ map[uint]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintIntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]int)
+ v, changed := fastpathTV.DecMapUintIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintIntV(rv2i(rv).(map[uint]int), false, d)
+ }
+}
+func (f fastpathT) DecMapUintIntX(vp *map[uint]int, d *Decoder) {
+ v, changed := f.DecMapUintIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintIntV(v map[uint]int, canChange bool,
+ d *Decoder) (_ map[uint]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintInt8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]int8)
+ v, changed := fastpathTV.DecMapUintInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintInt8V(rv2i(rv).(map[uint]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapUintInt8X(vp *map[uint]int8, d *Decoder) {
+ v, changed := f.DecMapUintInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintInt8V(v map[uint]int8, canChange bool,
+ d *Decoder) (_ map[uint]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintInt16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]int16)
+ v, changed := fastpathTV.DecMapUintInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintInt16V(rv2i(rv).(map[uint]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapUintInt16X(vp *map[uint]int16, d *Decoder) {
+ v, changed := f.DecMapUintInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintInt16V(v map[uint]int16, canChange bool,
+ d *Decoder) (_ map[uint]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintInt32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]int32)
+ v, changed := fastpathTV.DecMapUintInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintInt32V(rv2i(rv).(map[uint]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapUintInt32X(vp *map[uint]int32, d *Decoder) {
+ v, changed := f.DecMapUintInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintInt32V(v map[uint]int32, canChange bool,
+ d *Decoder) (_ map[uint]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintInt64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]int64)
+ v, changed := fastpathTV.DecMapUintInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintInt64V(rv2i(rv).(map[uint]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapUintInt64X(vp *map[uint]int64, d *Decoder) {
+ v, changed := f.DecMapUintInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintInt64V(v map[uint]int64, canChange bool,
+ d *Decoder) (_ map[uint]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]float32)
+ v, changed := fastpathTV.DecMapUintFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintFloat32V(rv2i(rv).(map[uint]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapUintFloat32X(vp *map[uint]float32, d *Decoder) {
+ v, changed := f.DecMapUintFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintFloat32V(v map[uint]float32, canChange bool,
+ d *Decoder) (_ map[uint]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]float64)
+ v, changed := fastpathTV.DecMapUintFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintFloat64V(rv2i(rv).(map[uint]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapUintFloat64X(vp *map[uint]float64, d *Decoder) {
+ v, changed := f.DecMapUintFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintFloat64V(v map[uint]float64, canChange bool,
+ d *Decoder) (_ map[uint]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintBoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint]bool)
+ v, changed := fastpathTV.DecMapUintBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintBoolV(rv2i(rv).(map[uint]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapUintBoolX(vp *map[uint]bool, d *Decoder) {
+ v, changed := f.DecMapUintBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintBoolV(v map[uint]bool, canChange bool,
+ d *Decoder) (_ map[uint]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]interface{})
+ v, changed := fastpathTV.DecMapUint8IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8IntfV(rv2i(rv).(map[uint8]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8IntfX(vp *map[uint8]interface{}, d *Decoder) {
+ v, changed := f.DecMapUint8IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8IntfV(v map[uint8]interface{}, canChange bool,
+ d *Decoder) (_ map[uint8]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[uint8]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk uint8
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]string)
+ v, changed := fastpathTV.DecMapUint8StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8StringV(rv2i(rv).(map[uint8]string), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8StringX(vp *map[uint8]string, d *Decoder) {
+ v, changed := f.DecMapUint8StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8StringV(v map[uint8]string, canChange bool,
+ d *Decoder) (_ map[uint8]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[uint8]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]uint)
+ v, changed := fastpathTV.DecMapUint8UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8UintV(rv2i(rv).(map[uint8]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8UintX(vp *map[uint8]uint, d *Decoder) {
+ v, changed := f.DecMapUint8UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8UintV(v map[uint8]uint, canChange bool,
+ d *Decoder) (_ map[uint8]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint8]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]uint8)
+ v, changed := fastpathTV.DecMapUint8Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Uint8V(rv2i(rv).(map[uint8]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Uint8X(vp *map[uint8]uint8, d *Decoder) {
+ v, changed := f.DecMapUint8Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Uint8V(v map[uint8]uint8, canChange bool,
+ d *Decoder) (_ map[uint8]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[uint8]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]uint16)
+ v, changed := fastpathTV.DecMapUint8Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Uint16V(rv2i(rv).(map[uint8]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Uint16X(vp *map[uint8]uint16, d *Decoder) {
+ v, changed := f.DecMapUint8Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Uint16V(v map[uint8]uint16, canChange bool,
+ d *Decoder) (_ map[uint8]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[uint8]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]uint32)
+ v, changed := fastpathTV.DecMapUint8Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Uint32V(rv2i(rv).(map[uint8]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Uint32X(vp *map[uint8]uint32, d *Decoder) {
+ v, changed := f.DecMapUint8Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Uint32V(v map[uint8]uint32, canChange bool,
+ d *Decoder) (_ map[uint8]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[uint8]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]uint64)
+ v, changed := fastpathTV.DecMapUint8Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Uint64V(rv2i(rv).(map[uint8]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Uint64X(vp *map[uint8]uint64, d *Decoder) {
+ v, changed := f.DecMapUint8Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Uint64V(v map[uint8]uint64, canChange bool,
+ d *Decoder) (_ map[uint8]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint8]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]uintptr)
+ v, changed := fastpathTV.DecMapUint8UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8UintptrV(rv2i(rv).(map[uint8]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8UintptrX(vp *map[uint8]uintptr, d *Decoder) {
+ v, changed := f.DecMapUint8UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8UintptrV(v map[uint8]uintptr, canChange bool,
+ d *Decoder) (_ map[uint8]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint8]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]int)
+ v, changed := fastpathTV.DecMapUint8IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8IntV(rv2i(rv).(map[uint8]int), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8IntX(vp *map[uint8]int, d *Decoder) {
+ v, changed := f.DecMapUint8IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8IntV(v map[uint8]int, canChange bool,
+ d *Decoder) (_ map[uint8]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint8]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]int8)
+ v, changed := fastpathTV.DecMapUint8Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Int8V(rv2i(rv).(map[uint8]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Int8X(vp *map[uint8]int8, d *Decoder) {
+ v, changed := f.DecMapUint8Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Int8V(v map[uint8]int8, canChange bool,
+ d *Decoder) (_ map[uint8]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[uint8]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]int16)
+ v, changed := fastpathTV.DecMapUint8Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Int16V(rv2i(rv).(map[uint8]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Int16X(vp *map[uint8]int16, d *Decoder) {
+ v, changed := f.DecMapUint8Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Int16V(v map[uint8]int16, canChange bool,
+ d *Decoder) (_ map[uint8]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[uint8]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]int32)
+ v, changed := fastpathTV.DecMapUint8Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Int32V(rv2i(rv).(map[uint8]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Int32X(vp *map[uint8]int32, d *Decoder) {
+ v, changed := f.DecMapUint8Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Int32V(v map[uint8]int32, canChange bool,
+ d *Decoder) (_ map[uint8]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[uint8]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]int64)
+ v, changed := fastpathTV.DecMapUint8Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Int64V(rv2i(rv).(map[uint8]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Int64X(vp *map[uint8]int64, d *Decoder) {
+ v, changed := f.DecMapUint8Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Int64V(v map[uint8]int64, canChange bool,
+ d *Decoder) (_ map[uint8]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint8]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]float32)
+ v, changed := fastpathTV.DecMapUint8Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Float32V(rv2i(rv).(map[uint8]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Float32X(vp *map[uint8]float32, d *Decoder) {
+ v, changed := f.DecMapUint8Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Float32V(v map[uint8]float32, canChange bool,
+ d *Decoder) (_ map[uint8]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[uint8]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]float64)
+ v, changed := fastpathTV.DecMapUint8Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8Float64V(rv2i(rv).(map[uint8]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8Float64X(vp *map[uint8]float64, d *Decoder) {
+ v, changed := f.DecMapUint8Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8Float64V(v map[uint8]float64, canChange bool,
+ d *Decoder) (_ map[uint8]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint8]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint8BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint8]bool)
+ v, changed := fastpathTV.DecMapUint8BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint8BoolV(rv2i(rv).(map[uint8]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapUint8BoolX(vp *map[uint8]bool, d *Decoder) {
+ v, changed := f.DecMapUint8BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint8BoolV(v map[uint8]bool, canChange bool,
+ d *Decoder) (_ map[uint8]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[uint8]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint8
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]interface{})
+ v, changed := fastpathTV.DecMapUint16IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16IntfV(rv2i(rv).(map[uint16]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16IntfX(vp *map[uint16]interface{}, d *Decoder) {
+ v, changed := f.DecMapUint16IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16IntfV(v map[uint16]interface{}, canChange bool,
+ d *Decoder) (_ map[uint16]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[uint16]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk uint16
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]string)
+ v, changed := fastpathTV.DecMapUint16StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16StringV(rv2i(rv).(map[uint16]string), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16StringX(vp *map[uint16]string, d *Decoder) {
+ v, changed := f.DecMapUint16StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16StringV(v map[uint16]string, canChange bool,
+ d *Decoder) (_ map[uint16]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[uint16]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]uint)
+ v, changed := fastpathTV.DecMapUint16UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16UintV(rv2i(rv).(map[uint16]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16UintX(vp *map[uint16]uint, d *Decoder) {
+ v, changed := f.DecMapUint16UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16UintV(v map[uint16]uint, canChange bool,
+ d *Decoder) (_ map[uint16]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint16]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]uint8)
+ v, changed := fastpathTV.DecMapUint16Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Uint8V(rv2i(rv).(map[uint16]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Uint8X(vp *map[uint16]uint8, d *Decoder) {
+ v, changed := f.DecMapUint16Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Uint8V(v map[uint16]uint8, canChange bool,
+ d *Decoder) (_ map[uint16]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[uint16]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]uint16)
+ v, changed := fastpathTV.DecMapUint16Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Uint16V(rv2i(rv).(map[uint16]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Uint16X(vp *map[uint16]uint16, d *Decoder) {
+ v, changed := f.DecMapUint16Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Uint16V(v map[uint16]uint16, canChange bool,
+ d *Decoder) (_ map[uint16]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 4)
+ v = make(map[uint16]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]uint32)
+ v, changed := fastpathTV.DecMapUint16Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Uint32V(rv2i(rv).(map[uint16]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Uint32X(vp *map[uint16]uint32, d *Decoder) {
+ v, changed := f.DecMapUint16Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Uint32V(v map[uint16]uint32, canChange bool,
+ d *Decoder) (_ map[uint16]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[uint16]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]uint64)
+ v, changed := fastpathTV.DecMapUint16Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Uint64V(rv2i(rv).(map[uint16]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Uint64X(vp *map[uint16]uint64, d *Decoder) {
+ v, changed := f.DecMapUint16Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Uint64V(v map[uint16]uint64, canChange bool,
+ d *Decoder) (_ map[uint16]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint16]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]uintptr)
+ v, changed := fastpathTV.DecMapUint16UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16UintptrV(rv2i(rv).(map[uint16]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16UintptrX(vp *map[uint16]uintptr, d *Decoder) {
+ v, changed := f.DecMapUint16UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16UintptrV(v map[uint16]uintptr, canChange bool,
+ d *Decoder) (_ map[uint16]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint16]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]int)
+ v, changed := fastpathTV.DecMapUint16IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16IntV(rv2i(rv).(map[uint16]int), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16IntX(vp *map[uint16]int, d *Decoder) {
+ v, changed := f.DecMapUint16IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16IntV(v map[uint16]int, canChange bool,
+ d *Decoder) (_ map[uint16]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint16]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]int8)
+ v, changed := fastpathTV.DecMapUint16Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Int8V(rv2i(rv).(map[uint16]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Int8X(vp *map[uint16]int8, d *Decoder) {
+ v, changed := f.DecMapUint16Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Int8V(v map[uint16]int8, canChange bool,
+ d *Decoder) (_ map[uint16]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[uint16]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]int16)
+ v, changed := fastpathTV.DecMapUint16Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Int16V(rv2i(rv).(map[uint16]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Int16X(vp *map[uint16]int16, d *Decoder) {
+ v, changed := f.DecMapUint16Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Int16V(v map[uint16]int16, canChange bool,
+ d *Decoder) (_ map[uint16]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 4)
+ v = make(map[uint16]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]int32)
+ v, changed := fastpathTV.DecMapUint16Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Int32V(rv2i(rv).(map[uint16]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Int32X(vp *map[uint16]int32, d *Decoder) {
+ v, changed := f.DecMapUint16Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Int32V(v map[uint16]int32, canChange bool,
+ d *Decoder) (_ map[uint16]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[uint16]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]int64)
+ v, changed := fastpathTV.DecMapUint16Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Int64V(rv2i(rv).(map[uint16]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Int64X(vp *map[uint16]int64, d *Decoder) {
+ v, changed := f.DecMapUint16Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Int64V(v map[uint16]int64, canChange bool,
+ d *Decoder) (_ map[uint16]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint16]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]float32)
+ v, changed := fastpathTV.DecMapUint16Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Float32V(rv2i(rv).(map[uint16]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Float32X(vp *map[uint16]float32, d *Decoder) {
+ v, changed := f.DecMapUint16Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Float32V(v map[uint16]float32, canChange bool,
+ d *Decoder) (_ map[uint16]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[uint16]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]float64)
+ v, changed := fastpathTV.DecMapUint16Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16Float64V(rv2i(rv).(map[uint16]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16Float64X(vp *map[uint16]float64, d *Decoder) {
+ v, changed := f.DecMapUint16Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16Float64V(v map[uint16]float64, canChange bool,
+ d *Decoder) (_ map[uint16]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint16]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint16BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint16]bool)
+ v, changed := fastpathTV.DecMapUint16BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint16BoolV(rv2i(rv).(map[uint16]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapUint16BoolX(vp *map[uint16]bool, d *Decoder) {
+ v, changed := f.DecMapUint16BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint16BoolV(v map[uint16]bool, canChange bool,
+ d *Decoder) (_ map[uint16]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[uint16]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint16
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]interface{})
+ v, changed := fastpathTV.DecMapUint32IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32IntfV(rv2i(rv).(map[uint32]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32IntfX(vp *map[uint32]interface{}, d *Decoder) {
+ v, changed := f.DecMapUint32IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32IntfV(v map[uint32]interface{}, canChange bool,
+ d *Decoder) (_ map[uint32]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[uint32]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk uint32
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]string)
+ v, changed := fastpathTV.DecMapUint32StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32StringV(rv2i(rv).(map[uint32]string), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32StringX(vp *map[uint32]string, d *Decoder) {
+ v, changed := f.DecMapUint32StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32StringV(v map[uint32]string, canChange bool,
+ d *Decoder) (_ map[uint32]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[uint32]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]uint)
+ v, changed := fastpathTV.DecMapUint32UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32UintV(rv2i(rv).(map[uint32]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32UintX(vp *map[uint32]uint, d *Decoder) {
+ v, changed := f.DecMapUint32UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32UintV(v map[uint32]uint, canChange bool,
+ d *Decoder) (_ map[uint32]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint32]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]uint8)
+ v, changed := fastpathTV.DecMapUint32Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Uint8V(rv2i(rv).(map[uint32]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Uint8X(vp *map[uint32]uint8, d *Decoder) {
+ v, changed := f.DecMapUint32Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Uint8V(v map[uint32]uint8, canChange bool,
+ d *Decoder) (_ map[uint32]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[uint32]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]uint16)
+ v, changed := fastpathTV.DecMapUint32Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Uint16V(rv2i(rv).(map[uint32]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Uint16X(vp *map[uint32]uint16, d *Decoder) {
+ v, changed := f.DecMapUint32Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Uint16V(v map[uint32]uint16, canChange bool,
+ d *Decoder) (_ map[uint32]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[uint32]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]uint32)
+ v, changed := fastpathTV.DecMapUint32Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Uint32V(rv2i(rv).(map[uint32]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Uint32X(vp *map[uint32]uint32, d *Decoder) {
+ v, changed := f.DecMapUint32Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Uint32V(v map[uint32]uint32, canChange bool,
+ d *Decoder) (_ map[uint32]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[uint32]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]uint64)
+ v, changed := fastpathTV.DecMapUint32Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Uint64V(rv2i(rv).(map[uint32]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Uint64X(vp *map[uint32]uint64, d *Decoder) {
+ v, changed := f.DecMapUint32Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Uint64V(v map[uint32]uint64, canChange bool,
+ d *Decoder) (_ map[uint32]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint32]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]uintptr)
+ v, changed := fastpathTV.DecMapUint32UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32UintptrV(rv2i(rv).(map[uint32]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32UintptrX(vp *map[uint32]uintptr, d *Decoder) {
+ v, changed := f.DecMapUint32UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32UintptrV(v map[uint32]uintptr, canChange bool,
+ d *Decoder) (_ map[uint32]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint32]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]int)
+ v, changed := fastpathTV.DecMapUint32IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32IntV(rv2i(rv).(map[uint32]int), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32IntX(vp *map[uint32]int, d *Decoder) {
+ v, changed := f.DecMapUint32IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32IntV(v map[uint32]int, canChange bool,
+ d *Decoder) (_ map[uint32]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint32]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]int8)
+ v, changed := fastpathTV.DecMapUint32Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Int8V(rv2i(rv).(map[uint32]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Int8X(vp *map[uint32]int8, d *Decoder) {
+ v, changed := f.DecMapUint32Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Int8V(v map[uint32]int8, canChange bool,
+ d *Decoder) (_ map[uint32]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[uint32]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]int16)
+ v, changed := fastpathTV.DecMapUint32Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Int16V(rv2i(rv).(map[uint32]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Int16X(vp *map[uint32]int16, d *Decoder) {
+ v, changed := f.DecMapUint32Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Int16V(v map[uint32]int16, canChange bool,
+ d *Decoder) (_ map[uint32]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[uint32]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]int32)
+ v, changed := fastpathTV.DecMapUint32Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Int32V(rv2i(rv).(map[uint32]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Int32X(vp *map[uint32]int32, d *Decoder) {
+ v, changed := f.DecMapUint32Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Int32V(v map[uint32]int32, canChange bool,
+ d *Decoder) (_ map[uint32]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[uint32]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]int64)
+ v, changed := fastpathTV.DecMapUint32Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Int64V(rv2i(rv).(map[uint32]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Int64X(vp *map[uint32]int64, d *Decoder) {
+ v, changed := f.DecMapUint32Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Int64V(v map[uint32]int64, canChange bool,
+ d *Decoder) (_ map[uint32]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint32]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]float32)
+ v, changed := fastpathTV.DecMapUint32Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Float32V(rv2i(rv).(map[uint32]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Float32X(vp *map[uint32]float32, d *Decoder) {
+ v, changed := f.DecMapUint32Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Float32V(v map[uint32]float32, canChange bool,
+ d *Decoder) (_ map[uint32]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[uint32]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]float64)
+ v, changed := fastpathTV.DecMapUint32Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32Float64V(rv2i(rv).(map[uint32]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32Float64X(vp *map[uint32]float64, d *Decoder) {
+ v, changed := f.DecMapUint32Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32Float64V(v map[uint32]float64, canChange bool,
+ d *Decoder) (_ map[uint32]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint32]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint32BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint32]bool)
+ v, changed := fastpathTV.DecMapUint32BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint32BoolV(rv2i(rv).(map[uint32]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapUint32BoolX(vp *map[uint32]bool, d *Decoder) {
+ v, changed := f.DecMapUint32BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint32BoolV(v map[uint32]bool, canChange bool,
+ d *Decoder) (_ map[uint32]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[uint32]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint32
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]interface{})
+ v, changed := fastpathTV.DecMapUint64IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64IntfV(rv2i(rv).(map[uint64]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64IntfX(vp *map[uint64]interface{}, d *Decoder) {
+ v, changed := f.DecMapUint64IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64IntfV(v map[uint64]interface{}, canChange bool,
+ d *Decoder) (_ map[uint64]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[uint64]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk uint64
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]string)
+ v, changed := fastpathTV.DecMapUint64StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64StringV(rv2i(rv).(map[uint64]string), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64StringX(vp *map[uint64]string, d *Decoder) {
+ v, changed := f.DecMapUint64StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64StringV(v map[uint64]string, canChange bool,
+ d *Decoder) (_ map[uint64]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[uint64]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]uint)
+ v, changed := fastpathTV.DecMapUint64UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64UintV(rv2i(rv).(map[uint64]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64UintX(vp *map[uint64]uint, d *Decoder) {
+ v, changed := f.DecMapUint64UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64UintV(v map[uint64]uint, canChange bool,
+ d *Decoder) (_ map[uint64]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint64]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]uint8)
+ v, changed := fastpathTV.DecMapUint64Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Uint8V(rv2i(rv).(map[uint64]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Uint8X(vp *map[uint64]uint8, d *Decoder) {
+ v, changed := f.DecMapUint64Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Uint8V(v map[uint64]uint8, canChange bool,
+ d *Decoder) (_ map[uint64]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint64]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]uint16)
+ v, changed := fastpathTV.DecMapUint64Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Uint16V(rv2i(rv).(map[uint64]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Uint16X(vp *map[uint64]uint16, d *Decoder) {
+ v, changed := f.DecMapUint64Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Uint16V(v map[uint64]uint16, canChange bool,
+ d *Decoder) (_ map[uint64]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint64]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]uint32)
+ v, changed := fastpathTV.DecMapUint64Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Uint32V(rv2i(rv).(map[uint64]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Uint32X(vp *map[uint64]uint32, d *Decoder) {
+ v, changed := f.DecMapUint64Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Uint32V(v map[uint64]uint32, canChange bool,
+ d *Decoder) (_ map[uint64]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint64]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]uint64)
+ v, changed := fastpathTV.DecMapUint64Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Uint64V(rv2i(rv).(map[uint64]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Uint64X(vp *map[uint64]uint64, d *Decoder) {
+ v, changed := f.DecMapUint64Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Uint64V(v map[uint64]uint64, canChange bool,
+ d *Decoder) (_ map[uint64]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint64]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]uintptr)
+ v, changed := fastpathTV.DecMapUint64UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64UintptrV(rv2i(rv).(map[uint64]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64UintptrX(vp *map[uint64]uintptr, d *Decoder) {
+ v, changed := f.DecMapUint64UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64UintptrV(v map[uint64]uintptr, canChange bool,
+ d *Decoder) (_ map[uint64]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint64]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]int)
+ v, changed := fastpathTV.DecMapUint64IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64IntV(rv2i(rv).(map[uint64]int), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64IntX(vp *map[uint64]int, d *Decoder) {
+ v, changed := f.DecMapUint64IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64IntV(v map[uint64]int, canChange bool,
+ d *Decoder) (_ map[uint64]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint64]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]int8)
+ v, changed := fastpathTV.DecMapUint64Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Int8V(rv2i(rv).(map[uint64]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Int8X(vp *map[uint64]int8, d *Decoder) {
+ v, changed := f.DecMapUint64Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Int8V(v map[uint64]int8, canChange bool,
+ d *Decoder) (_ map[uint64]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint64]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]int16)
+ v, changed := fastpathTV.DecMapUint64Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Int16V(rv2i(rv).(map[uint64]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Int16X(vp *map[uint64]int16, d *Decoder) {
+ v, changed := f.DecMapUint64Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Int16V(v map[uint64]int16, canChange bool,
+ d *Decoder) (_ map[uint64]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uint64]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]int32)
+ v, changed := fastpathTV.DecMapUint64Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Int32V(rv2i(rv).(map[uint64]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Int32X(vp *map[uint64]int32, d *Decoder) {
+ v, changed := f.DecMapUint64Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Int32V(v map[uint64]int32, canChange bool,
+ d *Decoder) (_ map[uint64]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint64]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]int64)
+ v, changed := fastpathTV.DecMapUint64Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Int64V(rv2i(rv).(map[uint64]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Int64X(vp *map[uint64]int64, d *Decoder) {
+ v, changed := f.DecMapUint64Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Int64V(v map[uint64]int64, canChange bool,
+ d *Decoder) (_ map[uint64]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint64]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]float32)
+ v, changed := fastpathTV.DecMapUint64Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Float32V(rv2i(rv).(map[uint64]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Float32X(vp *map[uint64]float32, d *Decoder) {
+ v, changed := f.DecMapUint64Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Float32V(v map[uint64]float32, canChange bool,
+ d *Decoder) (_ map[uint64]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uint64]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]float64)
+ v, changed := fastpathTV.DecMapUint64Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64Float64V(rv2i(rv).(map[uint64]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64Float64X(vp *map[uint64]float64, d *Decoder) {
+ v, changed := f.DecMapUint64Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64Float64V(v map[uint64]float64, canChange bool,
+ d *Decoder) (_ map[uint64]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uint64]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUint64BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uint64]bool)
+ v, changed := fastpathTV.DecMapUint64BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUint64BoolV(rv2i(rv).(map[uint64]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapUint64BoolX(vp *map[uint64]bool, d *Decoder) {
+ v, changed := f.DecMapUint64BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUint64BoolV(v map[uint64]bool, canChange bool,
+ d *Decoder) (_ map[uint64]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uint64]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uint64
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeUint64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrIntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]interface{})
+ v, changed := fastpathTV.DecMapUintptrIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrIntfV(rv2i(rv).(map[uintptr]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrIntfX(vp *map[uintptr]interface{}, d *Decoder) {
+ v, changed := f.DecMapUintptrIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrIntfV(v map[uintptr]interface{}, canChange bool,
+ d *Decoder) (_ map[uintptr]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[uintptr]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk uintptr
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrStringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]string)
+ v, changed := fastpathTV.DecMapUintptrStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrStringV(rv2i(rv).(map[uintptr]string), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrStringX(vp *map[uintptr]string, d *Decoder) {
+ v, changed := f.DecMapUintptrStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrStringV(v map[uintptr]string, canChange bool,
+ d *Decoder) (_ map[uintptr]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[uintptr]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrUintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]uint)
+ v, changed := fastpathTV.DecMapUintptrUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrUintV(rv2i(rv).(map[uintptr]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrUintX(vp *map[uintptr]uint, d *Decoder) {
+ v, changed := f.DecMapUintptrUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrUintV(v map[uintptr]uint, canChange bool,
+ d *Decoder) (_ map[uintptr]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uintptr]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrUint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]uint8)
+ v, changed := fastpathTV.DecMapUintptrUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrUint8V(rv2i(rv).(map[uintptr]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrUint8X(vp *map[uintptr]uint8, d *Decoder) {
+ v, changed := f.DecMapUintptrUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrUint8V(v map[uintptr]uint8, canChange bool,
+ d *Decoder) (_ map[uintptr]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uintptr]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrUint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]uint16)
+ v, changed := fastpathTV.DecMapUintptrUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrUint16V(rv2i(rv).(map[uintptr]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrUint16X(vp *map[uintptr]uint16, d *Decoder) {
+ v, changed := f.DecMapUintptrUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrUint16V(v map[uintptr]uint16, canChange bool,
+ d *Decoder) (_ map[uintptr]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uintptr]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrUint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]uint32)
+ v, changed := fastpathTV.DecMapUintptrUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrUint32V(rv2i(rv).(map[uintptr]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrUint32X(vp *map[uintptr]uint32, d *Decoder) {
+ v, changed := f.DecMapUintptrUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrUint32V(v map[uintptr]uint32, canChange bool,
+ d *Decoder) (_ map[uintptr]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uintptr]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrUint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]uint64)
+ v, changed := fastpathTV.DecMapUintptrUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrUint64V(rv2i(rv).(map[uintptr]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrUint64X(vp *map[uintptr]uint64, d *Decoder) {
+ v, changed := f.DecMapUintptrUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrUint64V(v map[uintptr]uint64, canChange bool,
+ d *Decoder) (_ map[uintptr]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uintptr]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]uintptr)
+ v, changed := fastpathTV.DecMapUintptrUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrUintptrV(rv2i(rv).(map[uintptr]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrUintptrX(vp *map[uintptr]uintptr, d *Decoder) {
+ v, changed := f.DecMapUintptrUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrUintptrV(v map[uintptr]uintptr, canChange bool,
+ d *Decoder) (_ map[uintptr]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uintptr]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrIntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]int)
+ v, changed := fastpathTV.DecMapUintptrIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrIntV(rv2i(rv).(map[uintptr]int), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrIntX(vp *map[uintptr]int, d *Decoder) {
+ v, changed := f.DecMapUintptrIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrIntV(v map[uintptr]int, canChange bool,
+ d *Decoder) (_ map[uintptr]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uintptr]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrInt8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]int8)
+ v, changed := fastpathTV.DecMapUintptrInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrInt8V(rv2i(rv).(map[uintptr]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrInt8X(vp *map[uintptr]int8, d *Decoder) {
+ v, changed := f.DecMapUintptrInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrInt8V(v map[uintptr]int8, canChange bool,
+ d *Decoder) (_ map[uintptr]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uintptr]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrInt16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]int16)
+ v, changed := fastpathTV.DecMapUintptrInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrInt16V(rv2i(rv).(map[uintptr]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrInt16X(vp *map[uintptr]int16, d *Decoder) {
+ v, changed := f.DecMapUintptrInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrInt16V(v map[uintptr]int16, canChange bool,
+ d *Decoder) (_ map[uintptr]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[uintptr]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrInt32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]int32)
+ v, changed := fastpathTV.DecMapUintptrInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrInt32V(rv2i(rv).(map[uintptr]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrInt32X(vp *map[uintptr]int32, d *Decoder) {
+ v, changed := f.DecMapUintptrInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrInt32V(v map[uintptr]int32, canChange bool,
+ d *Decoder) (_ map[uintptr]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uintptr]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrInt64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]int64)
+ v, changed := fastpathTV.DecMapUintptrInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrInt64V(rv2i(rv).(map[uintptr]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrInt64X(vp *map[uintptr]int64, d *Decoder) {
+ v, changed := f.DecMapUintptrInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrInt64V(v map[uintptr]int64, canChange bool,
+ d *Decoder) (_ map[uintptr]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uintptr]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]float32)
+ v, changed := fastpathTV.DecMapUintptrFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrFloat32V(rv2i(rv).(map[uintptr]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrFloat32X(vp *map[uintptr]float32, d *Decoder) {
+ v, changed := f.DecMapUintptrFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrFloat32V(v map[uintptr]float32, canChange bool,
+ d *Decoder) (_ map[uintptr]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[uintptr]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]float64)
+ v, changed := fastpathTV.DecMapUintptrFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrFloat64V(rv2i(rv).(map[uintptr]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrFloat64X(vp *map[uintptr]float64, d *Decoder) {
+ v, changed := f.DecMapUintptrFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrFloat64V(v map[uintptr]float64, canChange bool,
+ d *Decoder) (_ map[uintptr]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[uintptr]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapUintptrBoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[uintptr]bool)
+ v, changed := fastpathTV.DecMapUintptrBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapUintptrBoolV(rv2i(rv).(map[uintptr]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapUintptrBoolX(vp *map[uintptr]bool, d *Decoder) {
+ v, changed := f.DecMapUintptrBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapUintptrBoolV(v map[uintptr]bool, canChange bool,
+ d *Decoder) (_ map[uintptr]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[uintptr]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk uintptr
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntIntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]interface{})
+ v, changed := fastpathTV.DecMapIntIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntIntfV(rv2i(rv).(map[int]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapIntIntfX(vp *map[int]interface{}, d *Decoder) {
+ v, changed := f.DecMapIntIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntIntfV(v map[int]interface{}, canChange bool,
+ d *Decoder) (_ map[int]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[int]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk int
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntStringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]string)
+ v, changed := fastpathTV.DecMapIntStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntStringV(rv2i(rv).(map[int]string), false, d)
+ }
+}
+func (f fastpathT) DecMapIntStringX(vp *map[int]string, d *Decoder) {
+ v, changed := f.DecMapIntStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntStringV(v map[int]string, canChange bool,
+ d *Decoder) (_ map[int]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[int]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntUintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]uint)
+ v, changed := fastpathTV.DecMapIntUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntUintV(rv2i(rv).(map[int]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapIntUintX(vp *map[int]uint, d *Decoder) {
+ v, changed := f.DecMapIntUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntUintV(v map[int]uint, canChange bool,
+ d *Decoder) (_ map[int]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntUint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]uint8)
+ v, changed := fastpathTV.DecMapIntUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntUint8V(rv2i(rv).(map[int]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapIntUint8X(vp *map[int]uint8, d *Decoder) {
+ v, changed := f.DecMapIntUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntUint8V(v map[int]uint8, canChange bool,
+ d *Decoder) (_ map[int]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntUint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]uint16)
+ v, changed := fastpathTV.DecMapIntUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntUint16V(rv2i(rv).(map[int]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapIntUint16X(vp *map[int]uint16, d *Decoder) {
+ v, changed := f.DecMapIntUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntUint16V(v map[int]uint16, canChange bool,
+ d *Decoder) (_ map[int]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntUint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]uint32)
+ v, changed := fastpathTV.DecMapIntUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntUint32V(rv2i(rv).(map[int]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapIntUint32X(vp *map[int]uint32, d *Decoder) {
+ v, changed := f.DecMapIntUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntUint32V(v map[int]uint32, canChange bool,
+ d *Decoder) (_ map[int]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntUint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]uint64)
+ v, changed := fastpathTV.DecMapIntUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntUint64V(rv2i(rv).(map[int]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapIntUint64X(vp *map[int]uint64, d *Decoder) {
+ v, changed := f.DecMapIntUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntUint64V(v map[int]uint64, canChange bool,
+ d *Decoder) (_ map[int]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]uintptr)
+ v, changed := fastpathTV.DecMapIntUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntUintptrV(rv2i(rv).(map[int]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapIntUintptrX(vp *map[int]uintptr, d *Decoder) {
+ v, changed := f.DecMapIntUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntUintptrV(v map[int]uintptr, canChange bool,
+ d *Decoder) (_ map[int]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntIntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]int)
+ v, changed := fastpathTV.DecMapIntIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntIntV(rv2i(rv).(map[int]int), false, d)
+ }
+}
+func (f fastpathT) DecMapIntIntX(vp *map[int]int, d *Decoder) {
+ v, changed := f.DecMapIntIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntIntV(v map[int]int, canChange bool,
+ d *Decoder) (_ map[int]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntInt8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]int8)
+ v, changed := fastpathTV.DecMapIntInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntInt8V(rv2i(rv).(map[int]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapIntInt8X(vp *map[int]int8, d *Decoder) {
+ v, changed := f.DecMapIntInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntInt8V(v map[int]int8, canChange bool,
+ d *Decoder) (_ map[int]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntInt16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]int16)
+ v, changed := fastpathTV.DecMapIntInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntInt16V(rv2i(rv).(map[int]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapIntInt16X(vp *map[int]int16, d *Decoder) {
+ v, changed := f.DecMapIntInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntInt16V(v map[int]int16, canChange bool,
+ d *Decoder) (_ map[int]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntInt32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]int32)
+ v, changed := fastpathTV.DecMapIntInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntInt32V(rv2i(rv).(map[int]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapIntInt32X(vp *map[int]int32, d *Decoder) {
+ v, changed := f.DecMapIntInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntInt32V(v map[int]int32, canChange bool,
+ d *Decoder) (_ map[int]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntInt64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]int64)
+ v, changed := fastpathTV.DecMapIntInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntInt64V(rv2i(rv).(map[int]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapIntInt64X(vp *map[int]int64, d *Decoder) {
+ v, changed := f.DecMapIntInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntInt64V(v map[int]int64, canChange bool,
+ d *Decoder) (_ map[int]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]float32)
+ v, changed := fastpathTV.DecMapIntFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntFloat32V(rv2i(rv).(map[int]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapIntFloat32X(vp *map[int]float32, d *Decoder) {
+ v, changed := f.DecMapIntFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntFloat32V(v map[int]float32, canChange bool,
+ d *Decoder) (_ map[int]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]float64)
+ v, changed := fastpathTV.DecMapIntFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntFloat64V(rv2i(rv).(map[int]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapIntFloat64X(vp *map[int]float64, d *Decoder) {
+ v, changed := f.DecMapIntFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntFloat64V(v map[int]float64, canChange bool,
+ d *Decoder) (_ map[int]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapIntBoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int]bool)
+ v, changed := fastpathTV.DecMapIntBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapIntBoolV(rv2i(rv).(map[int]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapIntBoolX(vp *map[int]bool, d *Decoder) {
+ v, changed := f.DecMapIntBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapIntBoolV(v map[int]bool, canChange bool,
+ d *Decoder) (_ map[int]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]interface{})
+ v, changed := fastpathTV.DecMapInt8IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8IntfV(rv2i(rv).(map[int8]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8IntfX(vp *map[int8]interface{}, d *Decoder) {
+ v, changed := f.DecMapInt8IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8IntfV(v map[int8]interface{}, canChange bool,
+ d *Decoder) (_ map[int8]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[int8]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk int8
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]string)
+ v, changed := fastpathTV.DecMapInt8StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8StringV(rv2i(rv).(map[int8]string), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8StringX(vp *map[int8]string, d *Decoder) {
+ v, changed := f.DecMapInt8StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8StringV(v map[int8]string, canChange bool,
+ d *Decoder) (_ map[int8]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[int8]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]uint)
+ v, changed := fastpathTV.DecMapInt8UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8UintV(rv2i(rv).(map[int8]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8UintX(vp *map[int8]uint, d *Decoder) {
+ v, changed := f.DecMapInt8UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8UintV(v map[int8]uint, canChange bool,
+ d *Decoder) (_ map[int8]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int8]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]uint8)
+ v, changed := fastpathTV.DecMapInt8Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Uint8V(rv2i(rv).(map[int8]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Uint8X(vp *map[int8]uint8, d *Decoder) {
+ v, changed := f.DecMapInt8Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Uint8V(v map[int8]uint8, canChange bool,
+ d *Decoder) (_ map[int8]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[int8]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]uint16)
+ v, changed := fastpathTV.DecMapInt8Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Uint16V(rv2i(rv).(map[int8]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Uint16X(vp *map[int8]uint16, d *Decoder) {
+ v, changed := f.DecMapInt8Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Uint16V(v map[int8]uint16, canChange bool,
+ d *Decoder) (_ map[int8]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[int8]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]uint32)
+ v, changed := fastpathTV.DecMapInt8Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Uint32V(rv2i(rv).(map[int8]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Uint32X(vp *map[int8]uint32, d *Decoder) {
+ v, changed := f.DecMapInt8Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Uint32V(v map[int8]uint32, canChange bool,
+ d *Decoder) (_ map[int8]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[int8]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]uint64)
+ v, changed := fastpathTV.DecMapInt8Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Uint64V(rv2i(rv).(map[int8]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Uint64X(vp *map[int8]uint64, d *Decoder) {
+ v, changed := f.DecMapInt8Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Uint64V(v map[int8]uint64, canChange bool,
+ d *Decoder) (_ map[int8]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int8]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]uintptr)
+ v, changed := fastpathTV.DecMapInt8UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8UintptrV(rv2i(rv).(map[int8]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8UintptrX(vp *map[int8]uintptr, d *Decoder) {
+ v, changed := f.DecMapInt8UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8UintptrV(v map[int8]uintptr, canChange bool,
+ d *Decoder) (_ map[int8]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int8]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]int)
+ v, changed := fastpathTV.DecMapInt8IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8IntV(rv2i(rv).(map[int8]int), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8IntX(vp *map[int8]int, d *Decoder) {
+ v, changed := f.DecMapInt8IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8IntV(v map[int8]int, canChange bool,
+ d *Decoder) (_ map[int8]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int8]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]int8)
+ v, changed := fastpathTV.DecMapInt8Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Int8V(rv2i(rv).(map[int8]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Int8X(vp *map[int8]int8, d *Decoder) {
+ v, changed := f.DecMapInt8Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Int8V(v map[int8]int8, canChange bool,
+ d *Decoder) (_ map[int8]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[int8]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]int16)
+ v, changed := fastpathTV.DecMapInt8Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Int16V(rv2i(rv).(map[int8]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Int16X(vp *map[int8]int16, d *Decoder) {
+ v, changed := f.DecMapInt8Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Int16V(v map[int8]int16, canChange bool,
+ d *Decoder) (_ map[int8]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[int8]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]int32)
+ v, changed := fastpathTV.DecMapInt8Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Int32V(rv2i(rv).(map[int8]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Int32X(vp *map[int8]int32, d *Decoder) {
+ v, changed := f.DecMapInt8Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Int32V(v map[int8]int32, canChange bool,
+ d *Decoder) (_ map[int8]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[int8]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]int64)
+ v, changed := fastpathTV.DecMapInt8Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Int64V(rv2i(rv).(map[int8]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Int64X(vp *map[int8]int64, d *Decoder) {
+ v, changed := f.DecMapInt8Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Int64V(v map[int8]int64, canChange bool,
+ d *Decoder) (_ map[int8]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int8]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]float32)
+ v, changed := fastpathTV.DecMapInt8Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Float32V(rv2i(rv).(map[int8]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Float32X(vp *map[int8]float32, d *Decoder) {
+ v, changed := f.DecMapInt8Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Float32V(v map[int8]float32, canChange bool,
+ d *Decoder) (_ map[int8]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[int8]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]float64)
+ v, changed := fastpathTV.DecMapInt8Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8Float64V(rv2i(rv).(map[int8]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8Float64X(vp *map[int8]float64, d *Decoder) {
+ v, changed := f.DecMapInt8Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8Float64V(v map[int8]float64, canChange bool,
+ d *Decoder) (_ map[int8]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int8]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt8BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int8]bool)
+ v, changed := fastpathTV.DecMapInt8BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt8BoolV(rv2i(rv).(map[int8]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapInt8BoolX(vp *map[int8]bool, d *Decoder) {
+ v, changed := f.DecMapInt8BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt8BoolV(v map[int8]bool, canChange bool,
+ d *Decoder) (_ map[int8]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[int8]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int8
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]interface{})
+ v, changed := fastpathTV.DecMapInt16IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16IntfV(rv2i(rv).(map[int16]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16IntfX(vp *map[int16]interface{}, d *Decoder) {
+ v, changed := f.DecMapInt16IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16IntfV(v map[int16]interface{}, canChange bool,
+ d *Decoder) (_ map[int16]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[int16]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk int16
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]string)
+ v, changed := fastpathTV.DecMapInt16StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16StringV(rv2i(rv).(map[int16]string), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16StringX(vp *map[int16]string, d *Decoder) {
+ v, changed := f.DecMapInt16StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16StringV(v map[int16]string, canChange bool,
+ d *Decoder) (_ map[int16]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 18)
+ v = make(map[int16]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]uint)
+ v, changed := fastpathTV.DecMapInt16UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16UintV(rv2i(rv).(map[int16]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16UintX(vp *map[int16]uint, d *Decoder) {
+ v, changed := f.DecMapInt16UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16UintV(v map[int16]uint, canChange bool,
+ d *Decoder) (_ map[int16]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int16]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]uint8)
+ v, changed := fastpathTV.DecMapInt16Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Uint8V(rv2i(rv).(map[int16]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Uint8X(vp *map[int16]uint8, d *Decoder) {
+ v, changed := f.DecMapInt16Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Uint8V(v map[int16]uint8, canChange bool,
+ d *Decoder) (_ map[int16]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[int16]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]uint16)
+ v, changed := fastpathTV.DecMapInt16Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Uint16V(rv2i(rv).(map[int16]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Uint16X(vp *map[int16]uint16, d *Decoder) {
+ v, changed := f.DecMapInt16Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Uint16V(v map[int16]uint16, canChange bool,
+ d *Decoder) (_ map[int16]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 4)
+ v = make(map[int16]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]uint32)
+ v, changed := fastpathTV.DecMapInt16Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Uint32V(rv2i(rv).(map[int16]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Uint32X(vp *map[int16]uint32, d *Decoder) {
+ v, changed := f.DecMapInt16Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Uint32V(v map[int16]uint32, canChange bool,
+ d *Decoder) (_ map[int16]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[int16]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]uint64)
+ v, changed := fastpathTV.DecMapInt16Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Uint64V(rv2i(rv).(map[int16]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Uint64X(vp *map[int16]uint64, d *Decoder) {
+ v, changed := f.DecMapInt16Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Uint64V(v map[int16]uint64, canChange bool,
+ d *Decoder) (_ map[int16]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int16]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]uintptr)
+ v, changed := fastpathTV.DecMapInt16UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16UintptrV(rv2i(rv).(map[int16]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16UintptrX(vp *map[int16]uintptr, d *Decoder) {
+ v, changed := f.DecMapInt16UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16UintptrV(v map[int16]uintptr, canChange bool,
+ d *Decoder) (_ map[int16]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int16]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]int)
+ v, changed := fastpathTV.DecMapInt16IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16IntV(rv2i(rv).(map[int16]int), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16IntX(vp *map[int16]int, d *Decoder) {
+ v, changed := f.DecMapInt16IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16IntV(v map[int16]int, canChange bool,
+ d *Decoder) (_ map[int16]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int16]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]int8)
+ v, changed := fastpathTV.DecMapInt16Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Int8V(rv2i(rv).(map[int16]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Int8X(vp *map[int16]int8, d *Decoder) {
+ v, changed := f.DecMapInt16Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Int8V(v map[int16]int8, canChange bool,
+ d *Decoder) (_ map[int16]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[int16]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]int16)
+ v, changed := fastpathTV.DecMapInt16Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Int16V(rv2i(rv).(map[int16]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Int16X(vp *map[int16]int16, d *Decoder) {
+ v, changed := f.DecMapInt16Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Int16V(v map[int16]int16, canChange bool,
+ d *Decoder) (_ map[int16]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 4)
+ v = make(map[int16]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]int32)
+ v, changed := fastpathTV.DecMapInt16Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Int32V(rv2i(rv).(map[int16]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Int32X(vp *map[int16]int32, d *Decoder) {
+ v, changed := f.DecMapInt16Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Int32V(v map[int16]int32, canChange bool,
+ d *Decoder) (_ map[int16]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[int16]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]int64)
+ v, changed := fastpathTV.DecMapInt16Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Int64V(rv2i(rv).(map[int16]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Int64X(vp *map[int16]int64, d *Decoder) {
+ v, changed := f.DecMapInt16Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Int64V(v map[int16]int64, canChange bool,
+ d *Decoder) (_ map[int16]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int16]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]float32)
+ v, changed := fastpathTV.DecMapInt16Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Float32V(rv2i(rv).(map[int16]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Float32X(vp *map[int16]float32, d *Decoder) {
+ v, changed := f.DecMapInt16Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Float32V(v map[int16]float32, canChange bool,
+ d *Decoder) (_ map[int16]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[int16]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]float64)
+ v, changed := fastpathTV.DecMapInt16Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16Float64V(rv2i(rv).(map[int16]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16Float64X(vp *map[int16]float64, d *Decoder) {
+ v, changed := f.DecMapInt16Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16Float64V(v map[int16]float64, canChange bool,
+ d *Decoder) (_ map[int16]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int16]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt16BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int16]bool)
+ v, changed := fastpathTV.DecMapInt16BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt16BoolV(rv2i(rv).(map[int16]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapInt16BoolX(vp *map[int16]bool, d *Decoder) {
+ v, changed := f.DecMapInt16BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt16BoolV(v map[int16]bool, canChange bool,
+ d *Decoder) (_ map[int16]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[int16]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int16
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]interface{})
+ v, changed := fastpathTV.DecMapInt32IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32IntfV(rv2i(rv).(map[int32]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32IntfX(vp *map[int32]interface{}, d *Decoder) {
+ v, changed := f.DecMapInt32IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32IntfV(v map[int32]interface{}, canChange bool,
+ d *Decoder) (_ map[int32]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[int32]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk int32
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]string)
+ v, changed := fastpathTV.DecMapInt32StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32StringV(rv2i(rv).(map[int32]string), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32StringX(vp *map[int32]string, d *Decoder) {
+ v, changed := f.DecMapInt32StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32StringV(v map[int32]string, canChange bool,
+ d *Decoder) (_ map[int32]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 20)
+ v = make(map[int32]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]uint)
+ v, changed := fastpathTV.DecMapInt32UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32UintV(rv2i(rv).(map[int32]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32UintX(vp *map[int32]uint, d *Decoder) {
+ v, changed := f.DecMapInt32UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32UintV(v map[int32]uint, canChange bool,
+ d *Decoder) (_ map[int32]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int32]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]uint8)
+ v, changed := fastpathTV.DecMapInt32Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Uint8V(rv2i(rv).(map[int32]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Uint8X(vp *map[int32]uint8, d *Decoder) {
+ v, changed := f.DecMapInt32Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Uint8V(v map[int32]uint8, canChange bool,
+ d *Decoder) (_ map[int32]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[int32]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]uint16)
+ v, changed := fastpathTV.DecMapInt32Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Uint16V(rv2i(rv).(map[int32]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Uint16X(vp *map[int32]uint16, d *Decoder) {
+ v, changed := f.DecMapInt32Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Uint16V(v map[int32]uint16, canChange bool,
+ d *Decoder) (_ map[int32]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[int32]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]uint32)
+ v, changed := fastpathTV.DecMapInt32Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Uint32V(rv2i(rv).(map[int32]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Uint32X(vp *map[int32]uint32, d *Decoder) {
+ v, changed := f.DecMapInt32Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Uint32V(v map[int32]uint32, canChange bool,
+ d *Decoder) (_ map[int32]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[int32]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]uint64)
+ v, changed := fastpathTV.DecMapInt32Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Uint64V(rv2i(rv).(map[int32]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Uint64X(vp *map[int32]uint64, d *Decoder) {
+ v, changed := f.DecMapInt32Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Uint64V(v map[int32]uint64, canChange bool,
+ d *Decoder) (_ map[int32]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int32]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]uintptr)
+ v, changed := fastpathTV.DecMapInt32UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32UintptrV(rv2i(rv).(map[int32]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32UintptrX(vp *map[int32]uintptr, d *Decoder) {
+ v, changed := f.DecMapInt32UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32UintptrV(v map[int32]uintptr, canChange bool,
+ d *Decoder) (_ map[int32]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int32]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]int)
+ v, changed := fastpathTV.DecMapInt32IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32IntV(rv2i(rv).(map[int32]int), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32IntX(vp *map[int32]int, d *Decoder) {
+ v, changed := f.DecMapInt32IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32IntV(v map[int32]int, canChange bool,
+ d *Decoder) (_ map[int32]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int32]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]int8)
+ v, changed := fastpathTV.DecMapInt32Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Int8V(rv2i(rv).(map[int32]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Int8X(vp *map[int32]int8, d *Decoder) {
+ v, changed := f.DecMapInt32Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Int8V(v map[int32]int8, canChange bool,
+ d *Decoder) (_ map[int32]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[int32]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]int16)
+ v, changed := fastpathTV.DecMapInt32Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Int16V(rv2i(rv).(map[int32]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Int16X(vp *map[int32]int16, d *Decoder) {
+ v, changed := f.DecMapInt32Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Int16V(v map[int32]int16, canChange bool,
+ d *Decoder) (_ map[int32]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 6)
+ v = make(map[int32]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]int32)
+ v, changed := fastpathTV.DecMapInt32Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Int32V(rv2i(rv).(map[int32]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Int32X(vp *map[int32]int32, d *Decoder) {
+ v, changed := f.DecMapInt32Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Int32V(v map[int32]int32, canChange bool,
+ d *Decoder) (_ map[int32]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[int32]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]int64)
+ v, changed := fastpathTV.DecMapInt32Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Int64V(rv2i(rv).(map[int32]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Int64X(vp *map[int32]int64, d *Decoder) {
+ v, changed := f.DecMapInt32Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Int64V(v map[int32]int64, canChange bool,
+ d *Decoder) (_ map[int32]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int32]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]float32)
+ v, changed := fastpathTV.DecMapInt32Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Float32V(rv2i(rv).(map[int32]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Float32X(vp *map[int32]float32, d *Decoder) {
+ v, changed := f.DecMapInt32Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Float32V(v map[int32]float32, canChange bool,
+ d *Decoder) (_ map[int32]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 8)
+ v = make(map[int32]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]float64)
+ v, changed := fastpathTV.DecMapInt32Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32Float64V(rv2i(rv).(map[int32]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32Float64X(vp *map[int32]float64, d *Decoder) {
+ v, changed := f.DecMapInt32Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32Float64V(v map[int32]float64, canChange bool,
+ d *Decoder) (_ map[int32]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int32]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt32BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int32]bool)
+ v, changed := fastpathTV.DecMapInt32BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt32BoolV(rv2i(rv).(map[int32]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapInt32BoolX(vp *map[int32]bool, d *Decoder) {
+ v, changed := f.DecMapInt32BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt32BoolV(v map[int32]bool, canChange bool,
+ d *Decoder) (_ map[int32]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[int32]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int32
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64IntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]interface{})
+ v, changed := fastpathTV.DecMapInt64IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64IntfV(rv2i(rv).(map[int64]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64IntfX(vp *map[int64]interface{}, d *Decoder) {
+ v, changed := f.DecMapInt64IntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64IntfV(v map[int64]interface{}, canChange bool,
+ d *Decoder) (_ map[int64]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[int64]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk int64
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64StringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]string)
+ v, changed := fastpathTV.DecMapInt64StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64StringV(rv2i(rv).(map[int64]string), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64StringX(vp *map[int64]string, d *Decoder) {
+ v, changed := f.DecMapInt64StringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64StringV(v map[int64]string, canChange bool,
+ d *Decoder) (_ map[int64]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 24)
+ v = make(map[int64]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64UintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]uint)
+ v, changed := fastpathTV.DecMapInt64UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64UintV(rv2i(rv).(map[int64]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64UintX(vp *map[int64]uint, d *Decoder) {
+ v, changed := f.DecMapInt64UintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64UintV(v map[int64]uint, canChange bool,
+ d *Decoder) (_ map[int64]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int64]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Uint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]uint8)
+ v, changed := fastpathTV.DecMapInt64Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Uint8V(rv2i(rv).(map[int64]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Uint8X(vp *map[int64]uint8, d *Decoder) {
+ v, changed := f.DecMapInt64Uint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Uint8V(v map[int64]uint8, canChange bool,
+ d *Decoder) (_ map[int64]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int64]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Uint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]uint16)
+ v, changed := fastpathTV.DecMapInt64Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Uint16V(rv2i(rv).(map[int64]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Uint16X(vp *map[int64]uint16, d *Decoder) {
+ v, changed := f.DecMapInt64Uint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Uint16V(v map[int64]uint16, canChange bool,
+ d *Decoder) (_ map[int64]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int64]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Uint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]uint32)
+ v, changed := fastpathTV.DecMapInt64Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Uint32V(rv2i(rv).(map[int64]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Uint32X(vp *map[int64]uint32, d *Decoder) {
+ v, changed := f.DecMapInt64Uint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Uint32V(v map[int64]uint32, canChange bool,
+ d *Decoder) (_ map[int64]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int64]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Uint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]uint64)
+ v, changed := fastpathTV.DecMapInt64Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Uint64V(rv2i(rv).(map[int64]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Uint64X(vp *map[int64]uint64, d *Decoder) {
+ v, changed := f.DecMapInt64Uint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Uint64V(v map[int64]uint64, canChange bool,
+ d *Decoder) (_ map[int64]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int64]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64UintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]uintptr)
+ v, changed := fastpathTV.DecMapInt64UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64UintptrV(rv2i(rv).(map[int64]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64UintptrX(vp *map[int64]uintptr, d *Decoder) {
+ v, changed := f.DecMapInt64UintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64UintptrV(v map[int64]uintptr, canChange bool,
+ d *Decoder) (_ map[int64]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int64]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64IntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]int)
+ v, changed := fastpathTV.DecMapInt64IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64IntV(rv2i(rv).(map[int64]int), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64IntX(vp *map[int64]int, d *Decoder) {
+ v, changed := f.DecMapInt64IntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64IntV(v map[int64]int, canChange bool,
+ d *Decoder) (_ map[int64]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int64]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Int8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]int8)
+ v, changed := fastpathTV.DecMapInt64Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Int8V(rv2i(rv).(map[int64]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Int8X(vp *map[int64]int8, d *Decoder) {
+ v, changed := f.DecMapInt64Int8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Int8V(v map[int64]int8, canChange bool,
+ d *Decoder) (_ map[int64]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int64]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Int16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]int16)
+ v, changed := fastpathTV.DecMapInt64Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Int16V(rv2i(rv).(map[int64]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Int16X(vp *map[int64]int16, d *Decoder) {
+ v, changed := f.DecMapInt64Int16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Int16V(v map[int64]int16, canChange bool,
+ d *Decoder) (_ map[int64]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 10)
+ v = make(map[int64]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Int32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]int32)
+ v, changed := fastpathTV.DecMapInt64Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Int32V(rv2i(rv).(map[int64]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Int32X(vp *map[int64]int32, d *Decoder) {
+ v, changed := f.DecMapInt64Int32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Int32V(v map[int64]int32, canChange bool,
+ d *Decoder) (_ map[int64]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int64]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Int64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]int64)
+ v, changed := fastpathTV.DecMapInt64Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Int64V(rv2i(rv).(map[int64]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Int64X(vp *map[int64]int64, d *Decoder) {
+ v, changed := f.DecMapInt64Int64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Int64V(v map[int64]int64, canChange bool,
+ d *Decoder) (_ map[int64]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int64]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Float32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]float32)
+ v, changed := fastpathTV.DecMapInt64Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Float32V(rv2i(rv).(map[int64]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Float32X(vp *map[int64]float32, d *Decoder) {
+ v, changed := f.DecMapInt64Float32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Float32V(v map[int64]float32, canChange bool,
+ d *Decoder) (_ map[int64]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 12)
+ v = make(map[int64]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64Float64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]float64)
+ v, changed := fastpathTV.DecMapInt64Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64Float64V(rv2i(rv).(map[int64]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64Float64X(vp *map[int64]float64, d *Decoder) {
+ v, changed := f.DecMapInt64Float64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64Float64V(v map[int64]float64, canChange bool,
+ d *Decoder) (_ map[int64]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 16)
+ v = make(map[int64]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapInt64BoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[int64]bool)
+ v, changed := fastpathTV.DecMapInt64BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapInt64BoolV(rv2i(rv).(map[int64]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapInt64BoolX(vp *map[int64]bool, d *Decoder) {
+ v, changed := f.DecMapInt64BoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapInt64BoolV(v map[int64]bool, canChange bool,
+ d *Decoder) (_ map[int64]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[int64]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk int64
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeInt64()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolIntfR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]interface{})
+ v, changed := fastpathTV.DecMapBoolIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolIntfV(rv2i(rv).(map[bool]interface{}), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolIntfX(vp *map[bool]interface{}, d *Decoder) {
+ v, changed := f.DecMapBoolIntfV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolIntfV(v map[bool]interface{}, canChange bool,
+ d *Decoder) (_ map[bool]interface{}, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[bool]interface{}, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ mapGet := v != nil && !d.h.MapValueReset && !d.h.InterfaceReset
+ var mk bool
+ var mv interface{}
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = nil
+ }
+ continue
+ }
+ if mapGet {
+ mv = v[mk]
+ } else {
+ mv = nil
+ }
+ d.decode(&mv)
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolStringR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]string)
+ v, changed := fastpathTV.DecMapBoolStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolStringV(rv2i(rv).(map[bool]string), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolStringX(vp *map[bool]string, d *Decoder) {
+ v, changed := f.DecMapBoolStringV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolStringV(v map[bool]string, canChange bool,
+ d *Decoder) (_ map[bool]string, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 17)
+ v = make(map[bool]string, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv string
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = ""
+ }
+ continue
+ }
+ mv = dd.DecodeString()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolUintR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]uint)
+ v, changed := fastpathTV.DecMapBoolUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolUintV(rv2i(rv).(map[bool]uint), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolUintX(vp *map[bool]uint, d *Decoder) {
+ v, changed := f.DecMapBoolUintV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolUintV(v map[bool]uint, canChange bool,
+ d *Decoder) (_ map[bool]uint, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[bool]uint, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv uint
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolUint8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]uint8)
+ v, changed := fastpathTV.DecMapBoolUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolUint8V(rv2i(rv).(map[bool]uint8), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolUint8X(vp *map[bool]uint8, d *Decoder) {
+ v, changed := f.DecMapBoolUint8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolUint8V(v map[bool]uint8, canChange bool,
+ d *Decoder) (_ map[bool]uint8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[bool]uint8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv uint8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint8(chkOvf.UintV(dd.DecodeUint64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolUint16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]uint16)
+ v, changed := fastpathTV.DecMapBoolUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolUint16V(rv2i(rv).(map[bool]uint16), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolUint16X(vp *map[bool]uint16, d *Decoder) {
+ v, changed := f.DecMapBoolUint16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolUint16V(v map[bool]uint16, canChange bool,
+ d *Decoder) (_ map[bool]uint16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[bool]uint16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv uint16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint16(chkOvf.UintV(dd.DecodeUint64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolUint32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]uint32)
+ v, changed := fastpathTV.DecMapBoolUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolUint32V(rv2i(rv).(map[bool]uint32), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolUint32X(vp *map[bool]uint32, d *Decoder) {
+ v, changed := f.DecMapBoolUint32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolUint32V(v map[bool]uint32, canChange bool,
+ d *Decoder) (_ map[bool]uint32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[bool]uint32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv uint32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uint32(chkOvf.UintV(dd.DecodeUint64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolUint64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]uint64)
+ v, changed := fastpathTV.DecMapBoolUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolUint64V(rv2i(rv).(map[bool]uint64), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolUint64X(vp *map[bool]uint64, d *Decoder) {
+ v, changed := f.DecMapBoolUint64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolUint64V(v map[bool]uint64, canChange bool,
+ d *Decoder) (_ map[bool]uint64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[bool]uint64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv uint64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeUint64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolUintptrR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]uintptr)
+ v, changed := fastpathTV.DecMapBoolUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolUintptrV(rv2i(rv).(map[bool]uintptr), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolUintptrX(vp *map[bool]uintptr, d *Decoder) {
+ v, changed := f.DecMapBoolUintptrV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolUintptrV(v map[bool]uintptr, canChange bool,
+ d *Decoder) (_ map[bool]uintptr, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[bool]uintptr, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv uintptr
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolIntR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]int)
+ v, changed := fastpathTV.DecMapBoolIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolIntV(rv2i(rv).(map[bool]int), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolIntX(vp *map[bool]int, d *Decoder) {
+ v, changed := f.DecMapBoolIntV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolIntV(v map[bool]int, canChange bool,
+ d *Decoder) (_ map[bool]int, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[bool]int, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv int
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolInt8R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]int8)
+ v, changed := fastpathTV.DecMapBoolInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolInt8V(rv2i(rv).(map[bool]int8), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolInt8X(vp *map[bool]int8, d *Decoder) {
+ v, changed := f.DecMapBoolInt8V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolInt8V(v map[bool]int8, canChange bool,
+ d *Decoder) (_ map[bool]int8, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[bool]int8, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv int8
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int8(chkOvf.IntV(dd.DecodeInt64(), 8))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolInt16R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]int16)
+ v, changed := fastpathTV.DecMapBoolInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolInt16V(rv2i(rv).(map[bool]int16), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolInt16X(vp *map[bool]int16, d *Decoder) {
+ v, changed := f.DecMapBoolInt16V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolInt16V(v map[bool]int16, canChange bool,
+ d *Decoder) (_ map[bool]int16, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 3)
+ v = make(map[bool]int16, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv int16
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int16(chkOvf.IntV(dd.DecodeInt64(), 16))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolInt32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]int32)
+ v, changed := fastpathTV.DecMapBoolInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolInt32V(rv2i(rv).(map[bool]int32), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolInt32X(vp *map[bool]int32, d *Decoder) {
+ v, changed := f.DecMapBoolInt32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolInt32V(v map[bool]int32, canChange bool,
+ d *Decoder) (_ map[bool]int32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[bool]int32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv int32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = int32(chkOvf.IntV(dd.DecodeInt64(), 32))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolInt64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]int64)
+ v, changed := fastpathTV.DecMapBoolInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolInt64V(rv2i(rv).(map[bool]int64), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolInt64X(vp *map[bool]int64, d *Decoder) {
+ v, changed := f.DecMapBoolInt64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolInt64V(v map[bool]int64, canChange bool,
+ d *Decoder) (_ map[bool]int64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[bool]int64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv int64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeInt64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolFloat32R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]float32)
+ v, changed := fastpathTV.DecMapBoolFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolFloat32V(rv2i(rv).(map[bool]float32), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolFloat32X(vp *map[bool]float32, d *Decoder) {
+ v, changed := f.DecMapBoolFloat32V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolFloat32V(v map[bool]float32, canChange bool,
+ d *Decoder) (_ map[bool]float32, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 5)
+ v = make(map[bool]float32, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv float32
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = float32(chkOvf.Float32V(dd.DecodeFloat64()))
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolFloat64R(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]float64)
+ v, changed := fastpathTV.DecMapBoolFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolFloat64V(rv2i(rv).(map[bool]float64), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolFloat64X(vp *map[bool]float64, d *Decoder) {
+ v, changed := f.DecMapBoolFloat64V(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolFloat64V(v map[bool]float64, canChange bool,
+ d *Decoder) (_ map[bool]float64, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 9)
+ v = make(map[bool]float64, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv float64
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = 0
+ }
+ continue
+ }
+ mv = dd.DecodeFloat64()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
+
+func (d *Decoder) fastpathDecMapBoolBoolR(f *codecFnInfo, rv reflect.Value) {
+ if rv.Kind() == reflect.Ptr {
+ vp := rv2i(rv).(*map[bool]bool)
+ v, changed := fastpathTV.DecMapBoolBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+ } else {
+ fastpathTV.DecMapBoolBoolV(rv2i(rv).(map[bool]bool), false, d)
+ }
+}
+func (f fastpathT) DecMapBoolBoolX(vp *map[bool]bool, d *Decoder) {
+ v, changed := f.DecMapBoolBoolV(*vp, true, d)
+ if changed {
+ *vp = v
+ }
+}
+func (_ fastpathT) DecMapBoolBoolV(v map[bool]bool, canChange bool,
+ d *Decoder) (_ map[bool]bool, changed bool) {
+ dd, esep := d.d, d.hh.hasElemSeparators()
+ containerLen := dd.ReadMapStart()
+ if canChange && v == nil {
+ xlen := decInferLen(containerLen, d.h.MaxInitLen, 2)
+ v = make(map[bool]bool, xlen)
+ changed = true
+ }
+ if containerLen == 0 {
+ dd.ReadMapEnd()
+ return v, changed
+ }
+ var mk bool
+ var mv bool
+ hasLen := containerLen > 0
+ for j := 0; (hasLen && j < containerLen) || !(hasLen || dd.CheckBreak()); j++ {
+ if esep {
+ dd.ReadMapElemKey()
+ }
+ mk = dd.DecodeBool()
+ if esep {
+ dd.ReadMapElemValue()
+ }
+ if dd.TryDecodeAsNil() {
+ if v == nil {
+ } else if d.h.DeleteOnNilMapValue {
+ delete(v, mk)
+ } else {
+ v[mk] = false
+ }
+ continue
+ }
+ mv = dd.DecodeBool()
+ if v != nil {
+ v[mk] = mv
+ }
+ }
+ dd.ReadMapEnd()
+ return v, changed
+}
diff --git a/vendor/github.com/ugorji/go/codec/fast-path.not.go b/vendor/github.com/ugorji/go/codec/fast-path.not.go
new file mode 100644
index 00000000..f11b4674
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/fast-path.not.go
@@ -0,0 +1,47 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build notfastpath
+
+package codec
+
+import "reflect"
+
+const fastpathEnabled = false
+
+// The generated fast-path code is very large, and adds a few seconds to the build time.
+// This causes test execution, execution of small tools which use codec, etc
+// to take a long time.
+//
+// To mitigate, we now support the notfastpath tag.
+// This tag disables fastpath during build, allowing for faster build, test execution,
+// short-program runs, etc.
+
+func fastpathDecodeTypeSwitch(iv interface{}, d *Decoder) bool { return false }
+func fastpathEncodeTypeSwitch(iv interface{}, e *Encoder) bool { return false }
+func fastpathEncodeTypeSwitchSlice(iv interface{}, e *Encoder) bool { return false }
+func fastpathEncodeTypeSwitchMap(iv interface{}, e *Encoder) bool { return false }
+func fastpathDecodeSetZeroTypeSwitch(iv interface{}) bool { return false }
+
+type fastpathT struct{}
+type fastpathE struct {
+ rtid uintptr
+ rt reflect.Type
+ encfn func(*Encoder, *codecFnInfo, reflect.Value)
+ decfn func(*Decoder, *codecFnInfo, reflect.Value)
+}
+type fastpathA [0]fastpathE
+
+func (x fastpathA) index(rtid uintptr) int { return -1 }
+
+func (_ fastpathT) DecSliceUint8V(v []uint8, canChange bool, d *Decoder) (_ []uint8, changed bool) {
+ fn := d.cfer().get(uint8SliceTyp, true, true)
+ d.kSlice(&fn.i, reflect.ValueOf(&v).Elem())
+ return v, true
+}
+
+var fastpathAV fastpathA
+var fastpathTV fastpathT
+
+// ----
+type TestMammoth2Wrapper struct{} // to allow testMammoth work in notfastpath mode
diff --git a/vendor/github.com/ugorji/go/codec/gen-helper.generated.go b/vendor/github.com/ugorji/go/codec/gen-helper.generated.go
new file mode 100644
index 00000000..917d2828
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/gen-helper.generated.go
@@ -0,0 +1,335 @@
+/* // +build ignore */
+
+// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// Code generated from gen-helper.go.tmpl - DO NOT EDIT.
+
+package codec
+
+import (
+ "encoding"
+ "reflect"
+)
+
+// GenVersion is the current version of codecgen.
+const GenVersion = 8
+
+// This file is used to generate helper code for codecgen.
+// The values here i.e. genHelper(En|De)coder are not to be used directly by
+// library users. They WILL change continuously and without notice.
+//
+// To help enforce this, we create an unexported type with exported members.
+// The only way to get the type is via the one exported type that we control (somewhat).
+//
+// When static codecs are created for types, they will use this value
+// to perform encoding or decoding of primitives or known slice or map types.
+
+// GenHelperEncoder is exported so that it can be used externally by codecgen.
+//
+// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
+func GenHelperEncoder(e *Encoder) (ge genHelperEncoder, ee genHelperEncDriver) {
+ ge = genHelperEncoder{e: e}
+ ee = genHelperEncDriver{encDriver: e.e}
+ return
+}
+
+// GenHelperDecoder is exported so that it can be used externally by codecgen.
+//
+// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINOUSLY WITHOUT NOTICE.
+func GenHelperDecoder(d *Decoder) (gd genHelperDecoder, dd genHelperDecDriver) {
+ gd = genHelperDecoder{d: d}
+ dd = genHelperDecDriver{decDriver: d.d}
+ return
+}
+
+type genHelperEncDriver struct {
+ encDriver
+}
+
+func (x genHelperEncDriver) EncodeBuiltin(rt uintptr, v interface{}) {}
+func (x genHelperEncDriver) EncStructFieldKey(keyType valueType, s string) {
+ encStructFieldKey(x.encDriver, keyType, s)
+}
+func (x genHelperEncDriver) EncodeSymbol(s string) {
+ x.encDriver.EncodeString(cUTF8, s)
+}
+
+type genHelperDecDriver struct {
+ decDriver
+ C checkOverflow
+}
+
+func (x genHelperDecDriver) DecodeBuiltin(rt uintptr, v interface{}) {}
+func (x genHelperDecDriver) DecStructFieldKey(keyType valueType, buf *[decScratchByteArrayLen]byte) []byte {
+ return decStructFieldKey(x.decDriver, keyType, buf)
+}
+func (x genHelperDecDriver) DecodeInt(bitsize uint8) (i int64) {
+ return x.C.IntV(x.decDriver.DecodeInt64(), bitsize)
+}
+func (x genHelperDecDriver) DecodeUint(bitsize uint8) (ui uint64) {
+ return x.C.UintV(x.decDriver.DecodeUint64(), bitsize)
+}
+func (x genHelperDecDriver) DecodeFloat(chkOverflow32 bool) (f float64) {
+ f = x.DecodeFloat64()
+ if chkOverflow32 && chkOvf.Float32(f) {
+ panicv.errorf("float32 overflow: %v", f)
+ }
+ return
+}
+func (x genHelperDecDriver) DecodeFloat32As64() (f float64) {
+ f = x.DecodeFloat64()
+ if chkOvf.Float32(f) {
+ panicv.errorf("float32 overflow: %v", f)
+ }
+ return
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+type genHelperEncoder struct {
+ M must
+ e *Encoder
+ F fastpathT
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+type genHelperDecoder struct {
+ C checkOverflow
+ d *Decoder
+ F fastpathT
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncBasicHandle() *BasicHandle {
+ return f.e.h
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncBinary() bool {
+ return f.e.be // f.e.hh.isBinaryEncoding()
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) IsJSONHandle() bool {
+ return f.e.js
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncFallback(iv interface{}) {
+ // println(">>>>>>>>> EncFallback")
+ // f.e.encodeI(iv, false, false)
+ f.e.encodeValue(reflect.ValueOf(iv), nil, false)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncTextMarshal(iv encoding.TextMarshaler) {
+ bs, fnerr := iv.MarshalText()
+ f.e.marshal(bs, fnerr, false, cUTF8)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncJSONMarshal(iv jsonMarshaler) {
+ bs, fnerr := iv.MarshalJSON()
+ f.e.marshal(bs, fnerr, true, cUTF8)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncBinaryMarshal(iv encoding.BinaryMarshaler) {
+ bs, fnerr := iv.MarshalBinary()
+ f.e.marshal(bs, fnerr, false, cRAW)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncRaw(iv Raw) { f.e.rawBytes(iv) }
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: builtin no longer supported - so we make this method a no-op,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperEncoder) TimeRtidIfBinc() (v uintptr) { return }
+
+// func (f genHelperEncoder) TimeRtidIfBinc() uintptr {
+// if _, ok := f.e.hh.(*BincHandle); ok {
+// return timeTypId
+// }
+// }
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) I2Rtid(v interface{}) uintptr {
+ return i2rtid(v)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) Extension(rtid uintptr) (xfn *extTypeTagFn) {
+ return f.e.h.getExt(rtid)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperEncoder) EncExtension(v interface{}, xfFn *extTypeTagFn) {
+ f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperEncoder) HasExtensions() bool {
+ return len(f.e.h.extHandle) != 0
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperEncoder) EncExt(v interface{}) (r bool) {
+ if xfFn := f.e.h.getExt(i2rtid(v)); xfFn != nil {
+ f.e.e.EncodeExt(v, xfFn.tag, xfFn.ext, f.e)
+ return true
+ }
+ return false
+}
+
+// ---------------- DECODER FOLLOWS -----------------
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecBasicHandle() *BasicHandle {
+ return f.d.h
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecBinary() bool {
+ return f.d.be // f.d.hh.isBinaryEncoding()
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecSwallow() { f.d.swallow() }
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecScratchBuffer() []byte {
+ return f.d.b[:]
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecScratchArrayBuffer() *[decScratchByteArrayLen]byte {
+ return &f.d.b
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecFallback(iv interface{}, chkPtr bool) {
+ // println(">>>>>>>>> DecFallback")
+ rv := reflect.ValueOf(iv)
+ if chkPtr {
+ rv = f.d.ensureDecodeable(rv)
+ }
+ f.d.decodeValue(rv, nil, false)
+ // f.d.decodeValueFallback(rv)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecSliceHelperStart() (decSliceHelper, int) {
+ return f.d.decSliceHelperStart()
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecStructFieldNotFound(index int, name string) {
+ f.d.structFieldNotFound(index, name)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecArrayCannotExpand(sliceLen, streamLen int) {
+ f.d.arrayCannotExpand(sliceLen, streamLen)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecTextUnmarshal(tm encoding.TextUnmarshaler) {
+ fnerr := tm.UnmarshalText(f.d.d.DecodeStringAsBytes())
+ if fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecJSONUnmarshal(tm jsonUnmarshaler) {
+ // bs := f.dd.DecodeStringAsBytes()
+ // grab the bytes to be read, as UnmarshalJSON needs the full JSON so as to unmarshal it itself.
+ fnerr := tm.UnmarshalJSON(f.d.nextValueBytes())
+ if fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecBinaryUnmarshal(bm encoding.BinaryUnmarshaler) {
+ fnerr := bm.UnmarshalBinary(f.d.d.DecodeBytes(nil, true))
+ if fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecRaw() []byte { return f.d.rawBytes() }
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: builtin no longer supported - so we make this method a no-op,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperDecoder) TimeRtidIfBinc() (v uintptr) { return }
+
+// func (f genHelperDecoder) TimeRtidIfBinc() uintptr {
+// // Note: builtin is no longer supported - so make this a no-op
+// if _, ok := f.d.hh.(*BincHandle); ok {
+// return timeTypId
+// }
+// return 0
+// }
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) IsJSONHandle() bool {
+ return f.d.js
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) I2Rtid(v interface{}) uintptr {
+ return i2rtid(v)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) Extension(rtid uintptr) (xfn *extTypeTagFn) {
+ return f.d.h.getExt(rtid)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecExtension(v interface{}, xfFn *extTypeTagFn) {
+ f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperDecoder) HasExtensions() bool {
+ return len(f.d.h.extHandle) != 0
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: No longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperDecoder) DecExt(v interface{}) (r bool) {
+ if xfFn := f.d.h.getExt(i2rtid(v)); xfFn != nil {
+ f.d.d.DecodeExt(v, xfFn.tag, xfFn.ext)
+ return true
+ }
+ return false
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+func (f genHelperDecoder) DecInferLen(clen, maxlen, unit int) (rvlen int) {
+ return decInferLen(clen, maxlen, unit)
+}
+
+// FOR USE BY CODECGEN ONLY. IT *WILL* CHANGE WITHOUT NOTICE. *DO NOT USE*
+//
+// Deprecated: no longer used,
+// but leave in-place so that old generated files continue to work without regeneration.
+func (f genHelperDecoder) StringView(v []byte) string { return stringView(v) }
diff --git a/vendor/github.com/ugorji/go/codec/gen.generated.go b/vendor/github.com/ugorji/go/codec/gen.generated.go
new file mode 100644
index 00000000..240ba9f8
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/gen.generated.go
@@ -0,0 +1,164 @@
+// +build codecgen.exec
+
+// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+// DO NOT EDIT. THIS FILE IS AUTO-GENERATED FROM gen-dec-(map|array).go.tmpl
+
+const genDecMapTmpl = `
+{{var "v"}} := *{{ .Varname }}
+{{var "l"}} := r.ReadMapStart()
+{{var "bh"}} := z.DecBasicHandle()
+if {{var "v"}} == nil {
+ {{var "rl"}} := z.DecInferLen({{var "l"}}, {{var "bh"}}.MaxInitLen, {{ .Size }})
+ {{var "v"}} = make(map[{{ .KTyp }}]{{ .Typ }}, {{var "rl"}})
+ *{{ .Varname }} = {{var "v"}}
+}
+var {{var "mk"}} {{ .KTyp }}
+var {{var "mv"}} {{ .Typ }}
+var {{var "mg"}}, {{var "mdn"}} {{if decElemKindPtr}}, {{var "ms"}}, {{var "mok"}}{{end}} bool
+if {{var "bh"}}.MapValueReset {
+ {{if decElemKindPtr}}{{var "mg"}} = true
+ {{else if decElemKindIntf}}if !{{var "bh"}}.InterfaceReset { {{var "mg"}} = true }
+ {{else if not decElemKindImmutable}}{{var "mg"}} = true
+ {{end}} }
+if {{var "l"}} != 0 {
+{{var "hl"}} := {{var "l"}} > 0
+ for {{var "j"}} := 0; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
+ r.ReadMapElemKey() {{/* z.DecSendContainerState(codecSelfer_containerMapKey{{ .Sfx }}) */}}
+ {{ $x := printf "%vmk%v" .TempVar .Rand }}{{ decLineVarK $x }}
+{{ if eq .KTyp "interface{}" }}{{/* // special case if a byte array. */}}if {{var "bv"}}, {{var "bok"}} := {{var "mk"}}.([]byte); {{var "bok"}} {
+ {{var "mk"}} = string({{var "bv"}})
+ }{{ end }}{{if decElemKindPtr}}
+ {{var "ms"}} = true{{end}}
+ if {{var "mg"}} {
+ {{if decElemKindPtr}}{{var "mv"}}, {{var "mok"}} = {{var "v"}}[{{var "mk"}}]
+ if {{var "mok"}} {
+ {{var "ms"}} = false
+ } {{else}}{{var "mv"}} = {{var "v"}}[{{var "mk"}}] {{end}}
+ } {{if not decElemKindImmutable}}else { {{var "mv"}} = {{decElemZero}} }{{end}}
+ r.ReadMapElemValue() {{/* z.DecSendContainerState(codecSelfer_containerMapValue{{ .Sfx }}) */}}
+ {{var "mdn"}} = false
+ {{ $x := printf "%vmv%v" .TempVar .Rand }}{{ $y := printf "%vmdn%v" .TempVar .Rand }}{{ decLineVar $x $y }}
+ if {{var "mdn"}} {
+ if {{ var "bh" }}.DeleteOnNilMapValue { delete({{var "v"}}, {{var "mk"}}) } else { {{var "v"}}[{{var "mk"}}] = {{decElemZero}} }
+ } else if {{if decElemKindPtr}} {{var "ms"}} && {{end}} {{var "v"}} != nil {
+ {{var "v"}}[{{var "mk"}}] = {{var "mv"}}
+ }
+}
+} // else len==0: TODO: Should we clear map entries?
+r.ReadMapEnd() {{/* z.DecSendContainerState(codecSelfer_containerMapEnd{{ .Sfx }}) */}}
+`
+
+const genDecListTmpl = `
+{{var "v"}} := {{if not isArray}}*{{end}}{{ .Varname }}
+{{var "h"}}, {{var "l"}} := z.DecSliceHelperStart() {{/* // helper, containerLenS */}}{{if not isArray}}
+var {{var "c"}} bool {{/* // changed */}}
+_ = {{var "c"}}{{end}}
+if {{var "l"}} == 0 {
+ {{if isSlice }}if {{var "v"}} == nil {
+ {{var "v"}} = []{{ .Typ }}{}
+ {{var "c"}} = true
+ } else if len({{var "v"}}) != 0 {
+ {{var "v"}} = {{var "v"}}[:0]
+ {{var "c"}} = true
+ } {{else if isChan }}if {{var "v"}} == nil {
+ {{var "v"}} = make({{ .CTyp }}, 0)
+ {{var "c"}} = true
+ } {{end}}
+} else {
+ {{var "hl"}} := {{var "l"}} > 0
+ var {{var "rl"}} int
+ _ = {{var "rl"}}
+ {{if isSlice }} if {{var "hl"}} {
+ if {{var "l"}} > cap({{var "v"}}) {
+ {{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
+ if {{var "rl"}} <= cap({{var "v"}}) {
+ {{var "v"}} = {{var "v"}}[:{{var "rl"}}]
+ } else {
+ {{var "v"}} = make([]{{ .Typ }}, {{var "rl"}})
+ }
+ {{var "c"}} = true
+ } else if {{var "l"}} != len({{var "v"}}) {
+ {{var "v"}} = {{var "v"}}[:{{var "l"}}]
+ {{var "c"}} = true
+ }
+ } {{end}}
+ var {{var "j"}} int
+ // var {{var "dn"}} bool
+ for ; ({{var "hl"}} && {{var "j"}} < {{var "l"}}) || !({{var "hl"}} || r.CheckBreak()); {{var "j"}}++ {
+ {{if not isArray}} if {{var "j"}} == 0 && {{var "v"}} == nil {
+ if {{var "hl"}} {
+ {{var "rl"}} = z.DecInferLen({{var "l"}}, z.DecBasicHandle().MaxInitLen, {{ .Size }})
+ } else {
+ {{var "rl"}} = {{if isSlice}}8{{else if isChan}}64{{end}}
+ }
+ {{var "v"}} = make({{if isSlice}}[]{{ .Typ }}{{else if isChan}}{{.CTyp}}{{end}}, {{var "rl"}})
+ {{var "c"}} = true
+ }{{end}}
+ {{var "h"}}.ElemContainerState({{var "j"}})
+ {{/* {{var "dn"}} = r.TryDecodeAsNil() */}}{{/* commented out, as decLineVar handles this already each time */}}
+ {{if isChan}}{{ $x := printf "%[1]vvcx%[2]v" .TempVar .Rand }}var {{$x}} {{ .Typ }}
+ {{ decLineVar $x }}
+ {{var "v"}} <- {{ $x }}
+ // println(">>>> sending ", {{ $x }}, " into ", {{var "v"}}) // TODO: remove this
+ {{else}}{{/* // if indefinite, etc, then expand the slice if necessary */}}
+ var {{var "db"}} bool
+ if {{var "j"}} >= len({{var "v"}}) {
+ {{if isSlice }} {{var "v"}} = append({{var "v"}}, {{ zero }})
+ {{var "c"}} = true
+ {{else}} z.DecArrayCannotExpand(len(v), {{var "j"}}+1); {{var "db"}} = true
+ {{end}}
+ }
+ if {{var "db"}} {
+ z.DecSwallow()
+ } else {
+ {{ $x := printf "%[1]vv%[2]v[%[1]vj%[2]v]" .TempVar .Rand }}{{ decLineVar $x }}
+ }
+ {{end}}
+ }
+ {{if isSlice}} if {{var "j"}} < len({{var "v"}}) {
+ {{var "v"}} = {{var "v"}}[:{{var "j"}}]
+ {{var "c"}} = true
+ } else if {{var "j"}} == 0 && {{var "v"}} == nil {
+ {{var "v"}} = make([]{{ .Typ }}, 0)
+ {{var "c"}} = true
+ } {{end}}
+}
+{{var "h"}}.End()
+{{if not isArray }}if {{var "c"}} {
+ *{{ .Varname }} = {{var "v"}}
+}{{end}}
+`
+
+const genEncChanTmpl = `
+{{.Label}}:
+switch timeout{{.Sfx}} := z.EncBasicHandle().ChanRecvTimeout; {
+case timeout{{.Sfx}} == 0: // only consume available
+ for {
+ select {
+ case b{{.Sfx}} := <-{{.Chan}}:
+ {{ .Slice }} = append({{.Slice}}, b{{.Sfx}})
+ default:
+ break {{.Label}}
+ }
+ }
+case timeout{{.Sfx}} > 0: // consume until timeout
+ tt{{.Sfx}} := time.NewTimer(timeout{{.Sfx}})
+ for {
+ select {
+ case b{{.Sfx}} := <-{{.Chan}}:
+ {{.Slice}} = append({{.Slice}}, b{{.Sfx}})
+ case <-tt{{.Sfx}}.C:
+ // close(tt.C)
+ break {{.Label}}
+ }
+ }
+default: // consume until close
+ for b{{.Sfx}} := range {{.Chan}} {
+ {{.Slice}} = append({{.Slice}}, b{{.Sfx}})
+ }
+}
+`
diff --git a/vendor/github.com/ugorji/go/codec/gen.go b/vendor/github.com/ugorji/go/codec/gen.go
new file mode 100644
index 00000000..b4c4031f
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/gen.go
@@ -0,0 +1,2139 @@
+// +build codecgen.exec
+
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "bytes"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "text/template"
+ "time"
+ "unicode"
+ "unicode/utf8"
+)
+
+// ---------------------------------------------------
+// codecgen supports the full cycle of reflection-based codec:
+// - RawExt
+// - Raw
+// - Extensions
+// - (Binary|Text|JSON)(Unm|M)arshal
+// - generic by-kind
+//
+// This means that, for dynamic things, we MUST use reflection to at least get the reflect.Type.
+// In those areas, we try to only do reflection or interface-conversion when NECESSARY:
+// - Extensions, only if Extensions are configured.
+//
+// However, codecgen doesn't support the following:
+// - Canonical option. (codecgen IGNORES it currently)
+// This is just because it has not been implemented.
+//
+// During encode/decode, Selfer takes precedence.
+// A type implementing Selfer will know how to encode/decode itself statically.
+//
+// The following field types are supported:
+// array: [n]T
+// slice: []T
+// map: map[K]V
+// primitive: [u]int[n], float(32|64), bool, string
+// struct
+//
+// ---------------------------------------------------
+// Note that a Selfer cannot call (e|d).(En|De)code on itself,
+// as this will cause a circular reference, as (En|De)code will call Selfer methods.
+// Any type that implements Selfer must implement completely and not fallback to (En|De)code.
+//
+// In addition, code in this file manages the generation of fast-path implementations of
+// encode/decode of slices/maps of primitive keys/values.
+//
+// Users MUST re-generate their implementations whenever the code shape changes.
+// The generated code will panic if it was generated with a version older than the supporting library.
+// ---------------------------------------------------
+//
+// codec framework is very feature rich.
+// When encoding or decoding into an interface, it depends on the runtime type of the interface.
+// The type of the interface may be a named type, an extension, etc.
+// Consequently, we fallback to runtime codec for encoding/decoding interfaces.
+// In addition, we fallback for any value which cannot be guaranteed at runtime.
+// This allows us support ANY value, including any named types, specifically those which
+// do not implement our interfaces (e.g. Selfer).
+//
+// This explains some slowness compared to other code generation codecs (e.g. msgp).
+// This reduction in speed is only seen when your refers to interfaces,
+// e.g. type T struct { A interface{}; B []interface{}; C map[string]interface{} }
+//
+// codecgen will panic if the file was generated with an old version of the library in use.
+//
+// Note:
+// It was a conscious decision to have gen.go always explicitly call EncodeNil or TryDecodeAsNil.
+// This way, there isn't a function call overhead just to see that we should not enter a block of code.
+//
+// Note:
+// codecgen-generated code depends on the variables defined by fast-path.generated.go.
+// consequently, you cannot run with tags "codecgen notfastpath".
+
+// GenVersion is the current version of codecgen.
+//
+// NOTE: Increment this value each time codecgen changes fundamentally.
+// Fundamental changes are:
+// - helper methods change (signature change, new ones added, some removed, etc)
+// - codecgen command line changes
+//
+// v1: Initial Version
+// v2:
+// v3: Changes for Kubernetes:
+// changes in signature of some unpublished helper methods and codecgen cmdline arguments.
+// v4: Removed separator support from (en|de)cDriver, and refactored codec(gen)
+// v5: changes to support faster json decoding. Let encoder/decoder maintain state of collections.
+// v6: removed unsafe from gen, and now uses codecgen.exec tag
+// v7:
+// v8: current - we now maintain compatibility with old generated code.
+const genVersion = 8
+
+const (
+ genCodecPkg = "codec1978"
+ genTempVarPfx = "yy"
+ genTopLevelVarName = "x"
+
+ // ignore canBeNil parameter, and always set to true.
+ // This is because nil can appear anywhere, so we should always check.
+ genAnythingCanBeNil = true
+
+ // if genUseOneFunctionForDecStructMap, make a single codecDecodeSelferFromMap function;
+ // else make codecDecodeSelferFromMap{LenPrefix,CheckBreak} so that conditionals
+ // are not executed a lot.
+ //
+ // From testing, it didn't make much difference in runtime, so keep as true (one function only)
+ genUseOneFunctionForDecStructMap = true
+)
+
+type genStructMapStyle uint8
+
+const (
+ genStructMapStyleConsolidated genStructMapStyle = iota
+ genStructMapStyleLenPrefix
+ genStructMapStyleCheckBreak
+)
+
+var (
+ errGenAllTypesSamePkg = errors.New("All types must be in the same package")
+ errGenExpectArrayOrMap = errors.New("unexpected type. Expecting array/map/slice")
+
+ genBase64enc = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789__")
+ genQNameRegex = regexp.MustCompile(`[A-Za-z_.]+`)
+)
+
+type genBuf struct {
+ buf []byte
+}
+
+func (x *genBuf) s(s string) *genBuf { x.buf = append(x.buf, s...); return x }
+func (x *genBuf) b(s []byte) *genBuf { x.buf = append(x.buf, s...); return x }
+func (x *genBuf) v() string { return string(x.buf) }
+func (x *genBuf) f(s string, args ...interface{}) { x.s(fmt.Sprintf(s, args...)) }
+func (x *genBuf) reset() {
+ if x.buf != nil {
+ x.buf = x.buf[:0]
+ }
+}
+
+// genRunner holds some state used during a Gen run.
+type genRunner struct {
+ w io.Writer // output
+ c uint64 // counter used for generating varsfx
+ t []reflect.Type // list of types to run selfer on
+
+ tc reflect.Type // currently running selfer on this type
+ te map[uintptr]bool // types for which the encoder has been created
+ td map[uintptr]bool // types for which the decoder has been created
+ cp string // codec import path
+
+ im map[string]reflect.Type // imports to add
+ imn map[string]string // package names of imports to add
+ imc uint64 // counter for import numbers
+
+ is map[reflect.Type]struct{} // types seen during import search
+ bp string // base PkgPath, for which we are generating for
+
+ cpfx string // codec package prefix
+
+ tm map[reflect.Type]struct{} // types for which enc/dec must be generated
+ ts []reflect.Type // types for which enc/dec must be generated
+
+ xs string // top level variable/constant suffix
+ hn string // fn helper type name
+
+ ti *TypeInfos
+ // rr *rand.Rand // random generator for file-specific types
+
+ nx bool // no extensions
+}
+
+// Gen will write a complete go file containing Selfer implementations for each
+// type passed. All the types must be in the same package.
+//
+// Library users: DO NOT USE IT DIRECTLY. IT WILL CHANGE CONTINUOUSLY WITHOUT NOTICE.
+func Gen(w io.Writer, buildTags, pkgName, uid string, noExtensions bool,
+ ti *TypeInfos, typ ...reflect.Type) {
+ // All types passed to this method do not have a codec.Selfer method implemented directly.
+ // codecgen already checks the AST and skips any types that define the codec.Selfer methods.
+ // Consequently, there's no need to check and trim them if they implement codec.Selfer
+
+ if len(typ) == 0 {
+ return
+ }
+ x := genRunner{
+ w: w,
+ t: typ,
+ te: make(map[uintptr]bool),
+ td: make(map[uintptr]bool),
+ im: make(map[string]reflect.Type),
+ imn: make(map[string]string),
+ is: make(map[reflect.Type]struct{}),
+ tm: make(map[reflect.Type]struct{}),
+ ts: []reflect.Type{},
+ bp: genImportPath(typ[0]),
+ xs: uid,
+ ti: ti,
+ nx: noExtensions,
+ }
+ if x.ti == nil {
+ x.ti = defTypeInfos
+ }
+ if x.xs == "" {
+ rr := rand.New(rand.NewSource(time.Now().UnixNano()))
+ x.xs = strconv.FormatInt(rr.Int63n(9999), 10)
+ }
+
+ // gather imports first:
+ x.cp = genImportPath(reflect.TypeOf(x))
+ x.imn[x.cp] = genCodecPkg
+ for _, t := range typ {
+ // fmt.Printf("###########: PkgPath: '%v', Name: '%s'\n", genImportPath(t), t.Name())
+ if genImportPath(t) != x.bp {
+ panic(errGenAllTypesSamePkg)
+ }
+ x.genRefPkgs(t)
+ }
+ if buildTags != "" {
+ x.line("// +build " + buildTags)
+ x.line("")
+ }
+ x.line(`
+
+// Code generated by codecgen - DO NOT EDIT.
+
+`)
+ x.line("package " + pkgName)
+ x.line("")
+ x.line("import (")
+ if x.cp != x.bp {
+ x.cpfx = genCodecPkg + "."
+ x.linef("%s \"%s\"", genCodecPkg, x.cp)
+ }
+ // use a sorted set of im keys, so that we can get consistent output
+ imKeys := make([]string, 0, len(x.im))
+ for k := range x.im {
+ imKeys = append(imKeys, k)
+ }
+ sort.Strings(imKeys)
+ for _, k := range imKeys { // for k, _ := range x.im {
+ if k == x.imn[k] {
+ x.linef("\"%s\"", k)
+ } else {
+ x.linef("%s \"%s\"", x.imn[k], k)
+ }
+ }
+ // add required packages
+ for _, k := range [...]string{"runtime", "errors", "strconv"} { // "reflect", "fmt"
+ if _, ok := x.im[k]; !ok {
+ x.line("\"" + k + "\"")
+ }
+ }
+ x.line(")")
+ x.line("")
+
+ x.line("const (")
+ x.linef("// ----- content types ----")
+ x.linef("codecSelferCcUTF8%s = %v", x.xs, int64(cUTF8))
+ x.linef("codecSelferCcRAW%s = %v", x.xs, int64(cRAW))
+ x.linef("// ----- value types used ----")
+ for _, vt := range [...]valueType{
+ valueTypeArray, valueTypeMap, valueTypeString,
+ valueTypeInt, valueTypeUint, valueTypeFloat} {
+ x.linef("codecSelferValueType%s%s = %v", vt.String(), x.xs, int64(vt))
+ }
+
+ x.linef("codecSelferBitsize%s = uint8(32 << (^uint(0) >> 63))", x.xs)
+ x.line(")")
+ x.line("var (")
+ x.line("errCodecSelferOnlyMapOrArrayEncodeToStruct" + x.xs + " = errors.New(`only encoded map or array can be decoded into a struct`)")
+ x.line(")")
+ x.line("")
+
+ x.hn = "codecSelfer" + x.xs
+ x.line("type " + x.hn + " struct{}")
+ x.line("")
+
+ x.varsfxreset()
+ x.line("func init() {")
+ x.linef("if %sGenVersion != %v {", x.cpfx, genVersion)
+ x.line("_, file, _, _ := runtime.Caller(0)")
+ x.outf(`panic("codecgen version mismatch: current: %v, need " + strconv.FormatInt(int64(%sGenVersion), 10) + ". Re-generate file: " + file)`, genVersion, x.cpfx)
+ // x.out(`panic(fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v", `)
+ // x.linef(`%v, %sGenVersion, file))`, genVersion, x.cpfx)
+ x.linef("}")
+ x.line("if false { // reference the types, but skip this branch at build/run time")
+ // x.line("_ = strconv.ParseInt")
+ var n int
+ // for k, t := range x.im {
+ for _, k := range imKeys {
+ t := x.im[k]
+ x.linef("var v%v %s.%s", n, x.imn[k], t.Name())
+ n++
+ }
+ if n > 0 {
+ x.out("_")
+ for i := 1; i < n; i++ {
+ x.out(", _")
+ }
+ x.out(" = v0")
+ for i := 1; i < n; i++ {
+ x.outf(", v%v", i)
+ }
+ }
+ x.line("} ") // close if false
+ x.line("}") // close init
+ x.line("")
+
+ // generate rest of type info
+ for _, t := range typ {
+ x.tc = t
+ x.selfer(true)
+ x.selfer(false)
+ }
+
+ for _, t := range x.ts {
+ rtid := rt2id(t)
+ // generate enc functions for all these slice/map types.
+ x.varsfxreset()
+ x.linef("func (x %s) enc%s(v %s%s, e *%sEncoder) {", x.hn, x.genMethodNameT(t), x.arr2str(t, "*"), x.genTypeName(t), x.cpfx)
+ x.genRequiredMethodVars(true)
+ switch t.Kind() {
+ case reflect.Array, reflect.Slice, reflect.Chan:
+ x.encListFallback("v", t)
+ case reflect.Map:
+ x.encMapFallback("v", t)
+ default:
+ panic(errGenExpectArrayOrMap)
+ }
+ x.line("}")
+ x.line("")
+
+ // generate dec functions for all these slice/map types.
+ x.varsfxreset()
+ x.linef("func (x %s) dec%s(v *%s, d *%sDecoder) {", x.hn, x.genMethodNameT(t), x.genTypeName(t), x.cpfx)
+ x.genRequiredMethodVars(false)
+ switch t.Kind() {
+ case reflect.Array, reflect.Slice, reflect.Chan:
+ x.decListFallback("v", rtid, t)
+ case reflect.Map:
+ x.decMapFallback("v", rtid, t)
+ default:
+ panic(errGenExpectArrayOrMap)
+ }
+ x.line("}")
+ x.line("")
+ }
+
+ x.line("")
+}
+
+func (x *genRunner) checkForSelfer(t reflect.Type, varname string) bool {
+ // return varname != genTopLevelVarName && t != x.tc
+ // the only time we checkForSelfer is if we are not at the TOP of the generated code.
+ return varname != genTopLevelVarName
+}
+
+func (x *genRunner) arr2str(t reflect.Type, s string) string {
+ if t.Kind() == reflect.Array {
+ return s
+ }
+ return ""
+}
+
+func (x *genRunner) genRequiredMethodVars(encode bool) {
+ x.line("var h " + x.hn)
+ if encode {
+ x.line("z, r := " + x.cpfx + "GenHelperEncoder(e)")
+ } else {
+ x.line("z, r := " + x.cpfx + "GenHelperDecoder(d)")
+ }
+ x.line("_, _, _ = h, z, r")
+}
+
+func (x *genRunner) genRefPkgs(t reflect.Type) {
+ if _, ok := x.is[t]; ok {
+ return
+ }
+ x.is[t] = struct{}{}
+ tpkg, tname := genImportPath(t), t.Name()
+ if tpkg != "" && tpkg != x.bp && tpkg != x.cp && tname != "" && tname[0] >= 'A' && tname[0] <= 'Z' {
+ if _, ok := x.im[tpkg]; !ok {
+ x.im[tpkg] = t
+ if idx := strings.LastIndex(tpkg, "/"); idx < 0 {
+ x.imn[tpkg] = tpkg
+ } else {
+ x.imc++
+ x.imn[tpkg] = "pkg" + strconv.FormatUint(x.imc, 10) + "_" + genGoIdentifier(tpkg[idx+1:], false)
+ }
+ }
+ }
+ switch t.Kind() {
+ case reflect.Array, reflect.Slice, reflect.Ptr, reflect.Chan:
+ x.genRefPkgs(t.Elem())
+ case reflect.Map:
+ x.genRefPkgs(t.Elem())
+ x.genRefPkgs(t.Key())
+ case reflect.Struct:
+ for i := 0; i < t.NumField(); i++ {
+ if fname := t.Field(i).Name; fname != "" && fname[0] >= 'A' && fname[0] <= 'Z' {
+ x.genRefPkgs(t.Field(i).Type)
+ }
+ }
+ }
+}
+
+func (x *genRunner) varsfx() string {
+ x.c++
+ return strconv.FormatUint(x.c, 10)
+}
+
+func (x *genRunner) varsfxreset() {
+ x.c = 0
+}
+
+func (x *genRunner) out(s string) {
+ _, err := io.WriteString(x.w, s)
+ if err != nil {
+ panic(err)
+ }
+}
+
+func (x *genRunner) outf(s string, params ...interface{}) {
+ _, err := fmt.Fprintf(x.w, s, params...)
+ if err != nil {
+ panic(err)
+ }
+}
+
+func (x *genRunner) line(s string) {
+ x.out(s)
+ if len(s) == 0 || s[len(s)-1] != '\n' {
+ x.out("\n")
+ }
+}
+
+func (x *genRunner) linef(s string, params ...interface{}) {
+ x.outf(s, params...)
+ if len(s) == 0 || s[len(s)-1] != '\n' {
+ x.out("\n")
+ }
+}
+
+func (x *genRunner) genTypeName(t reflect.Type) (n string) {
+ // defer func() { fmt.Printf(">>>> ####: genTypeName: t: %v, name: '%s'\n", t, n) }()
+
+ // if the type has a PkgPath, which doesn't match the current package,
+ // then include it.
+ // We cannot depend on t.String() because it includes current package,
+ // or t.PkgPath because it includes full import path,
+ //
+ var ptrPfx string
+ for t.Kind() == reflect.Ptr {
+ ptrPfx += "*"
+ t = t.Elem()
+ }
+ if tn := t.Name(); tn != "" {
+ return ptrPfx + x.genTypeNamePrim(t)
+ }
+ switch t.Kind() {
+ case reflect.Map:
+ return ptrPfx + "map[" + x.genTypeName(t.Key()) + "]" + x.genTypeName(t.Elem())
+ case reflect.Slice:
+ return ptrPfx + "[]" + x.genTypeName(t.Elem())
+ case reflect.Array:
+ return ptrPfx + "[" + strconv.FormatInt(int64(t.Len()), 10) + "]" + x.genTypeName(t.Elem())
+ case reflect.Chan:
+ return ptrPfx + t.ChanDir().String() + " " + x.genTypeName(t.Elem())
+ default:
+ if t == intfTyp {
+ return ptrPfx + "interface{}"
+ } else {
+ return ptrPfx + x.genTypeNamePrim(t)
+ }
+ }
+}
+
+func (x *genRunner) genTypeNamePrim(t reflect.Type) (n string) {
+ if t.Name() == "" {
+ return t.String()
+ } else if genImportPath(t) == "" || genImportPath(t) == genImportPath(x.tc) {
+ return t.Name()
+ } else {
+ return x.imn[genImportPath(t)] + "." + t.Name()
+ // return t.String() // best way to get the package name inclusive
+ }
+}
+
+func (x *genRunner) genZeroValueR(t reflect.Type) string {
+ // if t is a named type, w
+ switch t.Kind() {
+ case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func,
+ reflect.Slice, reflect.Map, reflect.Invalid:
+ return "nil"
+ case reflect.Bool:
+ return "false"
+ case reflect.String:
+ return `""`
+ case reflect.Struct, reflect.Array:
+ return x.genTypeName(t) + "{}"
+ default: // all numbers
+ return "0"
+ }
+}
+
+func (x *genRunner) genMethodNameT(t reflect.Type) (s string) {
+ return genMethodNameT(t, x.tc)
+}
+
+func (x *genRunner) selfer(encode bool) {
+ t := x.tc
+ t0 := t
+ // always make decode use a pointer receiver,
+ // and structs/arrays always use a ptr receiver (encode|decode)
+ isptr := !encode || t.Kind() == reflect.Array || (t.Kind() == reflect.Struct && t != timeTyp)
+ x.varsfxreset()
+
+ fnSigPfx := "func (" + genTopLevelVarName + " "
+ if isptr {
+ fnSigPfx += "*"
+ }
+ fnSigPfx += x.genTypeName(t)
+ x.out(fnSigPfx)
+
+ if isptr {
+ t = reflect.PtrTo(t)
+ }
+ if encode {
+ x.line(") CodecEncodeSelf(e *" + x.cpfx + "Encoder) {")
+ x.genRequiredMethodVars(true)
+ x.encVar(genTopLevelVarName, t)
+ } else {
+ x.line(") CodecDecodeSelf(d *" + x.cpfx + "Decoder) {")
+ x.genRequiredMethodVars(false)
+ // do not use decVar, as there is no need to check TryDecodeAsNil
+ // or way to elegantly handle that, and also setting it to a
+ // non-nil value doesn't affect the pointer passed.
+ // x.decVar(genTopLevelVarName, t, false)
+ x.dec(genTopLevelVarName, t0, true)
+ }
+ x.line("}")
+ x.line("")
+
+ if encode || t0.Kind() != reflect.Struct {
+ return
+ }
+
+ // write is containerMap
+ if genUseOneFunctionForDecStructMap {
+ x.out(fnSigPfx)
+ x.line(") codecDecodeSelfFromMap(l int, d *" + x.cpfx + "Decoder) {")
+ x.genRequiredMethodVars(false)
+ x.decStructMap(genTopLevelVarName, "l", rt2id(t0), t0, genStructMapStyleConsolidated)
+ x.line("}")
+ x.line("")
+ } else {
+ x.out(fnSigPfx)
+ x.line(") codecDecodeSelfFromMapLenPrefix(l int, d *" + x.cpfx + "Decoder) {")
+ x.genRequiredMethodVars(false)
+ x.decStructMap(genTopLevelVarName, "l", rt2id(t0), t0, genStructMapStyleLenPrefix)
+ x.line("}")
+ x.line("")
+
+ x.out(fnSigPfx)
+ x.line(") codecDecodeSelfFromMapCheckBreak(l int, d *" + x.cpfx + "Decoder) {")
+ x.genRequiredMethodVars(false)
+ x.decStructMap(genTopLevelVarName, "l", rt2id(t0), t0, genStructMapStyleCheckBreak)
+ x.line("}")
+ x.line("")
+ }
+
+ // write containerArray
+ x.out(fnSigPfx)
+ x.line(") codecDecodeSelfFromArray(l int, d *" + x.cpfx + "Decoder) {")
+ x.genRequiredMethodVars(false)
+ x.decStructArray(genTopLevelVarName, "l", "return", rt2id(t0), t0)
+ x.line("}")
+ x.line("")
+
+}
+
+// used for chan, array, slice, map
+func (x *genRunner) xtraSM(varname string, t reflect.Type, encode, isptr bool) {
+ var ptrPfx, addrPfx string
+ if isptr {
+ ptrPfx = "*"
+ } else {
+ addrPfx = "&"
+ }
+ if encode {
+ x.linef("h.enc%s((%s%s)(%s), e)", x.genMethodNameT(t), ptrPfx, x.genTypeName(t), varname)
+ } else {
+ x.linef("h.dec%s((*%s)(%s%s), d)", x.genMethodNameT(t), x.genTypeName(t), addrPfx, varname)
+ }
+ x.registerXtraT(t)
+}
+
+func (x *genRunner) registerXtraT(t reflect.Type) {
+ // recursively register the types
+ if _, ok := x.tm[t]; ok {
+ return
+ }
+ var tkey reflect.Type
+ switch t.Kind() {
+ case reflect.Chan, reflect.Slice, reflect.Array:
+ case reflect.Map:
+ tkey = t.Key()
+ default:
+ return
+ }
+ x.tm[t] = struct{}{}
+ x.ts = append(x.ts, t)
+ // check if this refers to any xtra types eg. a slice of array: add the array
+ x.registerXtraT(t.Elem())
+ if tkey != nil {
+ x.registerXtraT(tkey)
+ }
+}
+
+// encVar will encode a variable.
+// The parameter, t, is the reflect.Type of the variable itself
+func (x *genRunner) encVar(varname string, t reflect.Type) {
+ // fmt.Printf(">>>>>> varname: %s, t: %v\n", varname, t)
+ var checkNil bool
+ switch t.Kind() {
+ case reflect.Ptr, reflect.Interface, reflect.Slice, reflect.Map, reflect.Chan:
+ checkNil = true
+ }
+ if checkNil {
+ x.linef("if %s == nil { r.EncodeNil() } else { ", varname)
+ }
+
+ switch t.Kind() {
+ case reflect.Ptr:
+ telem := t.Elem()
+ tek := telem.Kind()
+ if tek == reflect.Array || (tek == reflect.Struct && telem != timeTyp) {
+ x.enc(varname, genNonPtr(t))
+ break
+ }
+ i := x.varsfx()
+ x.line(genTempVarPfx + i + " := *" + varname)
+ x.enc(genTempVarPfx+i, genNonPtr(t))
+ case reflect.Struct, reflect.Array:
+ if t == timeTyp {
+ x.enc(varname, t)
+ break
+ }
+ i := x.varsfx()
+ x.line(genTempVarPfx + i + " := &" + varname)
+ x.enc(genTempVarPfx+i, t)
+ default:
+ x.enc(varname, t)
+ }
+
+ if checkNil {
+ x.line("}")
+ }
+
+}
+
+// enc will encode a variable (varname) of type t, where t represents T.
+// if t is !time.Time and t is of kind reflect.Struct or reflect.Array, varname is of type *T
+// (to prevent copying),
+// else t is of type T
+func (x *genRunner) enc(varname string, t reflect.Type) {
+ rtid := rt2id(t)
+ ti2 := x.ti.get(rtid, t)
+ // We call CodecEncodeSelf if one of the following are honored:
+ // - the type already implements Selfer, call that
+ // - the type has a Selfer implementation just created, use that
+ // - the type is in the list of the ones we will generate for, but it is not currently being generated
+
+ mi := x.varsfx()
+ // tptr := reflect.PtrTo(t)
+ tk := t.Kind()
+ if x.checkForSelfer(t, varname) {
+ if tk == reflect.Array || (tk == reflect.Struct && rtid != timeTypId) { // varname is of type *T
+ // if tptr.Implements(selferTyp) || t.Implements(selferTyp) {
+ if ti2.isFlag(typeInfoFlagIsZeroerPtr) || ti2.isFlag(typeInfoFlagIsZeroer) {
+ x.line(varname + ".CodecEncodeSelf(e)")
+ return
+ }
+ } else { // varname is of type T
+ if ti2.cs { // t.Implements(selferTyp) {
+ x.line(varname + ".CodecEncodeSelf(e)")
+ return
+ } else if ti2.csp { // tptr.Implements(selferTyp) {
+ x.linef("%ssf%s := &%s", genTempVarPfx, mi, varname)
+ x.linef("%ssf%s.CodecEncodeSelf(e)", genTempVarPfx, mi)
+ return
+ }
+ }
+
+ if _, ok := x.te[rtid]; ok {
+ x.line(varname + ".CodecEncodeSelf(e)")
+ return
+ }
+ }
+
+ inlist := false
+ for _, t0 := range x.t {
+ if t == t0 {
+ inlist = true
+ if x.checkForSelfer(t, varname) {
+ x.line(varname + ".CodecEncodeSelf(e)")
+ return
+ }
+ break
+ }
+ }
+
+ var rtidAdded bool
+ if t == x.tc {
+ x.te[rtid] = true
+ rtidAdded = true
+ }
+
+ // check if
+ // - type is time.Time, RawExt, Raw
+ // - the type implements (Text|JSON|Binary)(Unm|M)arshal
+
+ x.line("if false {") //start if block
+ defer func() { x.line("}") }() //end if block
+
+ if t == timeTyp {
+ x.linef("} else { r.EncodeTime(%s)", varname)
+ return
+ }
+ if t == rawTyp {
+ x.linef("} else { z.EncRaw(%s)", varname)
+ return
+ }
+ if t == rawExtTyp {
+ x.linef("} else { r.EncodeRawExt(%s, e)", varname)
+ return
+ }
+ // only check for extensions if the type is named, and has a packagePath.
+ var arrayOrStruct = tk == reflect.Array || tk == reflect.Struct // meaning varname if of type *T
+ if !x.nx && genImportPath(t) != "" && t.Name() != "" {
+ yy := fmt.Sprintf("%sxt%s", genTempVarPfx, mi)
+ x.linef("} else if %s := z.Extension(z.I2Rtid(%s)); %s != nil { z.EncExtension(%s, %s) ", yy, varname, yy, varname, yy)
+ }
+ if arrayOrStruct { // varname is of type *T
+ if ti2.bm || ti2.bmp { // t.Implements(binaryMarshalerTyp) || tptr.Implements(binaryMarshalerTyp) {
+ x.linef("} else if z.EncBinary() { z.EncBinaryMarshal(%v) ", varname)
+ }
+ if ti2.jm || ti2.jmp { // t.Implements(jsonMarshalerTyp) || tptr.Implements(jsonMarshalerTyp) {
+ x.linef("} else if !z.EncBinary() && z.IsJSONHandle() { z.EncJSONMarshal(%v) ", varname)
+ } else if ti2.tm || ti2.tmp { // t.Implements(textMarshalerTyp) || tptr.Implements(textMarshalerTyp) {
+ x.linef("} else if !z.EncBinary() { z.EncTextMarshal(%v) ", varname)
+ }
+ } else { // varname is of type T
+ if ti2.bm { // t.Implements(binaryMarshalerTyp) {
+ x.linef("} else if z.EncBinary() { z.EncBinaryMarshal(%v) ", varname)
+ } else if ti2.bmp { // tptr.Implements(binaryMarshalerTyp) {
+ x.linef("} else if z.EncBinary() { z.EncBinaryMarshal(&%v) ", varname)
+ }
+ if ti2.jm { // t.Implements(jsonMarshalerTyp) {
+ x.linef("} else if !z.EncBinary() && z.IsJSONHandle() { z.EncJSONMarshal(%v) ", varname)
+ } else if ti2.jmp { // tptr.Implements(jsonMarshalerTyp) {
+ x.linef("} else if !z.EncBinary() && z.IsJSONHandle() { z.EncJSONMarshal(&%v) ", varname)
+ } else if ti2.tm { // t.Implements(textMarshalerTyp) {
+ x.linef("} else if !z.EncBinary() { z.EncTextMarshal(%v) ", varname)
+ } else if ti2.tmp { // tptr.Implements(textMarshalerTyp) {
+ x.linef("} else if !z.EncBinary() { z.EncTextMarshal(&%v) ", varname)
+ }
+ }
+ x.line("} else {")
+
+ switch t.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ x.line("r.EncodeInt(int64(" + varname + "))")
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ x.line("r.EncodeUint(uint64(" + varname + "))")
+ case reflect.Float32:
+ x.line("r.EncodeFloat32(float32(" + varname + "))")
+ case reflect.Float64:
+ x.line("r.EncodeFloat64(float64(" + varname + "))")
+ case reflect.Bool:
+ x.line("r.EncodeBool(bool(" + varname + "))")
+ case reflect.String:
+ x.line("r.EncodeString(codecSelferCcUTF8" + x.xs + ", string(" + varname + "))")
+ case reflect.Chan:
+ x.xtraSM(varname, t, true, false)
+ // x.encListFallback(varname, rtid, t)
+ case reflect.Array:
+ x.xtraSM(varname, t, true, true)
+ case reflect.Slice:
+ // if nil, call dedicated function
+ // if a []uint8, call dedicated function
+ // if a known fastpath slice, call dedicated function
+ // else write encode function in-line.
+ // - if elements are primitives or Selfers, call dedicated function on each member.
+ // - else call Encoder.encode(XXX) on it.
+ if rtid == uint8SliceTypId {
+ x.line("r.EncodeStringBytes(codecSelferCcRAW" + x.xs + ", []byte(" + varname + "))")
+ } else if fastpathAV.index(rtid) != -1 {
+ g := x.newGenV(t)
+ x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", e)")
+ } else {
+ x.xtraSM(varname, t, true, false)
+ // x.encListFallback(varname, rtid, t)
+ }
+ case reflect.Map:
+ // if nil, call dedicated function
+ // if a known fastpath map, call dedicated function
+ // else write encode function in-line.
+ // - if elements are primitives or Selfers, call dedicated function on each member.
+ // - else call Encoder.encode(XXX) on it.
+ // x.line("if " + varname + " == nil { \nr.EncodeNil()\n } else { ")
+ if fastpathAV.index(rtid) != -1 {
+ g := x.newGenV(t)
+ x.line("z.F." + g.MethodNamePfx("Enc", false) + "V(" + varname + ", e)")
+ } else {
+ x.xtraSM(varname, t, true, false)
+ // x.encMapFallback(varname, rtid, t)
+ }
+ case reflect.Struct:
+ if !inlist {
+ delete(x.te, rtid)
+ x.line("z.EncFallback(" + varname + ")")
+ break
+ }
+ x.encStruct(varname, rtid, t)
+ default:
+ if rtidAdded {
+ delete(x.te, rtid)
+ }
+ x.line("z.EncFallback(" + varname + ")")
+ }
+}
+
+func (x *genRunner) encZero(t reflect.Type) {
+ switch t.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ x.line("r.EncodeInt(0)")
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ x.line("r.EncodeUint(0)")
+ case reflect.Float32:
+ x.line("r.EncodeFloat32(0)")
+ case reflect.Float64:
+ x.line("r.EncodeFloat64(0)")
+ case reflect.Bool:
+ x.line("r.EncodeBool(false)")
+ case reflect.String:
+ x.line("r.EncodeString(codecSelferCcUTF8" + x.xs + `, "")`)
+ default:
+ x.line("r.EncodeNil()")
+ }
+}
+
+func (x *genRunner) encOmitEmptyLine(t2 reflect.StructField, varname string, buf *genBuf) {
+ // smartly check omitEmpty on a struct type, as it may contain uncomparable map/slice/etc.
+ // also, for maps/slices/arrays, check if len ! 0 (not if == zero value)
+ varname2 := varname + "." + t2.Name
+ switch t2.Type.Kind() {
+ case reflect.Struct:
+ rtid2 := rt2id(t2.Type)
+ ti2 := x.ti.get(rtid2, t2.Type)
+ // fmt.Printf(">>>> structfield: omitempty: type: %s, field: %s\n", t2.Type.Name(), t2.Name)
+ if ti2.rtid == timeTypId {
+ buf.s("!(").s(varname2).s(".IsZero())")
+ break
+ }
+ if ti2.isFlag(typeInfoFlagIsZeroerPtr) || ti2.isFlag(typeInfoFlagIsZeroer) {
+ buf.s("!(").s(varname2).s(".IsZero())")
+ break
+ }
+ if ti2.isFlag(typeInfoFlagComparable) {
+ buf.s(varname2).s(" != ").s(x.genZeroValueR(t2.Type))
+ break
+ }
+ // buf.s("(")
+ buf.s("false")
+ for i, n := 0, t2.Type.NumField(); i < n; i++ {
+ f := t2.Type.Field(i)
+ if f.PkgPath != "" { // unexported
+ continue
+ }
+ buf.s(" || ")
+ x.encOmitEmptyLine(f, varname2, buf)
+ }
+ //buf.s(")")
+ case reflect.Bool:
+ buf.s(varname2)
+ case reflect.Map, reflect.Slice, reflect.Array, reflect.Chan:
+ buf.s("len(").s(varname2).s(") != 0")
+ default:
+ buf.s(varname2).s(" != ").s(x.genZeroValueR(t2.Type))
+ }
+}
+
+func (x *genRunner) encStruct(varname string, rtid uintptr, t reflect.Type) {
+ // Use knowledge from structfieldinfo (mbs, encodable fields. Ignore omitempty. )
+ // replicate code in kStruct i.e. for each field, deref type to non-pointer, and call x.enc on it
+
+ // if t === type currently running selfer on, do for all
+ ti := x.ti.get(rtid, t)
+ i := x.varsfx()
+ sepVarname := genTempVarPfx + "sep" + i
+ numfieldsvar := genTempVarPfx + "q" + i
+ ti2arrayvar := genTempVarPfx + "r" + i
+ struct2arrvar := genTempVarPfx + "2arr" + i
+
+ x.line(sepVarname + " := !z.EncBinary()")
+ x.linef("%s := z.EncBasicHandle().StructToArray", struct2arrvar)
+ x.linef("_, _ = %s, %s", sepVarname, struct2arrvar)
+ x.linef("const %s bool = %v // struct tag has 'toArray'", ti2arrayvar, ti.toArray)
+
+ tisfi := ti.sfiSrc // always use sequence from file. decStruct expects same thing.
+
+ // var nn int
+ // due to omitEmpty, we need to calculate the
+ // number of non-empty things we write out first.
+ // This is required as we need to pre-determine the size of the container,
+ // to support length-prefixing.
+ if ti.anyOmitEmpty {
+ x.linef("var %s = [%v]bool{ // should field at this index be written?", numfieldsvar, len(tisfi))
+
+ for j, si := range tisfi {
+ _ = j
+ if !si.omitEmpty() {
+ // x.linef("%s[%v] = true // %s", numfieldsvar, j, si.fieldName)
+ x.linef("true, // %s", si.fieldName)
+ // nn++
+ continue
+ }
+ var t2 reflect.StructField
+ var omitline genBuf
+ {
+ t2typ := t
+ varname3 := varname
+ // go through the loop, record the t2 field explicitly,
+ // and gather the omit line if embedded in pointers.
+ for ij, ix := range si.is {
+ if uint8(ij) == si.nis {
+ break
+ }
+ for t2typ.Kind() == reflect.Ptr {
+ t2typ = t2typ.Elem()
+ }
+ t2 = t2typ.Field(int(ix))
+ t2typ = t2.Type
+ varname3 = varname3 + "." + t2.Name
+ // do not include actual field in the omit line.
+ // that is done subsequently (right after - below).
+ if uint8(ij+1) < si.nis && t2typ.Kind() == reflect.Ptr {
+ omitline.s(varname3).s(" != nil && ")
+ }
+ }
+ }
+ x.encOmitEmptyLine(t2, varname, &omitline)
+ x.linef("%s, // %s", omitline.v(), si.fieldName)
+ }
+ x.line("}")
+ x.linef("_ = %s", numfieldsvar)
+ }
+ // x.linef("var %snn%s int", genTempVarPfx, i)
+ x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
+ x.linef("r.WriteArrayStart(%d)", len(tisfi))
+ x.linef("} else {") // if not ti.toArray
+ if ti.anyOmitEmpty {
+ // nn = 0
+ // x.linef("var %snn%s = %v", genTempVarPfx, i, nn)
+ x.linef("var %snn%s int", genTempVarPfx, i)
+ x.linef("for _, b := range %s { if b { %snn%s++ } }", numfieldsvar, genTempVarPfx, i)
+ x.linef("r.WriteMapStart(%snn%s)", genTempVarPfx, i)
+ x.linef("%snn%s = %v", genTempVarPfx, i, 0)
+ } else {
+ x.linef("r.WriteMapStart(%d)", len(tisfi))
+ }
+ x.line("}") // close if not StructToArray
+
+ for j, si := range tisfi {
+ i := x.varsfx()
+ isNilVarName := genTempVarPfx + "n" + i
+ var labelUsed bool
+ var t2 reflect.StructField
+ {
+ t2typ := t
+ varname3 := varname
+ for ij, ix := range si.is {
+ if uint8(ij) == si.nis {
+ break
+ }
+ for t2typ.Kind() == reflect.Ptr {
+ t2typ = t2typ.Elem()
+ }
+ t2 = t2typ.Field(int(ix))
+ t2typ = t2.Type
+ varname3 = varname3 + "." + t2.Name
+ if t2typ.Kind() == reflect.Ptr {
+ if !labelUsed {
+ x.line("var " + isNilVarName + " bool")
+ }
+ x.line("if " + varname3 + " == nil { " + isNilVarName + " = true ")
+ x.line("goto LABEL" + i)
+ x.line("}")
+ labelUsed = true
+ // "varname3 = new(" + x.genTypeName(t3.Elem()) + ") }")
+ }
+ }
+ // t2 = t.FieldByIndex(si.is)
+ }
+ if labelUsed {
+ x.line("LABEL" + i + ":")
+ }
+ // if the type of the field is a Selfer, or one of the ones
+
+ x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray
+ if labelUsed {
+ x.linef("if %s { r.WriteArrayElem(); r.EncodeNil() } else { ", isNilVarName)
+ }
+ x.line("r.WriteArrayElem()")
+ if si.omitEmpty() {
+ x.linef("if %s[%v] {", numfieldsvar, j)
+ }
+ x.encVar(varname+"."+t2.Name, t2.Type)
+ if si.omitEmpty() {
+ x.linef("} else {")
+ x.encZero(t2.Type)
+ x.linef("}")
+ }
+ if labelUsed {
+ x.line("}")
+ }
+
+ x.linef("} else {") // if not ti.toArray
+
+ if si.omitEmpty() {
+ x.linef("if %s[%v] {", numfieldsvar, j)
+ }
+ x.line("r.WriteMapElemKey()")
+
+ // x.line("r.EncodeString(codecSelferCcUTF8" + x.xs + ", `" + si.encName + "`)")
+ // emulate EncStructFieldKey
+ switch ti.keyType {
+ case valueTypeInt:
+ x.linef("r.EncodeInt(z.M.Int(strconv.ParseInt(`%s`, 10, 64)))", si.encName)
+ case valueTypeUint:
+ x.linef("r.EncodeUint(z.M.Uint(strconv.ParseUint(`%s`, 10, 64)))", si.encName)
+ case valueTypeFloat:
+ x.linef("r.EncodeFloat64(z.M.Float(strconv.ParseFloat(`%s`, 64)))", si.encName)
+ default: // string
+ x.linef("r.EncodeString(codecSelferCcUTF8%s, `%s`)", x.xs, si.encName)
+ }
+ // x.linef("r.EncStructFieldKey(codecSelferValueType%s%s, `%s`)", ti.keyType.String(), x.xs, si.encName)
+ x.line("r.WriteMapElemValue()")
+ if labelUsed {
+ x.line("if " + isNilVarName + " { r.EncodeNil() } else { ")
+ x.encVar(varname+"."+t2.Name, t2.Type)
+ x.line("}")
+ } else {
+ x.encVar(varname+"."+t2.Name, t2.Type)
+ }
+ if si.omitEmpty() {
+ x.line("}")
+ }
+ x.linef("} ") // end if/else ti.toArray
+ }
+ x.linef("if %s || %s {", ti2arrayvar, struct2arrvar) // if ti.toArray {
+ x.line("r.WriteArrayEnd()")
+ x.line("} else {")
+ x.line("r.WriteMapEnd()")
+ x.line("}")
+
+}
+
+func (x *genRunner) encListFallback(varname string, t reflect.Type) {
+ elemBytes := t.Elem().Kind() == reflect.Uint8
+ if t.AssignableTo(uint8SliceTyp) {
+ x.linef("r.EncodeStringBytes(codecSelferCcRAW%s, []byte(%s))", x.xs, varname)
+ return
+ }
+ if t.Kind() == reflect.Array && elemBytes {
+ x.linef("r.EncodeStringBytes(codecSelferCcRAW%s, ((*[%d]byte)(%s))[:])", x.xs, t.Len(), varname)
+ return
+ }
+ i := x.varsfx()
+ if t.Kind() == reflect.Chan {
+ type ts struct {
+ Label, Chan, Slice, Sfx string
+ }
+ tm, err := template.New("").Parse(genEncChanTmpl)
+ if err != nil {
+ panic(err)
+ }
+ x.linef("if %s == nil { r.EncodeNil() } else { ", varname)
+ x.linef("var sch%s []%s", i, x.genTypeName(t.Elem()))
+ err = tm.Execute(x.w, &ts{"Lsch" + i, varname, "sch" + i, i})
+ if err != nil {
+ panic(err)
+ }
+ // x.linef("%s = sch%s", varname, i)
+ if elemBytes {
+ x.linef("r.EncodeStringBytes(codecSelferCcRAW%s, []byte(%s))", x.xs, "sch"+i)
+ x.line("}")
+ return
+ }
+ varname = "sch" + i
+ }
+
+ x.line("r.WriteArrayStart(len(" + varname + "))")
+ x.linef("for _, %sv%s := range %s {", genTempVarPfx, i, varname)
+ x.line("r.WriteArrayElem()")
+
+ x.encVar(genTempVarPfx+"v"+i, t.Elem())
+ x.line("}")
+ x.line("r.WriteArrayEnd()")
+ if t.Kind() == reflect.Chan {
+ x.line("}")
+ }
+}
+
+func (x *genRunner) encMapFallback(varname string, t reflect.Type) {
+ // TODO: expand this to handle canonical.
+ i := x.varsfx()
+ x.line("r.WriteMapStart(len(" + varname + "))")
+ x.linef("for %sk%s, %sv%s := range %s {", genTempVarPfx, i, genTempVarPfx, i, varname)
+ x.line("r.WriteMapElemKey()")
+ x.encVar(genTempVarPfx+"k"+i, t.Key())
+ x.line("r.WriteMapElemValue()")
+ x.encVar(genTempVarPfx+"v"+i, t.Elem())
+ x.line("}")
+ x.line("r.WriteMapEnd()")
+}
+
+func (x *genRunner) decVarInitPtr(varname, nilvar string, t reflect.Type, si *structFieldInfo,
+ newbuf, nilbuf *genBuf) (t2 reflect.StructField) {
+ //we must accommodate anonymous fields, where the embedded field is a nil pointer in the value.
+ // t2 = t.FieldByIndex(si.is)
+ t2typ := t
+ varname3 := varname
+ t2kind := t2typ.Kind()
+ var nilbufed bool
+ if si != nil {
+ for ij, ix := range si.is {
+ if uint8(ij) == si.nis {
+ break
+ }
+ for t2typ.Kind() == reflect.Ptr {
+ t2typ = t2typ.Elem()
+ }
+ t2 = t2typ.Field(int(ix))
+ t2typ = t2.Type
+ varname3 = varname3 + "." + t2.Name
+ t2kind = t2typ.Kind()
+ if t2kind != reflect.Ptr {
+ continue
+ }
+ if newbuf != nil {
+ newbuf.f("if %s == nil { %s = new(%s) }\n", varname3, varname3, x.genTypeName(t2typ.Elem()))
+ }
+ if nilbuf != nil {
+ if !nilbufed {
+ nilbuf.s("if true")
+ nilbufed = true
+ }
+ nilbuf.s(" && ").s(varname3).s(" != nil")
+ }
+ }
+ }
+ // if t2typ.Kind() == reflect.Ptr {
+ // varname3 = varname3 + t2.Name
+ // }
+ if nilbuf != nil {
+ if nilbufed {
+ nilbuf.s(" { ")
+ }
+ if nilvar != "" {
+ nilbuf.s(nilvar).s(" = true")
+ } else if tk := t2typ.Kind(); tk == reflect.Ptr {
+ if strings.IndexByte(varname3, '.') != -1 || strings.IndexByte(varname3, '[') != -1 {
+ nilbuf.s(varname3).s(" = nil")
+ } else {
+ nilbuf.s("*").s(varname3).s(" = ").s(x.genZeroValueR(t2typ.Elem()))
+ }
+ } else {
+ nilbuf.s(varname3).s(" = ").s(x.genZeroValueR(t2typ))
+ }
+ if nilbufed {
+ nilbuf.s("}")
+ }
+ }
+ return t2
+}
+
+// decVar takes a variable called varname, of type t
+func (x *genRunner) decVarMain(varname, rand string, t reflect.Type, checkNotNil bool) {
+ // We only encode as nil if a nillable value.
+ // This removes some of the wasted checks for TryDecodeAsNil.
+ // We need to think about this more, to see what happens if omitempty, etc
+ // cause a nil value to be stored when something is expected.
+ // This could happen when decoding from a struct encoded as an array.
+ // For that, decVar should be called with canNil=true, to force true as its value.
+ var varname2 string
+ if t.Kind() != reflect.Ptr {
+ if t.PkgPath() != "" || !x.decTryAssignPrimitive(varname, t, false) {
+ x.dec(varname, t, false)
+ }
+ } else {
+ if checkNotNil {
+ x.linef("if %s == nil { %s = new(%s) }", varname, varname, x.genTypeName(t.Elem()))
+ }
+ // Ensure we set underlying ptr to a non-nil value (so we can deref to it later).
+ // There's a chance of a **T in here which is nil.
+ var ptrPfx string
+ for t = t.Elem(); t.Kind() == reflect.Ptr; t = t.Elem() {
+ ptrPfx += "*"
+ if checkNotNil {
+ x.linef("if %s%s == nil { %s%s = new(%s)}",
+ ptrPfx, varname, ptrPfx, varname, x.genTypeName(t))
+ }
+ }
+ // Should we create temp var if a slice/map indexing? No. dec(...) can now handle it.
+
+ if ptrPfx == "" {
+ x.dec(varname, t, true)
+ } else {
+ varname2 = genTempVarPfx + "z" + rand
+ x.line(varname2 + " := " + ptrPfx + varname)
+ x.dec(varname2, t, true)
+ }
+ }
+}
+
+// decVar takes a variable called varname, of type t
+func (x *genRunner) decVar(varname, nilvar string, t reflect.Type, canBeNil, checkNotNil bool) {
+ i := x.varsfx()
+
+ // We only encode as nil if a nillable value.
+ // This removes some of the wasted checks for TryDecodeAsNil.
+ // We need to think about this more, to see what happens if omitempty, etc
+ // cause a nil value to be stored when something is expected.
+ // This could happen when decoding from a struct encoded as an array.
+ // For that, decVar should be called with canNil=true, to force true as its value.
+
+ if !canBeNil {
+ canBeNil = genAnythingCanBeNil || !genIsImmutable(t)
+ }
+
+ if canBeNil {
+ var buf genBuf
+ x.decVarInitPtr(varname, nilvar, t, nil, nil, &buf)
+ x.linef("if r.TryDecodeAsNil() { %s } else {", buf.buf)
+ } else {
+ x.line("// cannot be nil")
+ }
+
+ x.decVarMain(varname, i, t, checkNotNil)
+
+ if canBeNil {
+ x.line("} ")
+ }
+}
+
+// dec will decode a variable (varname) of type t or ptrTo(t) if isptr==true.
+// t is always a basetype (i.e. not of kind reflect.Ptr).
+func (x *genRunner) dec(varname string, t reflect.Type, isptr bool) {
+ // assumptions:
+ // - the varname is to a pointer already. No need to take address of it
+ // - t is always a baseType T (not a *T, etc).
+ rtid := rt2id(t)
+ ti2 := x.ti.get(rtid, t)
+ // tptr := reflect.PtrTo(t)
+ if x.checkForSelfer(t, varname) {
+ if ti2.cs || ti2.csp { // t.Implements(selferTyp) || tptr.Implements(selferTyp) {
+ x.line(varname + ".CodecDecodeSelf(d)")
+ return
+ }
+ if _, ok := x.td[rtid]; ok {
+ x.line(varname + ".CodecDecodeSelf(d)")
+ return
+ }
+ }
+
+ inlist := false
+ for _, t0 := range x.t {
+ if t == t0 {
+ inlist = true
+ if x.checkForSelfer(t, varname) {
+ x.line(varname + ".CodecDecodeSelf(d)")
+ return
+ }
+ break
+ }
+ }
+
+ var rtidAdded bool
+ if t == x.tc {
+ x.td[rtid] = true
+ rtidAdded = true
+ }
+
+ // check if
+ // - type is time.Time, Raw, RawExt
+ // - the type implements (Text|JSON|Binary)(Unm|M)arshal
+
+ mi := x.varsfx()
+ // x.linef("%sm%s := z.DecBinary()", genTempVarPfx, mi)
+ // x.linef("_ = %sm%s", genTempVarPfx, mi)
+ x.line("if false {") //start if block
+ defer func() { x.line("}") }() //end if block
+
+ var ptrPfx, addrPfx string
+ if isptr {
+ ptrPfx = "*"
+ } else {
+ addrPfx = "&"
+ }
+ if t == timeTyp {
+ x.linef("} else { %s%v = r.DecodeTime()", ptrPfx, varname)
+ return
+ }
+ if t == rawTyp {
+ x.linef("} else { %s%v = z.DecRaw()", ptrPfx, varname)
+ return
+ }
+
+ if t == rawExtTyp {
+ x.linef("} else { r.DecodeExt(%s%v, 0, nil)", addrPfx, varname)
+ return
+ }
+
+ // only check for extensions if the type is named, and has a packagePath.
+ if !x.nx && genImportPath(t) != "" && t.Name() != "" {
+ // first check if extensions are configued, before doing the interface conversion
+ // x.linef("} else if z.HasExtensions() && z.DecExt(%s) {", varname)
+ yy := fmt.Sprintf("%sxt%s", genTempVarPfx, mi)
+ x.linef("} else if %s := z.Extension(z.I2Rtid(%s)); %s != nil { z.DecExtension(%s, %s) ", yy, varname, yy, varname, yy)
+ }
+
+ if ti2.bu || ti2.bup { // t.Implements(binaryUnmarshalerTyp) || tptr.Implements(binaryUnmarshalerTyp) {
+ x.linef("} else if z.DecBinary() { z.DecBinaryUnmarshal(%s%v) ", addrPfx, varname)
+ }
+ if ti2.ju || ti2.jup { // t.Implements(jsonUnmarshalerTyp) || tptr.Implements(jsonUnmarshalerTyp) {
+ x.linef("} else if !z.DecBinary() && z.IsJSONHandle() { z.DecJSONUnmarshal(%s%v)", addrPfx, varname)
+ } else if ti2.tu || ti2.tup { // t.Implements(textUnmarshalerTyp) || tptr.Implements(textUnmarshalerTyp) {
+ x.linef("} else if !z.DecBinary() { z.DecTextUnmarshal(%s%v)", addrPfx, varname)
+ }
+
+ x.line("} else {")
+
+ if x.decTryAssignPrimitive(varname, t, isptr) {
+ return
+ }
+
+ switch t.Kind() {
+ case reflect.Array, reflect.Chan:
+ x.xtraSM(varname, t, false, isptr)
+ case reflect.Slice:
+ // if a []uint8, call dedicated function
+ // if a known fastpath slice, call dedicated function
+ // else write encode function in-line.
+ // - if elements are primitives or Selfers, call dedicated function on each member.
+ // - else call Encoder.encode(XXX) on it.
+ if rtid == uint8SliceTypId {
+ x.linef("%s%s = r.DecodeBytes(%s(%s[]byte)(%s), false)",
+ ptrPfx, varname, ptrPfx, ptrPfx, varname)
+ } else if fastpathAV.index(rtid) != -1 {
+ g := x.newGenV(t)
+ x.linef("z.F.%sX(%s%s, d)", g.MethodNamePfx("Dec", false), addrPfx, varname)
+ } else {
+ x.xtraSM(varname, t, false, isptr)
+ // x.decListFallback(varname, rtid, false, t)
+ }
+ case reflect.Map:
+ // if a known fastpath map, call dedicated function
+ // else write encode function in-line.
+ // - if elements are primitives or Selfers, call dedicated function on each member.
+ // - else call Encoder.encode(XXX) on it.
+ if fastpathAV.index(rtid) != -1 {
+ g := x.newGenV(t)
+ x.linef("z.F.%sX(%s%s, d)", g.MethodNamePfx("Dec", false), addrPfx, varname)
+ } else {
+ x.xtraSM(varname, t, false, isptr)
+ // x.decMapFallback(varname, rtid, t)
+ }
+ case reflect.Struct:
+ if inlist {
+ // no need to create temp variable if isptr, or x.F or x[F]
+ if isptr || strings.IndexByte(varname, '.') != -1 || strings.IndexByte(varname, '[') != -1 {
+ x.decStruct(varname, rtid, t)
+ } else {
+ varname2 := genTempVarPfx + "j" + mi
+ x.line(varname2 + " := &" + varname)
+ x.decStruct(varname2, rtid, t)
+ }
+ } else {
+ // delete(x.td, rtid)
+ x.line("z.DecFallback(" + addrPfx + varname + ", false)")
+ }
+ default:
+ if rtidAdded {
+ delete(x.te, rtid)
+ }
+ x.line("z.DecFallback(" + addrPfx + varname + ", true)")
+ }
+}
+
+func (x *genRunner) decTryAssignPrimitive(varname string, t reflect.Type, isptr bool) (done bool) {
+ // This should only be used for exact primitives (ie un-named types).
+ // Named types may be implementations of Selfer, Unmarshaler, etc.
+ // They should be handled by dec(...)
+
+ var ptr string
+ if isptr {
+ ptr = "*"
+ }
+ switch t.Kind() {
+ case reflect.Int:
+ x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), codecSelferBitsize%s))", ptr, varname, x.genTypeName(t), x.xs)
+ case reflect.Int8:
+ x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), 8))", ptr, varname, x.genTypeName(t))
+ case reflect.Int16:
+ x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), 16))", ptr, varname, x.genTypeName(t))
+ case reflect.Int32:
+ x.linef("%s%s = (%s)(z.C.IntV(r.DecodeInt64(), 32))", ptr, varname, x.genTypeName(t))
+ case reflect.Int64:
+ x.linef("%s%s = (%s)(r.DecodeInt64())", ptr, varname, x.genTypeName(t))
+
+ case reflect.Uint:
+ x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), codecSelferBitsize%s))", ptr, varname, x.genTypeName(t), x.xs)
+ case reflect.Uint8:
+ x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), 8))", ptr, varname, x.genTypeName(t))
+ case reflect.Uint16:
+ x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), 16))", ptr, varname, x.genTypeName(t))
+ case reflect.Uint32:
+ x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), 32))", ptr, varname, x.genTypeName(t))
+ case reflect.Uint64:
+ x.linef("%s%s = (%s)(r.DecodeUint64())", ptr, varname, x.genTypeName(t))
+ case reflect.Uintptr:
+ x.linef("%s%s = (%s)(z.C.UintV(r.DecodeUint64(), codecSelferBitsize%s))", ptr, varname, x.genTypeName(t), x.xs)
+
+ case reflect.Float32:
+ x.linef("%s%s = (%s)(r.DecodeFloat32As64())", ptr, varname, x.genTypeName(t))
+ case reflect.Float64:
+ x.linef("%s%s = (%s)(r.DecodeFloat64())", ptr, varname, x.genTypeName(t))
+
+ case reflect.Bool:
+ x.linef("%s%s = (%s)(r.DecodeBool())", ptr, varname, x.genTypeName(t))
+ case reflect.String:
+ x.linef("%s%s = (%s)(r.DecodeString())", ptr, varname, x.genTypeName(t))
+ default:
+ return false
+ }
+ return true
+}
+
+func (x *genRunner) decListFallback(varname string, rtid uintptr, t reflect.Type) {
+ if t.AssignableTo(uint8SliceTyp) {
+ x.line("*" + varname + " = r.DecodeBytes(*((*[]byte)(" + varname + ")), false)")
+ return
+ }
+ if t.Kind() == reflect.Array && t.Elem().Kind() == reflect.Uint8 {
+ x.linef("r.DecodeBytes( ((*[%d]byte)(%s))[:], true)", t.Len(), varname)
+ return
+ }
+ type tstruc struct {
+ TempVar string
+ Rand string
+ Varname string
+ CTyp string
+ Typ string
+ Immutable bool
+ Size int
+ }
+ telem := t.Elem()
+ ts := tstruc{genTempVarPfx, x.varsfx(), varname, x.genTypeName(t), x.genTypeName(telem), genIsImmutable(telem), int(telem.Size())}
+
+ funcs := make(template.FuncMap)
+
+ funcs["decLineVar"] = func(varname string) string {
+ x.decVar(varname, "", telem, false, true)
+ return ""
+ }
+ funcs["var"] = func(s string) string {
+ return ts.TempVar + s + ts.Rand
+ }
+ funcs["zero"] = func() string {
+ return x.genZeroValueR(telem)
+ }
+ funcs["isArray"] = func() bool {
+ return t.Kind() == reflect.Array
+ }
+ funcs["isSlice"] = func() bool {
+ return t.Kind() == reflect.Slice
+ }
+ funcs["isChan"] = func() bool {
+ return t.Kind() == reflect.Chan
+ }
+ tm, err := template.New("").Funcs(funcs).Parse(genDecListTmpl)
+ if err != nil {
+ panic(err)
+ }
+ if err = tm.Execute(x.w, &ts); err != nil {
+ panic(err)
+ }
+}
+
+func (x *genRunner) decMapFallback(varname string, rtid uintptr, t reflect.Type) {
+ type tstruc struct {
+ TempVar string
+ Sfx string
+ Rand string
+ Varname string
+ KTyp string
+ Typ string
+ Size int
+ }
+ telem := t.Elem()
+ tkey := t.Key()
+ ts := tstruc{
+ genTempVarPfx, x.xs, x.varsfx(), varname, x.genTypeName(tkey),
+ x.genTypeName(telem), int(telem.Size() + tkey.Size()),
+ }
+
+ funcs := make(template.FuncMap)
+ funcs["decElemZero"] = func() string {
+ return x.genZeroValueR(telem)
+ }
+ funcs["decElemKindImmutable"] = func() bool {
+ return genIsImmutable(telem)
+ }
+ funcs["decElemKindPtr"] = func() bool {
+ return telem.Kind() == reflect.Ptr
+ }
+ funcs["decElemKindIntf"] = func() bool {
+ return telem.Kind() == reflect.Interface
+ }
+ funcs["decLineVarK"] = func(varname string) string {
+ x.decVar(varname, "", tkey, false, true)
+ return ""
+ }
+ funcs["decLineVar"] = func(varname, decodedNilVarname string) string {
+ x.decVar(varname, decodedNilVarname, telem, false, true)
+ return ""
+ }
+ funcs["var"] = func(s string) string {
+ return ts.TempVar + s + ts.Rand
+ }
+
+ tm, err := template.New("").Funcs(funcs).Parse(genDecMapTmpl)
+ if err != nil {
+ panic(err)
+ }
+ if err = tm.Execute(x.w, &ts); err != nil {
+ panic(err)
+ }
+}
+
+func (x *genRunner) decStructMapSwitch(kName string, varname string, rtid uintptr, t reflect.Type) {
+ ti := x.ti.get(rtid, t)
+ tisfi := ti.sfiSrc // always use sequence from file. decStruct expects same thing.
+ x.line("switch (" + kName + ") {")
+ var newbuf, nilbuf genBuf
+ for _, si := range tisfi {
+ x.line("case \"" + si.encName + "\":")
+ newbuf.reset()
+ nilbuf.reset()
+ t2 := x.decVarInitPtr(varname, "", t, si, &newbuf, &nilbuf)
+ x.linef("if r.TryDecodeAsNil() { %s } else { %s", nilbuf.buf, newbuf.buf)
+ x.decVarMain(varname+"."+t2.Name, x.varsfx(), t2.Type, false)
+ x.line("}")
+ }
+ x.line("default:")
+ // pass the slice here, so that the string will not escape, and maybe save allocation
+ x.line("z.DecStructFieldNotFound(-1, " + kName + ")")
+ x.line("} // end switch " + kName)
+}
+
+func (x *genRunner) decStructMap(varname, lenvarname string, rtid uintptr, t reflect.Type, style genStructMapStyle) {
+ tpfx := genTempVarPfx
+ ti := x.ti.get(rtid, t)
+ i := x.varsfx()
+ kName := tpfx + "s" + i
+
+ switch style {
+ case genStructMapStyleLenPrefix:
+ x.linef("for %sj%s := 0; %sj%s < %s; %sj%s++ {", tpfx, i, tpfx, i, lenvarname, tpfx, i)
+ case genStructMapStyleCheckBreak:
+ x.linef("for %sj%s := 0; !r.CheckBreak(); %sj%s++ {", tpfx, i, tpfx, i)
+ default: // 0, otherwise.
+ x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length
+ x.linef("for %sj%s := 0; ; %sj%s++ {", tpfx, i, tpfx, i)
+ x.linef("if %shl%s { if %sj%s >= %s { break }", tpfx, i, tpfx, i, lenvarname)
+ x.line("} else { if r.CheckBreak() { break }; }")
+ }
+ x.line("r.ReadMapElemKey()")
+
+ // emulate decstructfieldkey
+ switch ti.keyType {
+ case valueTypeInt:
+ x.linef("%s := z.StringView(strconv.AppendInt(z.DecScratchArrayBuffer()[:0], r.DecodeInt64(), 10))", kName)
+ case valueTypeUint:
+ x.linef("%s := z.StringView(strconv.AppendUint(z.DecScratchArrayBuffer()[:0], r.DecodeUint64(), 10))", kName)
+ case valueTypeFloat:
+ x.linef("%s := z.StringView(strconv.AppendFloat(z.DecScratchArrayBuffer()[:0], r.DecodeFloat64(), 'f', -1, 64))", kName)
+ default: // string
+ x.linef("%s := z.StringView(r.DecodeStringAsBytes())", kName)
+ }
+ // x.linef("%s := z.StringView(r.DecStructFieldKey(codecSelferValueType%s%s, z.DecScratchArrayBuffer()))", kName, ti.keyType.String(), x.xs)
+
+ x.line("r.ReadMapElemValue()")
+ x.decStructMapSwitch(kName, varname, rtid, t)
+
+ x.line("} // end for " + tpfx + "j" + i)
+ x.line("r.ReadMapEnd()")
+}
+
+func (x *genRunner) decStructArray(varname, lenvarname, breakString string, rtid uintptr, t reflect.Type) {
+ tpfx := genTempVarPfx
+ i := x.varsfx()
+ ti := x.ti.get(rtid, t)
+ tisfi := ti.sfiSrc // always use sequence from file. decStruct expects same thing.
+ x.linef("var %sj%s int", tpfx, i)
+ x.linef("var %sb%s bool", tpfx, i) // break
+ x.linef("var %shl%s bool = %s >= 0", tpfx, i, lenvarname) // has length
+ var newbuf, nilbuf genBuf
+ for _, si := range tisfi {
+ x.linef("%sj%s++; if %shl%s { %sb%s = %sj%s > %s } else { %sb%s = r.CheckBreak() }",
+ tpfx, i, tpfx, i, tpfx, i,
+ tpfx, i, lenvarname, tpfx, i)
+ x.linef("if %sb%s { r.ReadArrayEnd(); %s }", tpfx, i, breakString)
+ x.line("r.ReadArrayElem()")
+ newbuf.reset()
+ nilbuf.reset()
+ t2 := x.decVarInitPtr(varname, "", t, si, &newbuf, &nilbuf)
+ x.linef("if r.TryDecodeAsNil() { %s } else { %s", nilbuf.buf, newbuf.buf)
+ x.decVarMain(varname+"."+t2.Name, x.varsfx(), t2.Type, false)
+ x.line("}")
+ }
+ // read remaining values and throw away.
+ x.line("for {")
+ x.linef("%sj%s++; if %shl%s { %sb%s = %sj%s > %s } else { %sb%s = r.CheckBreak() }",
+ tpfx, i, tpfx, i, tpfx, i,
+ tpfx, i, lenvarname, tpfx, i)
+ x.linef("if %sb%s { break }", tpfx, i)
+ x.line("r.ReadArrayElem()")
+ x.linef(`z.DecStructFieldNotFound(%sj%s - 1, "")`, tpfx, i)
+ x.line("}")
+ x.line("r.ReadArrayEnd()")
+}
+
+func (x *genRunner) decStruct(varname string, rtid uintptr, t reflect.Type) {
+ // varname MUST be a ptr, or a struct field or a slice element.
+ i := x.varsfx()
+ x.linef("%sct%s := r.ContainerType()", genTempVarPfx, i)
+ x.linef("if %sct%s == codecSelferValueTypeMap%s {", genTempVarPfx, i, x.xs)
+ x.line(genTempVarPfx + "l" + i + " := r.ReadMapStart()")
+ x.linef("if %sl%s == 0 {", genTempVarPfx, i)
+ x.line("r.ReadMapEnd()")
+ if genUseOneFunctionForDecStructMap {
+ x.line("} else { ")
+ x.linef("%s.codecDecodeSelfFromMap(%sl%s, d)", varname, genTempVarPfx, i)
+ } else {
+ x.line("} else if " + genTempVarPfx + "l" + i + " > 0 { ")
+ x.line(varname + ".codecDecodeSelfFromMapLenPrefix(" + genTempVarPfx + "l" + i + ", d)")
+ x.line("} else {")
+ x.line(varname + ".codecDecodeSelfFromMapCheckBreak(" + genTempVarPfx + "l" + i + ", d)")
+ }
+ x.line("}")
+
+ // else if container is array
+ x.linef("} else if %sct%s == codecSelferValueTypeArray%s {", genTempVarPfx, i, x.xs)
+ x.line(genTempVarPfx + "l" + i + " := r.ReadArrayStart()")
+ x.linef("if %sl%s == 0 {", genTempVarPfx, i)
+ x.line("r.ReadArrayEnd()")
+ x.line("} else { ")
+ x.linef("%s.codecDecodeSelfFromArray(%sl%s, d)", varname, genTempVarPfx, i)
+ x.line("}")
+ // else panic
+ x.line("} else { ")
+ x.line("panic(errCodecSelferOnlyMapOrArrayEncodeToStruct" + x.xs + ")")
+ x.line("} ")
+}
+
+// --------
+
+type genV struct {
+ // genV is either a primitive (Primitive != "") or a map (MapKey != "") or a slice
+ MapKey string
+ Elem string
+ Primitive string
+ Size int
+}
+
+func (x *genRunner) newGenV(t reflect.Type) (v genV) {
+ switch t.Kind() {
+ case reflect.Slice, reflect.Array:
+ te := t.Elem()
+ v.Elem = x.genTypeName(te)
+ v.Size = int(te.Size())
+ case reflect.Map:
+ te, tk := t.Elem(), t.Key()
+ v.Elem = x.genTypeName(te)
+ v.MapKey = x.genTypeName(tk)
+ v.Size = int(te.Size() + tk.Size())
+ default:
+ panic("unexpected type for newGenV. Requires map or slice type")
+ }
+ return
+}
+
+func (x *genV) MethodNamePfx(prefix string, prim bool) string {
+ var name []byte
+ if prefix != "" {
+ name = append(name, prefix...)
+ }
+ if prim {
+ name = append(name, genTitleCaseName(x.Primitive)...)
+ } else {
+ if x.MapKey == "" {
+ name = append(name, "Slice"...)
+ } else {
+ name = append(name, "Map"...)
+ name = append(name, genTitleCaseName(x.MapKey)...)
+ }
+ name = append(name, genTitleCaseName(x.Elem)...)
+ }
+ return string(name)
+
+}
+
+// genImportPath returns import path of a non-predeclared named typed, or an empty string otherwise.
+//
+// This handles the misbehaviour that occurs when 1.5-style vendoring is enabled,
+// where PkgPath returns the full path, including the vendoring pre-fix that should have been stripped.
+// We strip it here.
+func genImportPath(t reflect.Type) (s string) {
+ s = t.PkgPath()
+ if genCheckVendor {
+ // HACK: always handle vendoring. It should be typically on in go 1.6, 1.7
+ s = genStripVendor(s)
+ }
+ return
+}
+
+// A go identifier is (letter|_)[letter|number|_]*
+func genGoIdentifier(s string, checkFirstChar bool) string {
+ b := make([]byte, 0, len(s))
+ t := make([]byte, 4)
+ var n int
+ for i, r := range s {
+ if checkFirstChar && i == 0 && !unicode.IsLetter(r) {
+ b = append(b, '_')
+ }
+ // r must be unicode_letter, unicode_digit or _
+ if unicode.IsLetter(r) || unicode.IsDigit(r) {
+ n = utf8.EncodeRune(t, r)
+ b = append(b, t[:n]...)
+ } else {
+ b = append(b, '_')
+ }
+ }
+ return string(b)
+}
+
+func genNonPtr(t reflect.Type) reflect.Type {
+ for t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ return t
+}
+
+func genTitleCaseName(s string) string {
+ switch s {
+ case "interface{}", "interface {}":
+ return "Intf"
+ default:
+ return strings.ToUpper(s[0:1]) + s[1:]
+ }
+}
+
+func genMethodNameT(t reflect.Type, tRef reflect.Type) (n string) {
+ var ptrPfx string
+ for t.Kind() == reflect.Ptr {
+ ptrPfx += "Ptrto"
+ t = t.Elem()
+ }
+ tstr := t.String()
+ if tn := t.Name(); tn != "" {
+ if tRef != nil && genImportPath(t) == genImportPath(tRef) {
+ return ptrPfx + tn
+ } else {
+ if genQNameRegex.MatchString(tstr) {
+ return ptrPfx + strings.Replace(tstr, ".", "_", 1000)
+ } else {
+ return ptrPfx + genCustomTypeName(tstr)
+ }
+ }
+ }
+ switch t.Kind() {
+ case reflect.Map:
+ return ptrPfx + "Map" + genMethodNameT(t.Key(), tRef) + genMethodNameT(t.Elem(), tRef)
+ case reflect.Slice:
+ return ptrPfx + "Slice" + genMethodNameT(t.Elem(), tRef)
+ case reflect.Array:
+ return ptrPfx + "Array" + strconv.FormatInt(int64(t.Len()), 10) + genMethodNameT(t.Elem(), tRef)
+ case reflect.Chan:
+ var cx string
+ switch t.ChanDir() {
+ case reflect.SendDir:
+ cx = "ChanSend"
+ case reflect.RecvDir:
+ cx = "ChanRecv"
+ default:
+ cx = "Chan"
+ }
+ return ptrPfx + cx + genMethodNameT(t.Elem(), tRef)
+ default:
+ if t == intfTyp {
+ return ptrPfx + "Interface"
+ } else {
+ if tRef != nil && genImportPath(t) == genImportPath(tRef) {
+ if t.Name() != "" {
+ return ptrPfx + t.Name()
+ } else {
+ return ptrPfx + genCustomTypeName(tstr)
+ }
+ } else {
+ // best way to get the package name inclusive
+ // return ptrPfx + strings.Replace(tstr, ".", "_", 1000)
+ // return ptrPfx + genBase64enc.EncodeToString([]byte(tstr))
+ if t.Name() != "" && genQNameRegex.MatchString(tstr) {
+ return ptrPfx + strings.Replace(tstr, ".", "_", 1000)
+ } else {
+ return ptrPfx + genCustomTypeName(tstr)
+ }
+ }
+ }
+ }
+}
+
+// genCustomNameForType base64encodes the t.String() value in such a way
+// that it can be used within a function name.
+func genCustomTypeName(tstr string) string {
+ len2 := genBase64enc.EncodedLen(len(tstr))
+ bufx := make([]byte, len2)
+ genBase64enc.Encode(bufx, []byte(tstr))
+ for i := len2 - 1; i >= 0; i-- {
+ if bufx[i] == '=' {
+ len2--
+ } else {
+ break
+ }
+ }
+ return string(bufx[:len2])
+}
+
+func genIsImmutable(t reflect.Type) (v bool) {
+ return isImmutableKind(t.Kind())
+}
+
+type genInternal struct {
+ Version int
+ Values []genV
+}
+
+func (x genInternal) FastpathLen() (l int) {
+ for _, v := range x.Values {
+ if v.Primitive == "" && !(v.MapKey == "" && v.Elem == "uint8") {
+ l++
+ }
+ }
+ return
+}
+
+func genInternalZeroValue(s string) string {
+ switch s {
+ case "interface{}", "interface {}":
+ return "nil"
+ case "bool":
+ return "false"
+ case "string":
+ return `""`
+ default:
+ return "0"
+ }
+}
+
+var genInternalNonZeroValueIdx [5]uint64
+var genInternalNonZeroValueStrs = [2][5]string{
+ {`"string-is-an-interface"`, "true", `"some-string"`, "11.1", "33"},
+ {`"string-is-an-interface-2"`, "true", `"some-string-2"`, "22.2", "44"},
+}
+
+func genInternalNonZeroValue(s string) string {
+ switch s {
+ case "interface{}", "interface {}":
+ genInternalNonZeroValueIdx[0]++
+ return genInternalNonZeroValueStrs[genInternalNonZeroValueIdx[0]%2][0] // return string, to remove ambiguity
+ case "bool":
+ genInternalNonZeroValueIdx[1]++
+ return genInternalNonZeroValueStrs[genInternalNonZeroValueIdx[1]%2][1]
+ case "string":
+ genInternalNonZeroValueIdx[2]++
+ return genInternalNonZeroValueStrs[genInternalNonZeroValueIdx[2]%2][2]
+ case "float32", "float64", "float", "double":
+ genInternalNonZeroValueIdx[3]++
+ return genInternalNonZeroValueStrs[genInternalNonZeroValueIdx[3]%2][3]
+ default:
+ genInternalNonZeroValueIdx[4]++
+ return genInternalNonZeroValueStrs[genInternalNonZeroValueIdx[4]%2][4]
+ }
+}
+
+func genInternalEncCommandAsString(s string, vname string) string {
+ switch s {
+ case "uint", "uint8", "uint16", "uint32", "uint64":
+ return "ee.EncodeUint(uint64(" + vname + "))"
+ case "int", "int8", "int16", "int32", "int64":
+ return "ee.EncodeInt(int64(" + vname + "))"
+ case "string":
+ return "ee.EncodeString(cUTF8, " + vname + ")"
+ case "float32":
+ return "ee.EncodeFloat32(" + vname + ")"
+ case "float64":
+ return "ee.EncodeFloat64(" + vname + ")"
+ case "bool":
+ return "ee.EncodeBool(" + vname + ")"
+ // case "symbol":
+ // return "ee.EncodeSymbol(" + vname + ")"
+ default:
+ return "e.encode(" + vname + ")"
+ }
+}
+
+func genInternalDecCommandAsString(s string) string {
+ switch s {
+ case "uint":
+ return "uint(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))"
+ case "uint8":
+ return "uint8(chkOvf.UintV(dd.DecodeUint64(), 8))"
+ case "uint16":
+ return "uint16(chkOvf.UintV(dd.DecodeUint64(), 16))"
+ case "uint32":
+ return "uint32(chkOvf.UintV(dd.DecodeUint64(), 32))"
+ case "uint64":
+ return "dd.DecodeUint64()"
+ case "uintptr":
+ return "uintptr(chkOvf.UintV(dd.DecodeUint64(), uintBitsize))"
+ case "int":
+ return "int(chkOvf.IntV(dd.DecodeInt64(), intBitsize))"
+ case "int8":
+ return "int8(chkOvf.IntV(dd.DecodeInt64(), 8))"
+ case "int16":
+ return "int16(chkOvf.IntV(dd.DecodeInt64(), 16))"
+ case "int32":
+ return "int32(chkOvf.IntV(dd.DecodeInt64(), 32))"
+ case "int64":
+ return "dd.DecodeInt64()"
+
+ case "string":
+ return "dd.DecodeString()"
+ case "float32":
+ return "float32(chkOvf.Float32V(dd.DecodeFloat64()))"
+ case "float64":
+ return "dd.DecodeFloat64()"
+ case "bool":
+ return "dd.DecodeBool()"
+ default:
+ panic(errors.New("gen internal: unknown type for decode: " + s))
+ }
+}
+
+func genInternalSortType(s string, elem bool) string {
+ for _, v := range [...]string{"int", "uint", "float", "bool", "string"} {
+ if strings.HasPrefix(s, v) {
+ if elem {
+ if v == "int" || v == "uint" || v == "float" {
+ return v + "64"
+ } else {
+ return v
+ }
+ }
+ return v + "Slice"
+ }
+ }
+ panic("sorttype: unexpected type: " + s)
+}
+
+func genStripVendor(s string) string {
+ // HACK: Misbehaviour occurs in go 1.5. May have to re-visit this later.
+ // if s contains /vendor/ OR startsWith vendor/, then return everything after it.
+ const vendorStart = "vendor/"
+ const vendorInline = "/vendor/"
+ if i := strings.LastIndex(s, vendorInline); i >= 0 {
+ s = s[i+len(vendorInline):]
+ } else if strings.HasPrefix(s, vendorStart) {
+ s = s[len(vendorStart):]
+ }
+ return s
+}
+
+// var genInternalMu sync.Mutex
+var genInternalV = genInternal{Version: genVersion}
+var genInternalTmplFuncs template.FuncMap
+var genInternalOnce sync.Once
+
+func genInternalInit() {
+ types := [...]string{
+ "interface{}",
+ "string",
+ "float32",
+ "float64",
+ "uint",
+ "uint8",
+ "uint16",
+ "uint32",
+ "uint64",
+ "uintptr",
+ "int",
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "bool",
+ }
+ // keep as slice, so it is in specific iteration order.
+ // Initial order was uint64, string, interface{}, int, int64
+ mapvaltypes := [...]string{
+ "interface{}",
+ "string",
+ "uint",
+ "uint8",
+ "uint16",
+ "uint32",
+ "uint64",
+ "uintptr",
+ "int",
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "float32",
+ "float64",
+ "bool",
+ }
+ wordSizeBytes := int(intBitsize) / 8
+
+ mapvaltypes2 := map[string]int{
+ "interface{}": 2 * wordSizeBytes,
+ "string": 2 * wordSizeBytes,
+ "uint": 1 * wordSizeBytes,
+ "uint8": 1,
+ "uint16": 2,
+ "uint32": 4,
+ "uint64": 8,
+ "uintptr": 1 * wordSizeBytes,
+ "int": 1 * wordSizeBytes,
+ "int8": 1,
+ "int16": 2,
+ "int32": 4,
+ "int64": 8,
+ "float32": 4,
+ "float64": 8,
+ "bool": 1,
+ }
+ var gt = genInternal{Version: genVersion}
+
+ // For each slice or map type, there must be a (symmetrical) Encode and Decode fast-path function
+ for _, s := range types {
+ gt.Values = append(gt.Values, genV{Primitive: s, Size: mapvaltypes2[s]})
+ // if s != "uint8" { // do not generate fast path for slice of bytes. Treat specially already.
+ // gt.Values = append(gt.Values, genV{Elem: s, Size: mapvaltypes2[s]})
+ // }
+ gt.Values = append(gt.Values, genV{Elem: s, Size: mapvaltypes2[s]})
+ if _, ok := mapvaltypes2[s]; !ok {
+ gt.Values = append(gt.Values, genV{MapKey: s, Elem: s, Size: 2 * mapvaltypes2[s]})
+ }
+ for _, ms := range mapvaltypes {
+ gt.Values = append(gt.Values, genV{MapKey: s, Elem: ms, Size: mapvaltypes2[s] + mapvaltypes2[ms]})
+ }
+ }
+
+ funcs := make(template.FuncMap)
+ // funcs["haspfx"] = strings.HasPrefix
+ funcs["encmd"] = genInternalEncCommandAsString
+ funcs["decmd"] = genInternalDecCommandAsString
+ funcs["zerocmd"] = genInternalZeroValue
+ funcs["nonzerocmd"] = genInternalNonZeroValue
+ funcs["hasprefix"] = strings.HasPrefix
+ funcs["sorttype"] = genInternalSortType
+
+ genInternalV = gt
+ genInternalTmplFuncs = funcs
+}
+
+// genInternalGoFile is used to generate source files from templates.
+// It is run by the program author alone.
+// Unfortunately, it has to be exported so that it can be called from a command line tool.
+// *** DO NOT USE ***
+func genInternalGoFile(r io.Reader, w io.Writer) (err error) {
+ genInternalOnce.Do(genInternalInit)
+
+ gt := genInternalV
+
+ t := template.New("").Funcs(genInternalTmplFuncs)
+
+ tmplstr, err := ioutil.ReadAll(r)
+ if err != nil {
+ return
+ }
+
+ if t, err = t.Parse(string(tmplstr)); err != nil {
+ return
+ }
+
+ var out bytes.Buffer
+ err = t.Execute(&out, gt)
+ if err != nil {
+ return
+ }
+
+ bout, err := format.Source(out.Bytes())
+ if err != nil {
+ w.Write(out.Bytes()) // write out if error, so we can still see.
+ // w.Write(bout) // write out if error, as much as possible, so we can still see.
+ return
+ }
+ w.Write(bout)
+ return
+}
diff --git a/vendor/github.com/ugorji/go/codec/goversion_arrayof_gte_go15.go b/vendor/github.com/ugorji/go/codec/goversion_arrayof_gte_go15.go
new file mode 100644
index 00000000..9ddbe205
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_arrayof_gte_go15.go
@@ -0,0 +1,14 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.5
+
+package codec
+
+import "reflect"
+
+const reflectArrayOfSupported = true
+
+func reflectArrayOf(count int, elem reflect.Type) reflect.Type {
+ return reflect.ArrayOf(count, elem)
+}
diff --git a/vendor/github.com/ugorji/go/codec/goversion_arrayof_lt_go15.go b/vendor/github.com/ugorji/go/codec/goversion_arrayof_lt_go15.go
new file mode 100644
index 00000000..c5fcd669
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_arrayof_lt_go15.go
@@ -0,0 +1,14 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build !go1.5
+
+package codec
+
+import "reflect"
+
+const reflectArrayOfSupported = false
+
+func reflectArrayOf(count int, elem reflect.Type) reflect.Type {
+ panic("codec: reflect.ArrayOf unsupported in this go version")
+}
diff --git a/vendor/github.com/ugorji/go/codec/goversion_makemap_gte_go19.go b/vendor/github.com/ugorji/go/codec/goversion_makemap_gte_go19.go
new file mode 100644
index 00000000..bc39d6b7
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_makemap_gte_go19.go
@@ -0,0 +1,15 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.9
+
+package codec
+
+import "reflect"
+
+func makeMapReflect(t reflect.Type, size int) reflect.Value {
+ if size < 0 {
+ return reflect.MakeMapWithSize(t, 4)
+ }
+ return reflect.MakeMapWithSize(t, size)
+}
diff --git a/vendor/github.com/ugorji/go/codec/goversion_makemap_lt_go19.go b/vendor/github.com/ugorji/go/codec/goversion_makemap_lt_go19.go
new file mode 100644
index 00000000..cde4cd37
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_makemap_lt_go19.go
@@ -0,0 +1,12 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build !go1.9
+
+package codec
+
+import "reflect"
+
+func makeMapReflect(t reflect.Type, size int) reflect.Value {
+ return reflect.MakeMap(t)
+}
diff --git a/vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_gte_go110.go b/vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_gte_go110.go
new file mode 100644
index 00000000..794133a3
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_gte_go110.go
@@ -0,0 +1,8 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.10
+
+package codec
+
+const allowSetUnexportedEmbeddedPtr = false
diff --git a/vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_lt_go110.go b/vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_lt_go110.go
new file mode 100644
index 00000000..fd92ede3
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_unexportedembeddedptr_lt_go110.go
@@ -0,0 +1,8 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build !go1.10
+
+package codec
+
+const allowSetUnexportedEmbeddedPtr = true
diff --git a/vendor/github.com/ugorji/go/codec/goversion_unsupported_lt_go14.go b/vendor/github.com/ugorji/go/codec/goversion_unsupported_lt_go14.go
new file mode 100644
index 00000000..8debfa61
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_unsupported_lt_go14.go
@@ -0,0 +1,17 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build !go1.4
+
+package codec
+
+// This codec package will only work for go1.4 and above.
+// This is for the following reasons:
+// - go 1.4 was released in 2014
+// - go runtime is written fully in go
+// - interface only holds pointers
+// - reflect.Value is stabilized as 3 words
+
+func init() {
+ panic("codec: go 1.3 and below are not supported")
+}
diff --git a/vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go15.go b/vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go15.go
new file mode 100644
index 00000000..0f1bb01e
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go15.go
@@ -0,0 +1,10 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.5,!go1.6
+
+package codec
+
+import "os"
+
+var genCheckVendor = os.Getenv("GO15VENDOREXPERIMENT") == "1"
diff --git a/vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go16.go b/vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go16.go
new file mode 100644
index 00000000..2fb4b057
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_vendor_eq_go16.go
@@ -0,0 +1,10 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.6,!go1.7
+
+package codec
+
+import "os"
+
+var genCheckVendor = os.Getenv("GO15VENDOREXPERIMENT") != "0"
diff --git a/vendor/github.com/ugorji/go/codec/goversion_vendor_gte_go17.go b/vendor/github.com/ugorji/go/codec/goversion_vendor_gte_go17.go
new file mode 100644
index 00000000..c5b81550
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_vendor_gte_go17.go
@@ -0,0 +1,8 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.7
+
+package codec
+
+const genCheckVendor = true
diff --git a/vendor/github.com/ugorji/go/codec/goversion_vendor_lt_go15.go b/vendor/github.com/ugorji/go/codec/goversion_vendor_lt_go15.go
new file mode 100644
index 00000000..837cf240
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/goversion_vendor_lt_go15.go
@@ -0,0 +1,8 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build !go1.5
+
+package codec
+
+var genCheckVendor = false
diff --git a/vendor/github.com/ugorji/go/codec/helper.go b/vendor/github.com/ugorji/go/codec/helper.go
new file mode 100644
index 00000000..bd29895b
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/helper.go
@@ -0,0 +1,2414 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+// Contains code shared by both encode and decode.
+
+// Some shared ideas around encoding/decoding
+// ------------------------------------------
+//
+// If an interface{} is passed, we first do a type assertion to see if it is
+// a primitive type or a map/slice of primitive types, and use a fastpath to handle it.
+//
+// If we start with a reflect.Value, we are already in reflect.Value land and
+// will try to grab the function for the underlying Type and directly call that function.
+// This is more performant than calling reflect.Value.Interface().
+//
+// This still helps us bypass many layers of reflection, and give best performance.
+//
+// Containers
+// ------------
+// Containers in the stream are either associative arrays (key-value pairs) or
+// regular arrays (indexed by incrementing integers).
+//
+// Some streams support indefinite-length containers, and use a breaking
+// byte-sequence to denote that the container has come to an end.
+//
+// Some streams also are text-based, and use explicit separators to denote the
+// end/beginning of different values.
+//
+// During encode, we use a high-level condition to determine how to iterate through
+// the container. That decision is based on whether the container is text-based (with
+// separators) or binary (without separators). If binary, we do not even call the
+// encoding of separators.
+//
+// During decode, we use a different high-level condition to determine how to iterate
+// through the containers. That decision is based on whether the stream contained
+// a length prefix, or if it used explicit breaks. If length-prefixed, we assume that
+// it has to be binary, and we do not even try to read separators.
+//
+// Philosophy
+// ------------
+// On decode, this codec will update containers appropriately:
+// - If struct, update fields from stream into fields of struct.
+// If field in stream not found in struct, handle appropriately (based on option).
+// If a struct field has no corresponding value in the stream, leave it AS IS.
+// If nil in stream, set value to nil/zero value.
+// - If map, update map from stream.
+// If the stream value is NIL, set the map to nil.
+// - if slice, try to update up to length of array in stream.
+// if container len is less than stream array length,
+// and container cannot be expanded, handled (based on option).
+// This means you can decode 4-element stream array into 1-element array.
+//
+// ------------------------------------
+// On encode, user can specify omitEmpty. This means that the value will be omitted
+// if the zero value. The problem may occur during decode, where omitted values do not affect
+// the value being decoded into. This means that if decoding into a struct with an
+// int field with current value=5, and the field is omitted in the stream, then after
+// decoding, the value will still be 5 (not 0).
+// omitEmpty only works if you guarantee that you always decode into zero-values.
+//
+// ------------------------------------
+// We could have truncated a map to remove keys not available in the stream,
+// or set values in the struct which are not in the stream to their zero values.
+// We decided against it because there is no efficient way to do it.
+// We may introduce it as an option later.
+// However, that will require enabling it for both runtime and code generation modes.
+//
+// To support truncate, we need to do 2 passes over the container:
+// map
+// - first collect all keys (e.g. in k1)
+// - for each key in stream, mark k1 that the key should not be removed
+// - after updating map, do second pass and call delete for all keys in k1 which are not marked
+// struct:
+// - for each field, track the *typeInfo s1
+// - iterate through all s1, and for each one not marked, set value to zero
+// - this involves checking the possible anonymous fields which are nil ptrs.
+// too much work.
+//
+// ------------------------------------------
+// Error Handling is done within the library using panic.
+//
+// This way, the code doesn't have to keep checking if an error has happened,
+// and we don't have to keep sending the error value along with each call
+// or storing it in the En|Decoder and checking it constantly along the way.
+//
+// The disadvantage is that small functions which use panics cannot be inlined.
+// The code accounts for that by only using panics behind an interface;
+// since interface calls cannot be inlined, this is irrelevant.
+//
+// We considered storing the error is En|Decoder.
+// - once it has its err field set, it cannot be used again.
+// - panicing will be optional, controlled by const flag.
+// - code should always check error first and return early.
+// We eventually decided against it as it makes the code clumsier to always
+// check for these error conditions.
+
+import (
+ "bytes"
+ "encoding"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ scratchByteArrayLen = 32
+ // initCollectionCap = 16 // 32 is defensive. 16 is preferred.
+
+ // Support encoding.(Binary|Text)(Unm|M)arshaler.
+ // This constant flag will enable or disable it.
+ supportMarshalInterfaces = true
+
+ // for debugging, set this to false, to catch panic traces.
+ // Note that this will always cause rpc tests to fail, since they need io.EOF sent via panic.
+ recoverPanicToErr = true
+
+ // arrayCacheLen is the length of the cache used in encoder or decoder for
+ // allowing zero-alloc initialization.
+ arrayCacheLen = 8
+
+ // size of the cacheline: defaulting to value for archs: amd64, arm64, 386
+ // should use "runtime/internal/sys".CacheLineSize, but that is not exposed.
+ cacheLineSize = 64
+
+ wordSizeBits = 32 << (^uint(0) >> 63) // strconv.IntSize
+ wordSize = wordSizeBits / 8
+
+ maxLevelsEmbedding = 15 // use this, so structFieldInfo fits into 8 bytes
+)
+
+var (
+ oneByteArr = [1]byte{0}
+ zeroByteSlice = oneByteArr[:0:0]
+)
+
+var refBitset bitset32
+var pool pooler
+var panicv panicHdl
+
+func init() {
+ pool.init()
+
+ refBitset.set(byte(reflect.Map))
+ refBitset.set(byte(reflect.Ptr))
+ refBitset.set(byte(reflect.Func))
+ refBitset.set(byte(reflect.Chan))
+}
+
+type charEncoding uint8
+
+const (
+ cRAW charEncoding = iota
+ cUTF8
+ cUTF16LE
+ cUTF16BE
+ cUTF32LE
+ cUTF32BE
+)
+
+// valueType is the stream type
+type valueType uint8
+
+const (
+ valueTypeUnset valueType = iota
+ valueTypeNil
+ valueTypeInt
+ valueTypeUint
+ valueTypeFloat
+ valueTypeBool
+ valueTypeString
+ valueTypeSymbol
+ valueTypeBytes
+ valueTypeMap
+ valueTypeArray
+ valueTypeTime
+ valueTypeExt
+
+ // valueTypeInvalid = 0xff
+)
+
+var valueTypeStrings = [...]string{
+ "Unset",
+ "Nil",
+ "Int",
+ "Uint",
+ "Float",
+ "Bool",
+ "String",
+ "Symbol",
+ "Bytes",
+ "Map",
+ "Array",
+ "Timestamp",
+ "Ext",
+}
+
+func (x valueType) String() string {
+ if int(x) < len(valueTypeStrings) {
+ return valueTypeStrings[x]
+ }
+ return strconv.FormatInt(int64(x), 10)
+}
+
+type seqType uint8
+
+const (
+ _ seqType = iota
+ seqTypeArray
+ seqTypeSlice
+ seqTypeChan
+)
+
+// note that containerMapStart and containerArraySend are not sent.
+// This is because the ReadXXXStart and EncodeXXXStart already does these.
+type containerState uint8
+
+const (
+ _ containerState = iota
+
+ containerMapStart // slot left open, since Driver method already covers it
+ containerMapKey
+ containerMapValue
+ containerMapEnd
+ containerArrayStart // slot left open, since Driver methods already cover it
+ containerArrayElem
+ containerArrayEnd
+)
+
+// // sfiIdx used for tracking where a (field/enc)Name is seen in a []*structFieldInfo
+// type sfiIdx struct {
+// name string
+// index int
+// }
+
+// do not recurse if a containing type refers to an embedded type
+// which refers back to its containing type (via a pointer).
+// The second time this back-reference happens, break out,
+// so as not to cause an infinite loop.
+const rgetMaxRecursion = 2
+
+// Anecdotally, we believe most types have <= 12 fields.
+// - even Java's PMD rules set TooManyFields threshold to 15.
+// However, go has embedded fields, which should be regarded as
+// top level, allowing structs to possibly double or triple.
+// In addition, we don't want to keep creating transient arrays,
+// especially for the sfi index tracking, and the evtypes tracking.
+//
+// So - try to keep typeInfoLoadArray within 2K bytes
+const (
+ typeInfoLoadArraySfisLen = 16
+ typeInfoLoadArraySfiidxLen = 8 * 112
+ typeInfoLoadArrayEtypesLen = 12
+ typeInfoLoadArrayBLen = 8 * 4
+)
+
+type typeInfoLoad struct {
+ // fNames []string
+ // encNames []string
+ etypes []uintptr
+ sfis []structFieldInfo
+}
+
+type typeInfoLoadArray struct {
+ // fNames [typeInfoLoadArrayLen]string
+ // encNames [typeInfoLoadArrayLen]string
+ sfis [typeInfoLoadArraySfisLen]structFieldInfo
+ sfiidx [typeInfoLoadArraySfiidxLen]byte
+ etypes [typeInfoLoadArrayEtypesLen]uintptr
+ b [typeInfoLoadArrayBLen]byte // scratch - used for struct field names
+}
+
+// mirror json.Marshaler and json.Unmarshaler here,
+// so we don't import the encoding/json package
+
+type jsonMarshaler interface {
+ MarshalJSON() ([]byte, error)
+}
+type jsonUnmarshaler interface {
+ UnmarshalJSON([]byte) error
+}
+
+type isZeroer interface {
+ IsZero() bool
+}
+
+// type byteAccepter func(byte) bool
+
+var (
+ bigen = binary.BigEndian
+ structInfoFieldName = "_struct"
+
+ mapStrIntfTyp = reflect.TypeOf(map[string]interface{}(nil))
+ mapIntfIntfTyp = reflect.TypeOf(map[interface{}]interface{}(nil))
+ intfSliceTyp = reflect.TypeOf([]interface{}(nil))
+ intfTyp = intfSliceTyp.Elem()
+
+ reflectValTyp = reflect.TypeOf((*reflect.Value)(nil)).Elem()
+
+ stringTyp = reflect.TypeOf("")
+ timeTyp = reflect.TypeOf(time.Time{})
+ rawExtTyp = reflect.TypeOf(RawExt{})
+ rawTyp = reflect.TypeOf(Raw{})
+ uintptrTyp = reflect.TypeOf(uintptr(0))
+ uint8Typ = reflect.TypeOf(uint8(0))
+ uint8SliceTyp = reflect.TypeOf([]uint8(nil))
+ uintTyp = reflect.TypeOf(uint(0))
+ intTyp = reflect.TypeOf(int(0))
+
+ mapBySliceTyp = reflect.TypeOf((*MapBySlice)(nil)).Elem()
+
+ binaryMarshalerTyp = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
+ binaryUnmarshalerTyp = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
+
+ textMarshalerTyp = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+ textUnmarshalerTyp = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+
+ jsonMarshalerTyp = reflect.TypeOf((*jsonMarshaler)(nil)).Elem()
+ jsonUnmarshalerTyp = reflect.TypeOf((*jsonUnmarshaler)(nil)).Elem()
+
+ selferTyp = reflect.TypeOf((*Selfer)(nil)).Elem()
+ iszeroTyp = reflect.TypeOf((*isZeroer)(nil)).Elem()
+
+ uint8TypId = rt2id(uint8Typ)
+ uint8SliceTypId = rt2id(uint8SliceTyp)
+ rawExtTypId = rt2id(rawExtTyp)
+ rawTypId = rt2id(rawTyp)
+ intfTypId = rt2id(intfTyp)
+ timeTypId = rt2id(timeTyp)
+ stringTypId = rt2id(stringTyp)
+
+ mapStrIntfTypId = rt2id(mapStrIntfTyp)
+ mapIntfIntfTypId = rt2id(mapIntfIntfTyp)
+ intfSliceTypId = rt2id(intfSliceTyp)
+ // mapBySliceTypId = rt2id(mapBySliceTyp)
+
+ intBitsize = uint8(intTyp.Bits())
+ uintBitsize = uint8(uintTyp.Bits())
+
+ bsAll0x00 = []byte{0, 0, 0, 0, 0, 0, 0, 0}
+ bsAll0xff = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+
+ chkOvf checkOverflow
+
+ errNoFieldNameToStructFieldInfo = errors.New("no field name passed to parseStructFieldInfo")
+)
+
+var defTypeInfos = NewTypeInfos([]string{"codec", "json"})
+
+var immutableKindsSet = [32]bool{
+ // reflect.Invalid: ,
+ reflect.Bool: true,
+ reflect.Int: true,
+ reflect.Int8: true,
+ reflect.Int16: true,
+ reflect.Int32: true,
+ reflect.Int64: true,
+ reflect.Uint: true,
+ reflect.Uint8: true,
+ reflect.Uint16: true,
+ reflect.Uint32: true,
+ reflect.Uint64: true,
+ reflect.Uintptr: true,
+ reflect.Float32: true,
+ reflect.Float64: true,
+ reflect.Complex64: true,
+ reflect.Complex128: true,
+ // reflect.Array
+ // reflect.Chan
+ // reflect.Func: true,
+ // reflect.Interface
+ // reflect.Map
+ // reflect.Ptr
+ // reflect.Slice
+ reflect.String: true,
+ // reflect.Struct
+ // reflect.UnsafePointer
+}
+
+// Selfer defines methods by which a value can encode or decode itself.
+//
+// Any type which implements Selfer will be able to encode or decode itself.
+// Consequently, during (en|de)code, this takes precedence over
+// (text|binary)(M|Unm)arshal or extension support.
+//
+// Note: *the first set of bytes of any value MUST NOT represent nil in the format*.
+// This is because, during each decode, we first check the the next set of bytes
+// represent nil, and if so, we just set the value to nil.
+type Selfer interface {
+ CodecEncodeSelf(*Encoder)
+ CodecDecodeSelf(*Decoder)
+}
+
+// MapBySlice is a tag interface that denotes wrapped slice should encode as a map in the stream.
+// The slice contains a sequence of key-value pairs.
+// This affords storing a map in a specific sequence in the stream.
+//
+// Example usage:
+// type T1 []string // or []int or []Point or any other "slice" type
+// func (_ T1) MapBySlice{} // T1 now implements MapBySlice, and will be encoded as a map
+// type T2 struct { KeyValues T1 }
+//
+// var kvs = []string{"one", "1", "two", "2", "three", "3"}
+// var v2 = T2{ KeyValues: T1(kvs) }
+// // v2 will be encoded like the map: {"KeyValues": {"one": "1", "two": "2", "three": "3"} }
+//
+// The support of MapBySlice affords the following:
+// - A slice type which implements MapBySlice will be encoded as a map
+// - A slice can be decoded from a map in the stream
+// - It MUST be a slice type (not a pointer receiver) that implements MapBySlice
+type MapBySlice interface {
+ MapBySlice()
+}
+
+// BasicHandle encapsulates the common options and extension functions.
+//
+// Deprecated: DO NOT USE DIRECTLY. EXPORTED FOR GODOC BENEFIT. WILL BE REMOVED.
+type BasicHandle struct {
+ // BasicHandle is always a part of a different type.
+ // It doesn't have to fit into it own cache lines.
+
+ // TypeInfos is used to get the type info for any type.
+ //
+ // If not configured, the default TypeInfos is used, which uses struct tag keys: codec, json
+ TypeInfos *TypeInfos
+
+ // Note: BasicHandle is not comparable, due to these slices here (extHandle, intf2impls).
+ // If *[]T is used instead, this becomes comparable, at the cost of extra indirection.
+ // Thses slices are used all the time, so keep as slices (not pointers).
+
+ extHandle
+
+ intf2impls
+
+ RPCOptions
+
+ // ---- cache line
+
+ DecodeOptions
+
+ // ---- cache line
+
+ EncodeOptions
+
+ // noBuiltInTypeChecker
+}
+
+func (x *BasicHandle) getBasicHandle() *BasicHandle {
+ return x
+}
+
+func (x *BasicHandle) getTypeInfo(rtid uintptr, rt reflect.Type) (pti *typeInfo) {
+ if x.TypeInfos == nil {
+ return defTypeInfos.get(rtid, rt)
+ }
+ return x.TypeInfos.get(rtid, rt)
+}
+
+// Handle is the interface for a specific encoding format.
+//
+// Typically, a Handle is pre-configured before first time use,
+// and not modified while in use. Such a pre-configured Handle
+// is safe for concurrent access.
+type Handle interface {
+ Name() string
+ getBasicHandle() *BasicHandle
+ recreateEncDriver(encDriver) bool
+ newEncDriver(w *Encoder) encDriver
+ newDecDriver(r *Decoder) decDriver
+ isBinary() bool
+ hasElemSeparators() bool
+ // IsBuiltinType(rtid uintptr) bool
+}
+
+// Raw represents raw formatted bytes.
+// We "blindly" store it during encode and retrieve the raw bytes during decode.
+// Note: it is dangerous during encode, so we may gate the behaviour
+// behind an Encode flag which must be explicitly set.
+type Raw []byte
+
+// RawExt represents raw unprocessed extension data.
+// Some codecs will decode extension data as a *RawExt
+// if there is no registered extension for the tag.
+//
+// Only one of Data or Value is nil.
+// If Data is nil, then the content of the RawExt is in the Value.
+type RawExt struct {
+ Tag uint64
+ // Data is the []byte which represents the raw ext. If nil, ext is exposed in Value.
+ // Data is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of types
+ Data []byte
+ // Value represents the extension, if Data is nil.
+ // Value is used by codecs (e.g. cbor, json) which leverage the format to do
+ // custom serialization of the types.
+ Value interface{}
+}
+
+// BytesExt handles custom (de)serialization of types to/from []byte.
+// It is used by codecs (e.g. binc, msgpack, simple) which do custom serialization of the types.
+type BytesExt interface {
+ // WriteExt converts a value to a []byte.
+ //
+ // Note: v is a pointer iff the registered extension type is a struct or array kind.
+ WriteExt(v interface{}) []byte
+
+ // ReadExt updates a value from a []byte.
+ //
+ // Note: dst is always a pointer kind to the registered extension type.
+ ReadExt(dst interface{}, src []byte)
+}
+
+// InterfaceExt handles custom (de)serialization of types to/from another interface{} value.
+// The Encoder or Decoder will then handle the further (de)serialization of that known type.
+//
+// It is used by codecs (e.g. cbor, json) which use the format to do custom serialization of types.
+type InterfaceExt interface {
+ // ConvertExt converts a value into a simpler interface for easy encoding
+ // e.g. convert time.Time to int64.
+ //
+ // Note: v is a pointer iff the registered extension type is a struct or array kind.
+ ConvertExt(v interface{}) interface{}
+
+ // UpdateExt updates a value from a simpler interface for easy decoding
+ // e.g. convert int64 to time.Time.
+ //
+ // Note: dst is always a pointer kind to the registered extension type.
+ UpdateExt(dst interface{}, src interface{})
+}
+
+// Ext handles custom (de)serialization of custom types / extensions.
+type Ext interface {
+ BytesExt
+ InterfaceExt
+}
+
+// addExtWrapper is a wrapper implementation to support former AddExt exported method.
+type addExtWrapper struct {
+ encFn func(reflect.Value) ([]byte, error)
+ decFn func(reflect.Value, []byte) error
+}
+
+func (x addExtWrapper) WriteExt(v interface{}) []byte {
+ bs, err := x.encFn(reflect.ValueOf(v))
+ if err != nil {
+ panic(err)
+ }
+ return bs
+}
+
+func (x addExtWrapper) ReadExt(v interface{}, bs []byte) {
+ if err := x.decFn(reflect.ValueOf(v), bs); err != nil {
+ panic(err)
+ }
+}
+
+func (x addExtWrapper) ConvertExt(v interface{}) interface{} {
+ return x.WriteExt(v)
+}
+
+func (x addExtWrapper) UpdateExt(dest interface{}, v interface{}) {
+ x.ReadExt(dest, v.([]byte))
+}
+
+type extWrapper struct {
+ BytesExt
+ InterfaceExt
+}
+
+type bytesExtFailer struct{}
+
+func (bytesExtFailer) WriteExt(v interface{}) []byte {
+ panicv.errorstr("BytesExt.WriteExt is not supported")
+ return nil
+}
+func (bytesExtFailer) ReadExt(v interface{}, bs []byte) {
+ panicv.errorstr("BytesExt.ReadExt is not supported")
+}
+
+type interfaceExtFailer struct{}
+
+func (interfaceExtFailer) ConvertExt(v interface{}) interface{} {
+ panicv.errorstr("InterfaceExt.ConvertExt is not supported")
+ return nil
+}
+func (interfaceExtFailer) UpdateExt(dest interface{}, v interface{}) {
+ panicv.errorstr("InterfaceExt.UpdateExt is not supported")
+}
+
+type binaryEncodingType struct{}
+
+func (binaryEncodingType) isBinary() bool { return true }
+
+type textEncodingType struct{}
+
+func (textEncodingType) isBinary() bool { return false }
+
+// noBuiltInTypes is embedded into many types which do not support builtins
+// e.g. msgpack, simple, cbor.
+
+// type noBuiltInTypeChecker struct{}
+// func (noBuiltInTypeChecker) IsBuiltinType(rt uintptr) bool { return false }
+// type noBuiltInTypes struct{ noBuiltInTypeChecker }
+
+type noBuiltInTypes struct{}
+
+func (noBuiltInTypes) EncodeBuiltin(rt uintptr, v interface{}) {}
+func (noBuiltInTypes) DecodeBuiltin(rt uintptr, v interface{}) {}
+
+// type noStreamingCodec struct{}
+// func (noStreamingCodec) CheckBreak() bool { return false }
+// func (noStreamingCodec) hasElemSeparators() bool { return false }
+
+type noElemSeparators struct{}
+
+func (noElemSeparators) hasElemSeparators() (v bool) { return }
+func (noElemSeparators) recreateEncDriver(e encDriver) (v bool) { return }
+
+// bigenHelper.
+// Users must already slice the x completely, because we will not reslice.
+type bigenHelper struct {
+ x []byte // must be correctly sliced to appropriate len. slicing is a cost.
+ w encWriter
+}
+
+func (z bigenHelper) writeUint16(v uint16) {
+ bigen.PutUint16(z.x, v)
+ z.w.writeb(z.x)
+}
+
+func (z bigenHelper) writeUint32(v uint32) {
+ bigen.PutUint32(z.x, v)
+ z.w.writeb(z.x)
+}
+
+func (z bigenHelper) writeUint64(v uint64) {
+ bigen.PutUint64(z.x, v)
+ z.w.writeb(z.x)
+}
+
+type extTypeTagFn struct {
+ rtid uintptr
+ rtidptr uintptr
+ rt reflect.Type
+ tag uint64
+ ext Ext
+ _ [1]uint64 // padding
+}
+
+type extHandle []extTypeTagFn
+
+// AddExt registes an encode and decode function for a reflect.Type.
+// To deregister an Ext, call AddExt with nil encfn and/or nil decfn.
+//
+// Deprecated: Use SetBytesExt or SetInterfaceExt on the Handle instead.
+func (o *extHandle) AddExt(rt reflect.Type, tag byte,
+ encfn func(reflect.Value) ([]byte, error),
+ decfn func(reflect.Value, []byte) error) (err error) {
+ if encfn == nil || decfn == nil {
+ return o.SetExt(rt, uint64(tag), nil)
+ }
+ return o.SetExt(rt, uint64(tag), addExtWrapper{encfn, decfn})
+}
+
+// SetExt will set the extension for a tag and reflect.Type.
+// Note that the type must be a named type, and specifically not a pointer or Interface.
+// An error is returned if that is not honored.
+// To Deregister an ext, call SetExt with nil Ext.
+//
+// Deprecated: Use SetBytesExt or SetInterfaceExt on the Handle instead.
+func (o *extHandle) SetExt(rt reflect.Type, tag uint64, ext Ext) (err error) {
+ // o is a pointer, because we may need to initialize it
+ rk := rt.Kind()
+ for rk == reflect.Ptr {
+ rt = rt.Elem()
+ rk = rt.Kind()
+ }
+
+ if rt.PkgPath() == "" || rk == reflect.Interface { // || rk == reflect.Ptr {
+ return fmt.Errorf("codec.Handle.SetExt: Takes named type, not a pointer or interface: %v", rt)
+ }
+
+ rtid := rt2id(rt)
+ switch rtid {
+ case timeTypId, rawTypId, rawExtTypId:
+ // all natively supported type, so cannot have an extension
+ return // TODO: should we silently ignore, or return an error???
+ }
+ // if o == nil {
+ // return errors.New("codec.Handle.SetExt: extHandle not initialized")
+ // }
+ o2 := *o
+ // if o2 == nil {
+ // return errors.New("codec.Handle.SetExt: extHandle not initialized")
+ // }
+ for i := range o2 {
+ v := &o2[i]
+ if v.rtid == rtid {
+ v.tag, v.ext = tag, ext
+ return
+ }
+ }
+ rtidptr := rt2id(reflect.PtrTo(rt))
+ *o = append(o2, extTypeTagFn{rtid, rtidptr, rt, tag, ext, [1]uint64{}})
+ return
+}
+
+func (o extHandle) getExt(rtid uintptr) (v *extTypeTagFn) {
+ for i := range o {
+ v = &o[i]
+ if v.rtid == rtid || v.rtidptr == rtid {
+ return
+ }
+ }
+ return nil
+}
+
+func (o extHandle) getExtForTag(tag uint64) (v *extTypeTagFn) {
+ for i := range o {
+ v = &o[i]
+ if v.tag == tag {
+ return
+ }
+ }
+ return nil
+}
+
+type intf2impl struct {
+ rtid uintptr // for intf
+ impl reflect.Type
+ // _ [1]uint64 // padding // not-needed, as *intf2impl is never returned.
+}
+
+type intf2impls []intf2impl
+
+// Intf2Impl maps an interface to an implementing type.
+// This allows us support infering the concrete type
+// and populating it when passed an interface.
+// e.g. var v io.Reader can be decoded as a bytes.Buffer, etc.
+//
+// Passing a nil impl will clear the mapping.
+func (o *intf2impls) Intf2Impl(intf, impl reflect.Type) (err error) {
+ if impl != nil && !impl.Implements(intf) {
+ return fmt.Errorf("Intf2Impl: %v does not implement %v", impl, intf)
+ }
+ rtid := rt2id(intf)
+ o2 := *o
+ for i := range o2 {
+ v := &o2[i]
+ if v.rtid == rtid {
+ v.impl = impl
+ return
+ }
+ }
+ *o = append(o2, intf2impl{rtid, impl})
+ return
+}
+
+func (o intf2impls) intf2impl(rtid uintptr) (rv reflect.Value) {
+ for i := range o {
+ v := &o[i]
+ if v.rtid == rtid {
+ if v.impl == nil {
+ return
+ }
+ if v.impl.Kind() == reflect.Ptr {
+ return reflect.New(v.impl.Elem())
+ }
+ return reflect.New(v.impl).Elem()
+ }
+ }
+ return
+}
+
+type structFieldInfoFlag uint8
+
+const (
+ _ structFieldInfoFlag = 1 << iota
+ structFieldInfoFlagReady
+ structFieldInfoFlagOmitEmpty
+)
+
+func (x *structFieldInfoFlag) flagSet(f structFieldInfoFlag) {
+ *x = *x | f
+}
+
+func (x *structFieldInfoFlag) flagClr(f structFieldInfoFlag) {
+ *x = *x &^ f
+}
+
+func (x structFieldInfoFlag) flagGet(f structFieldInfoFlag) bool {
+ return x&f != 0
+}
+
+func (x structFieldInfoFlag) omitEmpty() bool {
+ return x.flagGet(structFieldInfoFlagOmitEmpty)
+}
+
+func (x structFieldInfoFlag) ready() bool {
+ return x.flagGet(structFieldInfoFlagReady)
+}
+
+type structFieldInfo struct {
+ encName string // encode name
+ fieldName string // field name
+
+ is [maxLevelsEmbedding]uint16 // (recursive/embedded) field index in struct
+ nis uint8 // num levels of embedding. if 1, then it's not embedded.
+ structFieldInfoFlag
+}
+
+func (si *structFieldInfo) setToZeroValue(v reflect.Value) {
+ if v, valid := si.field(v, false); valid {
+ v.Set(reflect.Zero(v.Type()))
+ }
+}
+
+// rv returns the field of the struct.
+// If anonymous, it returns an Invalid
+func (si *structFieldInfo) field(v reflect.Value, update bool) (rv2 reflect.Value, valid bool) {
+ // replicate FieldByIndex
+ for i, x := range si.is {
+ if uint8(i) == si.nis {
+ break
+ }
+ if v, valid = baseStructRv(v, update); !valid {
+ return
+ }
+ v = v.Field(int(x))
+ }
+
+ return v, true
+}
+
+// func (si *structFieldInfo) fieldval(v reflect.Value, update bool) reflect.Value {
+// v, _ = si.field(v, update)
+// return v
+// }
+
+func parseStructInfo(stag string) (toArray, omitEmpty bool, keytype valueType) {
+ keytype = valueTypeString // default
+ if stag == "" {
+ return
+ }
+ for i, s := range strings.Split(stag, ",") {
+ if i == 0 {
+ } else {
+ switch s {
+ case "omitempty":
+ omitEmpty = true
+ case "toarray":
+ toArray = true
+ case "int":
+ keytype = valueTypeInt
+ case "uint":
+ keytype = valueTypeUint
+ case "float":
+ keytype = valueTypeFloat
+ // case "bool":
+ // keytype = valueTypeBool
+ case "string":
+ keytype = valueTypeString
+ }
+ }
+ }
+ return
+}
+
+func (si *structFieldInfo) parseTag(stag string) {
+ // if fname == "" {
+ // panic(errNoFieldNameToStructFieldInfo)
+ // }
+
+ if stag == "" {
+ return
+ }
+ for i, s := range strings.Split(stag, ",") {
+ if i == 0 {
+ if s != "" {
+ si.encName = s
+ }
+ } else {
+ switch s {
+ case "omitempty":
+ si.flagSet(structFieldInfoFlagOmitEmpty)
+ // si.omitEmpty = true
+ // case "toarray":
+ // si.toArray = true
+ }
+ }
+ }
+}
+
+type sfiSortedByEncName []*structFieldInfo
+
+func (p sfiSortedByEncName) Len() int {
+ return len(p)
+}
+
+func (p sfiSortedByEncName) Less(i, j int) bool {
+ return p[i].encName < p[j].encName
+}
+
+func (p sfiSortedByEncName) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+const structFieldNodeNumToCache = 4
+
+type structFieldNodeCache struct {
+ rv [structFieldNodeNumToCache]reflect.Value
+ idx [structFieldNodeNumToCache]uint32
+ num uint8
+}
+
+func (x *structFieldNodeCache) get(key uint32) (fv reflect.Value, valid bool) {
+ for i, k := range &x.idx {
+ if uint8(i) == x.num {
+ return // break
+ }
+ if key == k {
+ return x.rv[i], true
+ }
+ }
+ return
+}
+
+func (x *structFieldNodeCache) tryAdd(fv reflect.Value, key uint32) {
+ if x.num < structFieldNodeNumToCache {
+ x.rv[x.num] = fv
+ x.idx[x.num] = key
+ x.num++
+ return
+ }
+}
+
+type structFieldNode struct {
+ v reflect.Value
+ cache2 structFieldNodeCache
+ cache3 structFieldNodeCache
+ update bool
+}
+
+func (x *structFieldNode) field(si *structFieldInfo) (fv reflect.Value) {
+ // return si.fieldval(x.v, x.update)
+ // Note: we only cache if nis=2 or nis=3 i.e. up to 2 levels of embedding
+ // This mostly saves us time on the repeated calls to v.Elem, v.Field, etc.
+ var valid bool
+ switch si.nis {
+ case 1:
+ fv = x.v.Field(int(si.is[0]))
+ case 2:
+ if fv, valid = x.cache2.get(uint32(si.is[0])); valid {
+ fv = fv.Field(int(si.is[1]))
+ return
+ }
+ fv = x.v.Field(int(si.is[0]))
+ if fv, valid = baseStructRv(fv, x.update); !valid {
+ return
+ }
+ x.cache2.tryAdd(fv, uint32(si.is[0]))
+ fv = fv.Field(int(si.is[1]))
+ case 3:
+ var key uint32 = uint32(si.is[0])<<16 | uint32(si.is[1])
+ if fv, valid = x.cache3.get(key); valid {
+ fv = fv.Field(int(si.is[2]))
+ return
+ }
+ fv = x.v.Field(int(si.is[0]))
+ if fv, valid = baseStructRv(fv, x.update); !valid {
+ return
+ }
+ fv = fv.Field(int(si.is[1]))
+ if fv, valid = baseStructRv(fv, x.update); !valid {
+ return
+ }
+ x.cache3.tryAdd(fv, key)
+ fv = fv.Field(int(si.is[2]))
+ default:
+ fv, _ = si.field(x.v, x.update)
+ }
+ return
+}
+
+func baseStructRv(v reflect.Value, update bool) (v2 reflect.Value, valid bool) {
+ for v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ if !update {
+ return
+ }
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ }
+ return v, true
+}
+
+type typeInfoFlag uint8
+
+const (
+ typeInfoFlagComparable = 1 << iota
+ typeInfoFlagIsZeroer
+ typeInfoFlagIsZeroerPtr
+)
+
+// typeInfo keeps information about each (non-ptr) type referenced in the encode/decode sequence.
+//
+// During an encode/decode sequence, we work as below:
+// - If base is a built in type, en/decode base value
+// - If base is registered as an extension, en/decode base value
+// - If type is binary(M/Unm)arshaler, call Binary(M/Unm)arshal method
+// - If type is text(M/Unm)arshaler, call Text(M/Unm)arshal method
+// - Else decode appropriately based on the reflect.Kind
+type typeInfo struct {
+ rt reflect.Type
+ elem reflect.Type
+ pkgpath string
+
+ rtid uintptr
+ // rv0 reflect.Value // saved zero value, used if immutableKind
+
+ numMeth uint16 // number of methods
+ kind uint8
+ chandir uint8
+
+ anyOmitEmpty bool // true if a struct, and any of the fields are tagged "omitempty"
+ toArray bool // whether this (struct) type should be encoded as an array
+ keyType valueType // if struct, how is the field name stored in a stream? default is string
+ mbs bool // base type (T or *T) is a MapBySlice
+
+ // ---- cpu cache line boundary?
+ sfiSort []*structFieldInfo // sorted. Used when enc/dec struct to map.
+ sfiSrc []*structFieldInfo // unsorted. Used when enc/dec struct to array.
+
+ key reflect.Type
+
+ // ---- cpu cache line boundary?
+ // sfis []structFieldInfo // all sfi, in src order, as created.
+ sfiNamesSort []byte // all names, with indexes into the sfiSort
+
+ // format of marshal type fields below: [btj][mu]p? OR csp?
+
+ bm bool // T is a binaryMarshaler
+ bmp bool // *T is a binaryMarshaler
+ bu bool // T is a binaryUnmarshaler
+ bup bool // *T is a binaryUnmarshaler
+ tm bool // T is a textMarshaler
+ tmp bool // *T is a textMarshaler
+ tu bool // T is a textUnmarshaler
+ tup bool // *T is a textUnmarshaler
+
+ jm bool // T is a jsonMarshaler
+ jmp bool // *T is a jsonMarshaler
+ ju bool // T is a jsonUnmarshaler
+ jup bool // *T is a jsonUnmarshaler
+ cs bool // T is a Selfer
+ csp bool // *T is a Selfer
+
+ // other flags, with individual bits representing if set.
+ flags typeInfoFlag
+
+ // _ [2]byte // padding
+ _ [3]uint64 // padding
+}
+
+func (ti *typeInfo) isFlag(f typeInfoFlag) bool {
+ return ti.flags&f != 0
+}
+
+func (ti *typeInfo) indexForEncName(name []byte) (index int16) {
+ var sn []byte
+ if len(name)+2 <= 32 {
+ var buf [32]byte // should not escape
+ sn = buf[:len(name)+2]
+ } else {
+ sn = make([]byte, len(name)+2)
+ }
+ copy(sn[1:], name)
+ sn[0], sn[len(sn)-1] = tiSep2(name), 0xff
+ j := bytes.Index(ti.sfiNamesSort, sn)
+ if j < 0 {
+ return -1
+ }
+ index = int16(uint16(ti.sfiNamesSort[j+len(sn)+1]) | uint16(ti.sfiNamesSort[j+len(sn)])<<8)
+ return
+}
+
+type rtid2ti struct {
+ rtid uintptr
+ ti *typeInfo
+}
+
+// TypeInfos caches typeInfo for each type on first inspection.
+//
+// It is configured with a set of tag keys, which are used to get
+// configuration for the type.
+type TypeInfos struct {
+ // infos: formerly map[uintptr]*typeInfo, now *[]rtid2ti, 2 words expected
+ infos atomicTypeInfoSlice
+ mu sync.Mutex
+ tags []string
+ _ [2]uint64 // padding
+}
+
+// NewTypeInfos creates a TypeInfos given a set of struct tags keys.
+//
+// This allows users customize the struct tag keys which contain configuration
+// of their types.
+func NewTypeInfos(tags []string) *TypeInfos {
+ return &TypeInfos{tags: tags}
+}
+
+func (x *TypeInfos) structTag(t reflect.StructTag) (s string) {
+ // check for tags: codec, json, in that order.
+ // this allows seamless support for many configured structs.
+ for _, x := range x.tags {
+ s = t.Get(x)
+ if s != "" {
+ return s
+ }
+ }
+ return
+}
+
+func (x *TypeInfos) find(s []rtid2ti, rtid uintptr) (idx int, ti *typeInfo) {
+ // binary search. adapted from sort/search.go.
+ // if sp == nil {
+ // return -1, nil
+ // }
+ // s := *sp
+ h, i, j := 0, 0, len(s)
+ for i < j {
+ h = i + (j-i)/2
+ if s[h].rtid < rtid {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ if i < len(s) && s[i].rtid == rtid {
+ return i, s[i].ti
+ }
+ return i, nil
+}
+
+func (x *TypeInfos) get(rtid uintptr, rt reflect.Type) (pti *typeInfo) {
+ sp := x.infos.load()
+ var idx int
+ if sp != nil {
+ idx, pti = x.find(sp, rtid)
+ if pti != nil {
+ return
+ }
+ }
+
+ rk := rt.Kind()
+
+ if rk == reflect.Ptr { // || (rk == reflect.Interface && rtid != intfTypId) {
+ panicv.errorf("invalid kind passed to TypeInfos.get: %v - %v", rk, rt)
+ }
+
+ // do not hold lock while computing this.
+ // it may lead to duplication, but that's ok.
+ ti := typeInfo{rt: rt, rtid: rtid, kind: uint8(rk), pkgpath: rt.PkgPath()}
+ // ti.rv0 = reflect.Zero(rt)
+
+ // ti.comparable = rt.Comparable()
+ ti.numMeth = uint16(rt.NumMethod())
+
+ ti.bm, ti.bmp = implIntf(rt, binaryMarshalerTyp)
+ ti.bu, ti.bup = implIntf(rt, binaryUnmarshalerTyp)
+ ti.tm, ti.tmp = implIntf(rt, textMarshalerTyp)
+ ti.tu, ti.tup = implIntf(rt, textUnmarshalerTyp)
+ ti.jm, ti.jmp = implIntf(rt, jsonMarshalerTyp)
+ ti.ju, ti.jup = implIntf(rt, jsonUnmarshalerTyp)
+ ti.cs, ti.csp = implIntf(rt, selferTyp)
+
+ b1, b2 := implIntf(rt, iszeroTyp)
+ if b1 {
+ ti.flags |= typeInfoFlagIsZeroer
+ }
+ if b2 {
+ ti.flags |= typeInfoFlagIsZeroerPtr
+ }
+ if rt.Comparable() {
+ ti.flags |= typeInfoFlagComparable
+ }
+
+ switch rk {
+ case reflect.Struct:
+ var omitEmpty bool
+ if f, ok := rt.FieldByName(structInfoFieldName); ok {
+ ti.toArray, omitEmpty, ti.keyType = parseStructInfo(x.structTag(f.Tag))
+ } else {
+ ti.keyType = valueTypeString
+ }
+ pp, pi := pool.tiLoad()
+ pv := pi.(*typeInfoLoadArray)
+ pv.etypes[0] = ti.rtid
+ // vv := typeInfoLoad{pv.fNames[:0], pv.encNames[:0], pv.etypes[:1], pv.sfis[:0]}
+ vv := typeInfoLoad{pv.etypes[:1], pv.sfis[:0]}
+ x.rget(rt, rtid, omitEmpty, nil, &vv)
+ // ti.sfis = vv.sfis
+ ti.sfiSrc, ti.sfiSort, ti.sfiNamesSort, ti.anyOmitEmpty = rgetResolveSFI(rt, vv.sfis, pv)
+ pp.Put(pi)
+ case reflect.Map:
+ ti.elem = rt.Elem()
+ ti.key = rt.Key()
+ case reflect.Slice:
+ ti.mbs, _ = implIntf(rt, mapBySliceTyp)
+ ti.elem = rt.Elem()
+ case reflect.Chan:
+ ti.elem = rt.Elem()
+ ti.chandir = uint8(rt.ChanDir())
+ case reflect.Array, reflect.Ptr:
+ ti.elem = rt.Elem()
+ }
+ // sfi = sfiSrc
+
+ x.mu.Lock()
+ sp = x.infos.load()
+ if sp == nil {
+ pti = &ti
+ vs := []rtid2ti{{rtid, pti}}
+ x.infos.store(vs)
+ } else {
+ idx, pti = x.find(sp, rtid)
+ if pti == nil {
+ pti = &ti
+ vs := make([]rtid2ti, len(sp)+1)
+ copy(vs, sp[:idx])
+ copy(vs[idx+1:], sp[idx:])
+ vs[idx] = rtid2ti{rtid, pti}
+ x.infos.store(vs)
+ }
+ }
+ x.mu.Unlock()
+ return
+}
+
+func (x *TypeInfos) rget(rt reflect.Type, rtid uintptr, omitEmpty bool,
+ indexstack []uint16, pv *typeInfoLoad) {
+ // Read up fields and store how to access the value.
+ //
+ // It uses go's rules for message selectors,
+ // which say that the field with the shallowest depth is selected.
+ //
+ // Note: we consciously use slices, not a map, to simulate a set.
+ // Typically, types have < 16 fields,
+ // and iteration using equals is faster than maps there
+ flen := rt.NumField()
+ if flen > (1< %v fields are not supported - has %v fields",
+ (1< maxLevelsEmbedding-1 {
+ panicv.errorf("codec: only supports up to %v depth of embedding - type has %v depth",
+ maxLevelsEmbedding-1, len(indexstack))
+ }
+ si.nis = uint8(len(indexstack)) + 1
+ copy(si.is[:], indexstack)
+ si.is[len(indexstack)] = j
+
+ if omitEmpty {
+ si.flagSet(structFieldInfoFlagOmitEmpty)
+ }
+ pv.sfis = append(pv.sfis, si)
+ }
+}
+
+func tiSep(name string) uint8 {
+ // (xn[0]%64) // (between 192-255 - outside ascii BMP)
+ // return 0xfe - (name[0] & 63)
+ // return 0xfe - (name[0] & 63) - uint8(len(name))
+ // return 0xfe - (name[0] & 63) - uint8(len(name)&63)
+ // return ((0xfe - (name[0] & 63)) & 0xf8) | (uint8(len(name) & 0x07))
+ return 0xfe - (name[0] & 63) - uint8(len(name)&63)
+}
+
+func tiSep2(name []byte) uint8 {
+ return 0xfe - (name[0] & 63) - uint8(len(name)&63)
+}
+
+// resolves the struct field info got from a call to rget.
+// Returns a trimmed, unsorted and sorted []*structFieldInfo.
+func rgetResolveSFI(rt reflect.Type, x []structFieldInfo, pv *typeInfoLoadArray) (
+ y, z []*structFieldInfo, ss []byte, anyOmitEmpty bool) {
+ sa := pv.sfiidx[:0]
+ sn := pv.b[:]
+ n := len(x)
+
+ var xn string
+ var ui uint16
+ var sep byte
+
+ for i := range x {
+ ui = uint16(i)
+ xn = x[i].encName // fieldName or encName? use encName for now.
+ if len(xn)+2 > cap(pv.b) {
+ sn = make([]byte, len(xn)+2)
+ } else {
+ sn = sn[:len(xn)+2]
+ }
+ // use a custom sep, so that misses are less frequent,
+ // since the sep (first char in search) is as unique as first char in field name.
+ sep = tiSep(xn)
+ sn[0], sn[len(sn)-1] = sep, 0xff
+ copy(sn[1:], xn)
+ j := bytes.Index(sa, sn)
+ if j == -1 {
+ sa = append(sa, sep)
+ sa = append(sa, xn...)
+ sa = append(sa, 0xff, byte(ui>>8), byte(ui))
+ } else {
+ index := uint16(sa[j+len(sn)+1]) | uint16(sa[j+len(sn)])<<8
+ // one of them must be reset to nil,
+ // and the index updated appropriately to the other one
+ if x[i].nis == x[index].nis {
+ } else if x[i].nis < x[index].nis {
+ sa[j+len(sn)], sa[j+len(sn)+1] = byte(ui>>8), byte(ui)
+ if x[index].ready() {
+ x[index].flagClr(structFieldInfoFlagReady)
+ n--
+ }
+ } else {
+ if x[i].ready() {
+ x[i].flagClr(structFieldInfoFlagReady)
+ n--
+ }
+ }
+ }
+
+ }
+ var w []structFieldInfo
+ sharingArray := len(x) <= typeInfoLoadArraySfisLen // sharing array with typeInfoLoadArray
+ if sharingArray {
+ w = make([]structFieldInfo, n)
+ }
+
+ // remove all the nils (non-ready)
+ y = make([]*structFieldInfo, n)
+ n = 0
+ var sslen int
+ for i := range x {
+ if !x[i].ready() {
+ continue
+ }
+ if !anyOmitEmpty && x[i].omitEmpty() {
+ anyOmitEmpty = true
+ }
+ if sharingArray {
+ w[n] = x[i]
+ y[n] = &w[n]
+ } else {
+ y[n] = &x[i]
+ }
+ sslen = sslen + len(x[i].encName) + 4
+ n++
+ }
+ if n != len(y) {
+ panicv.errorf("failure reading struct %v - expecting %d of %d valid fields, got %d",
+ rt, len(y), len(x), n)
+ }
+
+ z = make([]*structFieldInfo, len(y))
+ copy(z, y)
+ sort.Sort(sfiSortedByEncName(z))
+
+ sharingArray = len(sa) <= typeInfoLoadArraySfiidxLen
+ if sharingArray {
+ ss = make([]byte, 0, sslen)
+ } else {
+ ss = sa[:0] // reuse the newly made sa array if necessary
+ }
+ for i := range z {
+ xn = z[i].encName
+ sep = tiSep(xn)
+ ui = uint16(i)
+ ss = append(ss, sep)
+ ss = append(ss, xn...)
+ ss = append(ss, 0xff, byte(ui>>8), byte(ui))
+ }
+ return
+}
+
+func implIntf(rt, iTyp reflect.Type) (base bool, indir bool) {
+ return rt.Implements(iTyp), reflect.PtrTo(rt).Implements(iTyp)
+}
+
+// isEmptyStruct is only called from isEmptyValue, and checks if a struct is empty:
+// - does it implement IsZero() bool
+// - is it comparable, and can i compare directly using ==
+// - if checkStruct, then walk through the encodable fields
+// and check if they are empty or not.
+func isEmptyStruct(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
+ // v is a struct kind - no need to check again.
+ // We only check isZero on a struct kind, to reduce the amount of times
+ // that we lookup the rtid and typeInfo for each type as we walk the tree.
+
+ vt := v.Type()
+ rtid := rt2id(vt)
+ if tinfos == nil {
+ tinfos = defTypeInfos
+ }
+ ti := tinfos.get(rtid, vt)
+ if ti.rtid == timeTypId {
+ return rv2i(v).(time.Time).IsZero()
+ }
+ if ti.isFlag(typeInfoFlagIsZeroerPtr) && v.CanAddr() {
+ return rv2i(v.Addr()).(isZeroer).IsZero()
+ }
+ if ti.isFlag(typeInfoFlagIsZeroer) {
+ return rv2i(v).(isZeroer).IsZero()
+ }
+ if ti.isFlag(typeInfoFlagComparable) {
+ return rv2i(v) == rv2i(reflect.Zero(vt))
+ }
+ if !checkStruct {
+ return false
+ }
+ // We only care about what we can encode/decode,
+ // so that is what we use to check omitEmpty.
+ for _, si := range ti.sfiSrc {
+ sfv, valid := si.field(v, false)
+ if valid && !isEmptyValue(sfv, tinfos, deref, checkStruct) {
+ return false
+ }
+ }
+ return true
+}
+
+// func roundFloat(x float64) float64 {
+// t := math.Trunc(x)
+// if math.Abs(x-t) >= 0.5 {
+// return t + math.Copysign(1, x)
+// }
+// return t
+// }
+
+func panicToErr(h errstrDecorator, err *error) {
+ // Note: This method MUST be called directly from defer i.e. defer panicToErr ...
+ // else it seems the recover is not fully handled
+ if recoverPanicToErr {
+ if x := recover(); x != nil {
+ // fmt.Printf("panic'ing with: %v\n", x)
+ // debug.PrintStack()
+ panicValToErr(h, x, err)
+ }
+ }
+}
+
+func panicValToErr(h errstrDecorator, v interface{}, err *error) {
+ switch xerr := v.(type) {
+ case nil:
+ case error:
+ switch xerr {
+ case nil:
+ case io.EOF, io.ErrUnexpectedEOF, errEncoderNotInitialized, errDecoderNotInitialized:
+ // treat as special (bubble up)
+ *err = xerr
+ default:
+ h.wrapErrstr(xerr.Error(), err)
+ }
+ case string:
+ if xerr != "" {
+ h.wrapErrstr(xerr, err)
+ }
+ case fmt.Stringer:
+ if xerr != nil {
+ h.wrapErrstr(xerr.String(), err)
+ }
+ default:
+ h.wrapErrstr(v, err)
+ }
+}
+
+func isImmutableKind(k reflect.Kind) (v bool) {
+ return immutableKindsSet[k]
+}
+
+// ----
+
+type codecFnInfo struct {
+ ti *typeInfo
+ xfFn Ext
+ xfTag uint64
+ seq seqType
+ addrD bool
+ addrF bool // if addrD, this says whether decode function can take a value or a ptr
+ addrE bool
+ ready bool // ready to use
+}
+
+// codecFn encapsulates the captured variables and the encode function.
+// This way, we only do some calculations one times, and pass to the
+// code block that should be called (encapsulated in a function)
+// instead of executing the checks every time.
+type codecFn struct {
+ i codecFnInfo
+ fe func(*Encoder, *codecFnInfo, reflect.Value)
+ fd func(*Decoder, *codecFnInfo, reflect.Value)
+ _ [1]uint64 // padding
+}
+
+type codecRtidFn struct {
+ rtid uintptr
+ fn *codecFn
+}
+
+type codecFner struct {
+ // hh Handle
+ h *BasicHandle
+ s []codecRtidFn
+ be bool
+ js bool
+ _ [6]byte // padding
+ _ [3]uint64 // padding
+}
+
+func (c *codecFner) reset(hh Handle) {
+ bh := hh.getBasicHandle()
+ // only reset iff extensions changed or *TypeInfos changed
+ var hhSame = true &&
+ c.h == bh && c.h.TypeInfos == bh.TypeInfos &&
+ len(c.h.extHandle) == len(bh.extHandle) &&
+ (len(c.h.extHandle) == 0 || &c.h.extHandle[0] == &bh.extHandle[0])
+ if !hhSame {
+ // c.hh = hh
+ c.h, bh = bh, c.h // swap both
+ _, c.js = hh.(*JsonHandle)
+ c.be = hh.isBinary()
+ for i := range c.s {
+ c.s[i].fn.i.ready = false
+ }
+ }
+}
+
+func (c *codecFner) get(rt reflect.Type, checkFastpath, checkCodecSelfer bool) (fn *codecFn) {
+ rtid := rt2id(rt)
+
+ for _, x := range c.s {
+ if x.rtid == rtid {
+ // if rtid exists, then there's a *codenFn attached (non-nil)
+ fn = x.fn
+ if fn.i.ready {
+ return
+ }
+ break
+ }
+ }
+ var ti *typeInfo
+ if fn == nil {
+ fn = new(codecFn)
+ if c.s == nil {
+ c.s = make([]codecRtidFn, 0, 8)
+ }
+ c.s = append(c.s, codecRtidFn{rtid, fn})
+ } else {
+ ti = fn.i.ti
+ *fn = codecFn{}
+ fn.i.ti = ti
+ // fn.fe, fn.fd = nil, nil
+ }
+ fi := &(fn.i)
+ fi.ready = true
+ if ti == nil {
+ ti = c.h.getTypeInfo(rtid, rt)
+ fi.ti = ti
+ }
+
+ rk := reflect.Kind(ti.kind)
+
+ if checkCodecSelfer && (ti.cs || ti.csp) {
+ fn.fe = (*Encoder).selferMarshal
+ fn.fd = (*Decoder).selferUnmarshal
+ fi.addrF = true
+ fi.addrD = ti.csp
+ fi.addrE = ti.csp
+ } else if rtid == timeTypId {
+ fn.fe = (*Encoder).kTime
+ fn.fd = (*Decoder).kTime
+ } else if rtid == rawTypId {
+ fn.fe = (*Encoder).raw
+ fn.fd = (*Decoder).raw
+ } else if rtid == rawExtTypId {
+ fn.fe = (*Encoder).rawExt
+ fn.fd = (*Decoder).rawExt
+ fi.addrF = true
+ fi.addrD = true
+ fi.addrE = true
+ } else if xfFn := c.h.getExt(rtid); xfFn != nil {
+ fi.xfTag, fi.xfFn = xfFn.tag, xfFn.ext
+ fn.fe = (*Encoder).ext
+ fn.fd = (*Decoder).ext
+ fi.addrF = true
+ fi.addrD = true
+ if rk == reflect.Struct || rk == reflect.Array {
+ fi.addrE = true
+ }
+ } else if supportMarshalInterfaces && c.be && (ti.bm || ti.bmp) && (ti.bu || ti.bup) {
+ fn.fe = (*Encoder).binaryMarshal
+ fn.fd = (*Decoder).binaryUnmarshal
+ fi.addrF = true
+ fi.addrD = ti.bup
+ fi.addrE = ti.bmp
+ } else if supportMarshalInterfaces && !c.be && c.js && (ti.jm || ti.jmp) && (ti.ju || ti.jup) {
+ //If JSON, we should check JSONMarshal before textMarshal
+ fn.fe = (*Encoder).jsonMarshal
+ fn.fd = (*Decoder).jsonUnmarshal
+ fi.addrF = true
+ fi.addrD = ti.jup
+ fi.addrE = ti.jmp
+ } else if supportMarshalInterfaces && !c.be && (ti.tm || ti.tmp) && (ti.tu || ti.tup) {
+ fn.fe = (*Encoder).textMarshal
+ fn.fd = (*Decoder).textUnmarshal
+ fi.addrF = true
+ fi.addrD = ti.tup
+ fi.addrE = ti.tmp
+ } else {
+ if fastpathEnabled && checkFastpath && (rk == reflect.Map || rk == reflect.Slice) {
+ if ti.pkgpath == "" { // un-named slice or map
+ if idx := fastpathAV.index(rtid); idx != -1 {
+ fn.fe = fastpathAV[idx].encfn
+ fn.fd = fastpathAV[idx].decfn
+ fi.addrD = true
+ fi.addrF = false
+ }
+ } else {
+ // use mapping for underlying type if there
+ var rtu reflect.Type
+ if rk == reflect.Map {
+ rtu = reflect.MapOf(ti.key, ti.elem)
+ } else {
+ rtu = reflect.SliceOf(ti.elem)
+ }
+ rtuid := rt2id(rtu)
+ if idx := fastpathAV.index(rtuid); idx != -1 {
+ xfnf := fastpathAV[idx].encfn
+ xrt := fastpathAV[idx].rt
+ fn.fe = func(e *Encoder, xf *codecFnInfo, xrv reflect.Value) {
+ xfnf(e, xf, xrv.Convert(xrt))
+ }
+ fi.addrD = true
+ fi.addrF = false // meaning it can be an address(ptr) or a value
+ xfnf2 := fastpathAV[idx].decfn
+ fn.fd = func(d *Decoder, xf *codecFnInfo, xrv reflect.Value) {
+ if xrv.Kind() == reflect.Ptr {
+ xfnf2(d, xf, xrv.Convert(reflect.PtrTo(xrt)))
+ } else {
+ xfnf2(d, xf, xrv.Convert(xrt))
+ }
+ }
+ }
+ }
+ }
+ if fn.fe == nil && fn.fd == nil {
+ switch rk {
+ case reflect.Bool:
+ fn.fe = (*Encoder).kBool
+ fn.fd = (*Decoder).kBool
+ case reflect.String:
+ fn.fe = (*Encoder).kString
+ fn.fd = (*Decoder).kString
+ case reflect.Int:
+ fn.fd = (*Decoder).kInt
+ fn.fe = (*Encoder).kInt
+ case reflect.Int8:
+ fn.fe = (*Encoder).kInt8
+ fn.fd = (*Decoder).kInt8
+ case reflect.Int16:
+ fn.fe = (*Encoder).kInt16
+ fn.fd = (*Decoder).kInt16
+ case reflect.Int32:
+ fn.fe = (*Encoder).kInt32
+ fn.fd = (*Decoder).kInt32
+ case reflect.Int64:
+ fn.fe = (*Encoder).kInt64
+ fn.fd = (*Decoder).kInt64
+ case reflect.Uint:
+ fn.fd = (*Decoder).kUint
+ fn.fe = (*Encoder).kUint
+ case reflect.Uint8:
+ fn.fe = (*Encoder).kUint8
+ fn.fd = (*Decoder).kUint8
+ case reflect.Uint16:
+ fn.fe = (*Encoder).kUint16
+ fn.fd = (*Decoder).kUint16
+ case reflect.Uint32:
+ fn.fe = (*Encoder).kUint32
+ fn.fd = (*Decoder).kUint32
+ case reflect.Uint64:
+ fn.fe = (*Encoder).kUint64
+ fn.fd = (*Decoder).kUint64
+ case reflect.Uintptr:
+ fn.fe = (*Encoder).kUintptr
+ fn.fd = (*Decoder).kUintptr
+ case reflect.Float32:
+ fn.fe = (*Encoder).kFloat32
+ fn.fd = (*Decoder).kFloat32
+ case reflect.Float64:
+ fn.fe = (*Encoder).kFloat64
+ fn.fd = (*Decoder).kFloat64
+ case reflect.Invalid:
+ fn.fe = (*Encoder).kInvalid
+ fn.fd = (*Decoder).kErr
+ case reflect.Chan:
+ fi.seq = seqTypeChan
+ fn.fe = (*Encoder).kSlice
+ fn.fd = (*Decoder).kSlice
+ case reflect.Slice:
+ fi.seq = seqTypeSlice
+ fn.fe = (*Encoder).kSlice
+ fn.fd = (*Decoder).kSlice
+ case reflect.Array:
+ fi.seq = seqTypeArray
+ fn.fe = (*Encoder).kSlice
+ fi.addrF = false
+ fi.addrD = false
+ rt2 := reflect.SliceOf(ti.elem)
+ fn.fd = func(d *Decoder, xf *codecFnInfo, xrv reflect.Value) {
+ d.cfer().get(rt2, true, false).fd(d, xf, xrv.Slice(0, xrv.Len()))
+ }
+ // fn.fd = (*Decoder).kArray
+ case reflect.Struct:
+ if ti.anyOmitEmpty {
+ fn.fe = (*Encoder).kStruct
+ } else {
+ fn.fe = (*Encoder).kStructNoOmitempty
+ }
+ fn.fd = (*Decoder).kStruct
+ case reflect.Map:
+ fn.fe = (*Encoder).kMap
+ fn.fd = (*Decoder).kMap
+ case reflect.Interface:
+ // encode: reflect.Interface are handled already by preEncodeValue
+ fn.fd = (*Decoder).kInterface
+ fn.fe = (*Encoder).kErr
+ default:
+ // reflect.Ptr and reflect.Interface are handled already by preEncodeValue
+ fn.fe = (*Encoder).kErr
+ fn.fd = (*Decoder).kErr
+ }
+ }
+ }
+ return
+}
+
+type codecFnPooler struct {
+ cf *codecFner
+ cfp *sync.Pool
+ hh Handle
+}
+
+func (d *codecFnPooler) cfer() *codecFner {
+ if d.cf == nil {
+ var v interface{}
+ d.cfp, v = pool.codecFner()
+ d.cf = v.(*codecFner)
+ d.cf.reset(d.hh)
+ }
+ return d.cf
+}
+
+func (d *codecFnPooler) alwaysAtEnd() {
+ if d.cf != nil {
+ d.cfp.Put(d.cf)
+ d.cf, d.cfp = nil, nil
+ }
+}
+
+// ----
+
+// these "checkOverflow" functions must be inlinable, and not call anybody.
+// Overflow means that the value cannot be represented without wrapping/overflow.
+// Overflow=false does not mean that the value can be represented without losing precision
+// (especially for floating point).
+
+type checkOverflow struct{}
+
+// func (checkOverflow) Float16(f float64) (overflow bool) {
+// panicv.errorf("unimplemented")
+// if f < 0 {
+// f = -f
+// }
+// return math.MaxFloat32 < f && f <= math.MaxFloat64
+// }
+
+func (checkOverflow) Float32(v float64) (overflow bool) {
+ if v < 0 {
+ v = -v
+ }
+ return math.MaxFloat32 < v && v <= math.MaxFloat64
+}
+func (checkOverflow) Uint(v uint64, bitsize uint8) (overflow bool) {
+ if bitsize == 0 || bitsize >= 64 || v == 0 {
+ return
+ }
+ if trunc := (v << (64 - bitsize)) >> (64 - bitsize); v != trunc {
+ overflow = true
+ }
+ return
+}
+func (checkOverflow) Int(v int64, bitsize uint8) (overflow bool) {
+ if bitsize == 0 || bitsize >= 64 || v == 0 {
+ return
+ }
+ if trunc := (v << (64 - bitsize)) >> (64 - bitsize); v != trunc {
+ overflow = true
+ }
+ return
+}
+func (checkOverflow) SignedInt(v uint64) (overflow bool) {
+ //e.g. -127 to 128 for int8
+ pos := (v >> 63) == 0
+ ui2 := v & 0x7fffffffffffffff
+ if pos {
+ if ui2 > math.MaxInt64 {
+ overflow = true
+ }
+ } else {
+ if ui2 > math.MaxInt64-1 {
+ overflow = true
+ }
+ }
+ return
+}
+
+func (x checkOverflow) Float32V(v float64) float64 {
+ if x.Float32(v) {
+ panicv.errorf("float32 overflow: %v", v)
+ }
+ return v
+}
+func (x checkOverflow) UintV(v uint64, bitsize uint8) uint64 {
+ if x.Uint(v, bitsize) {
+ panicv.errorf("uint64 overflow: %v", v)
+ }
+ return v
+}
+func (x checkOverflow) IntV(v int64, bitsize uint8) int64 {
+ if x.Int(v, bitsize) {
+ panicv.errorf("int64 overflow: %v", v)
+ }
+ return v
+}
+func (x checkOverflow) SignedIntV(v uint64) int64 {
+ if x.SignedInt(v) {
+ panicv.errorf("uint64 to int64 overflow: %v", v)
+ }
+ return int64(v)
+}
+
+// ------------------ SORT -----------------
+
+func isNaN(f float64) bool { return f != f }
+
+// -----------------------
+
+type ioFlusher interface {
+ Flush() error
+}
+
+type ioPeeker interface {
+ Peek(int) ([]byte, error)
+}
+
+type ioBuffered interface {
+ Buffered() int
+}
+
+// -----------------------
+
+type intSlice []int64
+type uintSlice []uint64
+
+// type uintptrSlice []uintptr
+type floatSlice []float64
+type boolSlice []bool
+type stringSlice []string
+
+// type bytesSlice [][]byte
+
+func (p intSlice) Len() int { return len(p) }
+func (p intSlice) Less(i, j int) bool { return p[i] < p[j] }
+func (p intSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p uintSlice) Len() int { return len(p) }
+func (p uintSlice) Less(i, j int) bool { return p[i] < p[j] }
+func (p uintSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// func (p uintptrSlice) Len() int { return len(p) }
+// func (p uintptrSlice) Less(i, j int) bool { return p[i] < p[j] }
+// func (p uintptrSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p floatSlice) Len() int { return len(p) }
+func (p floatSlice) Less(i, j int) bool {
+ return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j])
+}
+func (p floatSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p stringSlice) Len() int { return len(p) }
+func (p stringSlice) Less(i, j int) bool { return p[i] < p[j] }
+func (p stringSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// func (p bytesSlice) Len() int { return len(p) }
+// func (p bytesSlice) Less(i, j int) bool { return bytes.Compare(p[i], p[j]) == -1 }
+// func (p bytesSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p boolSlice) Len() int { return len(p) }
+func (p boolSlice) Less(i, j int) bool { return !p[i] && p[j] }
+func (p boolSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// ---------------------
+
+type intRv struct {
+ v int64
+ r reflect.Value
+}
+type intRvSlice []intRv
+type uintRv struct {
+ v uint64
+ r reflect.Value
+}
+type uintRvSlice []uintRv
+type floatRv struct {
+ v float64
+ r reflect.Value
+}
+type floatRvSlice []floatRv
+type boolRv struct {
+ v bool
+ r reflect.Value
+}
+type boolRvSlice []boolRv
+type stringRv struct {
+ v string
+ r reflect.Value
+}
+type stringRvSlice []stringRv
+type bytesRv struct {
+ v []byte
+ r reflect.Value
+}
+type bytesRvSlice []bytesRv
+type timeRv struct {
+ v time.Time
+ r reflect.Value
+}
+type timeRvSlice []timeRv
+
+func (p intRvSlice) Len() int { return len(p) }
+func (p intRvSlice) Less(i, j int) bool { return p[i].v < p[j].v }
+func (p intRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p uintRvSlice) Len() int { return len(p) }
+func (p uintRvSlice) Less(i, j int) bool { return p[i].v < p[j].v }
+func (p uintRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p floatRvSlice) Len() int { return len(p) }
+func (p floatRvSlice) Less(i, j int) bool {
+ return p[i].v < p[j].v || isNaN(p[i].v) && !isNaN(p[j].v)
+}
+func (p floatRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p stringRvSlice) Len() int { return len(p) }
+func (p stringRvSlice) Less(i, j int) bool { return p[i].v < p[j].v }
+func (p stringRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p bytesRvSlice) Len() int { return len(p) }
+func (p bytesRvSlice) Less(i, j int) bool { return bytes.Compare(p[i].v, p[j].v) == -1 }
+func (p bytesRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p boolRvSlice) Len() int { return len(p) }
+func (p boolRvSlice) Less(i, j int) bool { return !p[i].v && p[j].v }
+func (p boolRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+func (p timeRvSlice) Len() int { return len(p) }
+func (p timeRvSlice) Less(i, j int) bool { return p[i].v.Before(p[j].v) }
+func (p timeRvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// -----------------
+
+type bytesI struct {
+ v []byte
+ i interface{}
+}
+
+type bytesISlice []bytesI
+
+func (p bytesISlice) Len() int { return len(p) }
+func (p bytesISlice) Less(i, j int) bool { return bytes.Compare(p[i].v, p[j].v) == -1 }
+func (p bytesISlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// -----------------
+
+type set []uintptr
+
+func (s *set) add(v uintptr) (exists bool) {
+ // e.ci is always nil, or len >= 1
+ x := *s
+ if x == nil {
+ x = make([]uintptr, 1, 8)
+ x[0] = v
+ *s = x
+ return
+ }
+ // typically, length will be 1. make this perform.
+ if len(x) == 1 {
+ if j := x[0]; j == 0 {
+ x[0] = v
+ } else if j == v {
+ exists = true
+ } else {
+ x = append(x, v)
+ *s = x
+ }
+ return
+ }
+ // check if it exists
+ for _, j := range x {
+ if j == v {
+ exists = true
+ return
+ }
+ }
+ // try to replace a "deleted" slot
+ for i, j := range x {
+ if j == 0 {
+ x[i] = v
+ return
+ }
+ }
+ // if unable to replace deleted slot, just append it.
+ x = append(x, v)
+ *s = x
+ return
+}
+
+func (s *set) remove(v uintptr) (exists bool) {
+ x := *s
+ if len(x) == 0 {
+ return
+ }
+ if len(x) == 1 {
+ if x[0] == v {
+ x[0] = 0
+ }
+ return
+ }
+ for i, j := range x {
+ if j == v {
+ exists = true
+ x[i] = 0 // set it to 0, as way to delete it.
+ // copy(x[i:], x[i+1:])
+ // x = x[:len(x)-1]
+ return
+ }
+ }
+ return
+}
+
+// ------
+
+// bitset types are better than [256]bool, because they permit the whole
+// bitset array being on a single cache line and use less memory.
+
+// given x > 0 and n > 0 and x is exactly 2^n, then pos/x === pos>>n AND pos%x === pos&(x-1).
+// consequently, pos/32 === pos>>5, pos/16 === pos>>4, pos/8 === pos>>3, pos%8 == pos&7
+
+type bitset256 [32]byte
+
+func (x *bitset256) isset(pos byte) bool {
+ return x[pos>>3]&(1<<(pos&7)) != 0
+}
+func (x *bitset256) issetv(pos byte) byte {
+ return x[pos>>3] & (1 << (pos & 7))
+}
+func (x *bitset256) set(pos byte) {
+ x[pos>>3] |= (1 << (pos & 7))
+}
+
+// func (x *bitset256) unset(pos byte) {
+// x[pos>>3] &^= (1 << (pos & 7))
+// }
+
+type bitset128 [16]byte
+
+func (x *bitset128) isset(pos byte) bool {
+ return x[pos>>3]&(1<<(pos&7)) != 0
+}
+func (x *bitset128) set(pos byte) {
+ x[pos>>3] |= (1 << (pos & 7))
+}
+
+// func (x *bitset128) unset(pos byte) {
+// x[pos>>3] &^= (1 << (pos & 7))
+// }
+
+type bitset32 [4]byte
+
+func (x *bitset32) isset(pos byte) bool {
+ return x[pos>>3]&(1<<(pos&7)) != 0
+}
+func (x *bitset32) set(pos byte) {
+ x[pos>>3] |= (1 << (pos & 7))
+}
+
+// func (x *bitset32) unset(pos byte) {
+// x[pos>>3] &^= (1 << (pos & 7))
+// }
+
+// type bit2set256 [64]byte
+
+// func (x *bit2set256) set(pos byte, v1, v2 bool) {
+// var pos2 uint8 = (pos & 3) << 1 // returning 0, 2, 4 or 6
+// if v1 {
+// x[pos>>2] |= 1 << (pos2 + 1)
+// }
+// if v2 {
+// x[pos>>2] |= 1 << pos2
+// }
+// }
+// func (x *bit2set256) get(pos byte) uint8 {
+// var pos2 uint8 = (pos & 3) << 1 // returning 0, 2, 4 or 6
+// return x[pos>>2] << (6 - pos2) >> 6 // 11000000 -> 00000011
+// }
+
+// ------------
+
+type pooler struct {
+ dn sync.Pool // for decNaked
+ cfn sync.Pool // for codecFner
+ tiload sync.Pool
+ strRv8, strRv16, strRv32, strRv64, strRv128 sync.Pool // for stringRV
+}
+
+func (p *pooler) init() {
+ p.strRv8.New = func() interface{} { return new([8]stringRv) }
+ p.strRv16.New = func() interface{} { return new([16]stringRv) }
+ p.strRv32.New = func() interface{} { return new([32]stringRv) }
+ p.strRv64.New = func() interface{} { return new([64]stringRv) }
+ p.strRv128.New = func() interface{} { return new([128]stringRv) }
+ p.dn.New = func() interface{} { x := new(decNaked); x.init(); return x }
+ p.tiload.New = func() interface{} { return new(typeInfoLoadArray) }
+ p.cfn.New = func() interface{} { return new(codecFner) }
+}
+
+func (p *pooler) stringRv8() (sp *sync.Pool, v interface{}) {
+ return &p.strRv8, p.strRv8.Get()
+}
+func (p *pooler) stringRv16() (sp *sync.Pool, v interface{}) {
+ return &p.strRv16, p.strRv16.Get()
+}
+func (p *pooler) stringRv32() (sp *sync.Pool, v interface{}) {
+ return &p.strRv32, p.strRv32.Get()
+}
+func (p *pooler) stringRv64() (sp *sync.Pool, v interface{}) {
+ return &p.strRv64, p.strRv64.Get()
+}
+func (p *pooler) stringRv128() (sp *sync.Pool, v interface{}) {
+ return &p.strRv128, p.strRv128.Get()
+}
+func (p *pooler) decNaked() (sp *sync.Pool, v interface{}) {
+ return &p.dn, p.dn.Get()
+}
+func (p *pooler) codecFner() (sp *sync.Pool, v interface{}) {
+ return &p.cfn, p.cfn.Get()
+}
+func (p *pooler) tiLoad() (sp *sync.Pool, v interface{}) {
+ return &p.tiload, p.tiload.Get()
+}
+
+// func (p *pooler) decNaked() (v *decNaked, f func(*decNaked) ) {
+// sp := &(p.dn)
+// vv := sp.Get()
+// return vv.(*decNaked), func(x *decNaked) { sp.Put(vv) }
+// }
+// func (p *pooler) decNakedGet() (v interface{}) {
+// return p.dn.Get()
+// }
+// func (p *pooler) codecFnerGet() (v interface{}) {
+// return p.cfn.Get()
+// }
+// func (p *pooler) tiLoadGet() (v interface{}) {
+// return p.tiload.Get()
+// }
+// func (p *pooler) decNakedPut(v interface{}) {
+// p.dn.Put(v)
+// }
+// func (p *pooler) codecFnerPut(v interface{}) {
+// p.cfn.Put(v)
+// }
+// func (p *pooler) tiLoadPut(v interface{}) {
+// p.tiload.Put(v)
+// }
+
+type panicHdl struct{}
+
+func (panicHdl) errorv(err error) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+func (panicHdl) errorstr(message string) {
+ if message != "" {
+ panic(message)
+ }
+}
+
+func (panicHdl) errorf(format string, params ...interface{}) {
+ if format != "" {
+ if len(params) == 0 {
+ panic(format)
+ } else {
+ panic(fmt.Sprintf(format, params...))
+ }
+ }
+}
+
+type errstrDecorator interface {
+ wrapErrstr(interface{}, *error)
+}
+
+type errstrDecoratorDef struct{}
+
+func (errstrDecoratorDef) wrapErrstr(v interface{}, e *error) { *e = fmt.Errorf("%v", v) }
+
+type must struct{}
+
+func (must) String(s string, err error) string {
+ if err != nil {
+ panicv.errorv(err)
+ }
+ return s
+}
+func (must) Int(s int64, err error) int64 {
+ if err != nil {
+ panicv.errorv(err)
+ }
+ return s
+}
+func (must) Uint(s uint64, err error) uint64 {
+ if err != nil {
+ panicv.errorv(err)
+ }
+ return s
+}
+func (must) Float(s float64, err error) float64 {
+ if err != nil {
+ panicv.errorv(err)
+ }
+ return s
+}
+
+// xdebugf prints the message in red on the terminal.
+// Use it in place of fmt.Printf (which it calls internally)
+func xdebugf(pattern string, args ...interface{}) {
+ var delim string
+ if len(pattern) > 0 && pattern[len(pattern)-1] != '\n' {
+ delim = "\n"
+ }
+ fmt.Printf("\033[1;31m"+pattern+delim+"\033[0m", args...)
+}
+
+// func isImmutableKind(k reflect.Kind) (v bool) {
+// return false ||
+// k == reflect.Int ||
+// k == reflect.Int8 ||
+// k == reflect.Int16 ||
+// k == reflect.Int32 ||
+// k == reflect.Int64 ||
+// k == reflect.Uint ||
+// k == reflect.Uint8 ||
+// k == reflect.Uint16 ||
+// k == reflect.Uint32 ||
+// k == reflect.Uint64 ||
+// k == reflect.Uintptr ||
+// k == reflect.Float32 ||
+// k == reflect.Float64 ||
+// k == reflect.Bool ||
+// k == reflect.String
+// }
+
+// func timeLocUTCName(tzint int16) string {
+// if tzint == 0 {
+// return "UTC"
+// }
+// var tzname = []byte("UTC+00:00")
+// //tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below.
+// //tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first
+// var tzhr, tzmin int16
+// if tzint < 0 {
+// tzname[3] = '-' // (TODO: verify. this works here)
+// tzhr, tzmin = -tzint/60, (-tzint)%60
+// } else {
+// tzhr, tzmin = tzint/60, tzint%60
+// }
+// tzname[4] = timeDigits[tzhr/10]
+// tzname[5] = timeDigits[tzhr%10]
+// tzname[7] = timeDigits[tzmin/10]
+// tzname[8] = timeDigits[tzmin%10]
+// return string(tzname)
+// //return time.FixedZone(string(tzname), int(tzint)*60)
+// }
diff --git a/vendor/github.com/ugorji/go/codec/helper_internal.go b/vendor/github.com/ugorji/go/codec/helper_internal.go
new file mode 100644
index 00000000..0cbd665e
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/helper_internal.go
@@ -0,0 +1,121 @@
+// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+// All non-std package dependencies live in this file,
+// so porting to different environment is easy (just update functions).
+
+func pruneSignExt(v []byte, pos bool) (n int) {
+ if len(v) < 2 {
+ } else if pos && v[0] == 0 {
+ for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ {
+ }
+ } else if !pos && v[0] == 0xff {
+ for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ {
+ }
+ }
+ return
+}
+
+// validate that this function is correct ...
+// culled from OGRE (Object-Oriented Graphics Rendering Engine)
+// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
+func halfFloatToFloatBits(yy uint16) (d uint32) {
+ y := uint32(yy)
+ s := (y >> 15) & 0x01
+ e := (y >> 10) & 0x1f
+ m := y & 0x03ff
+
+ if e == 0 {
+ if m == 0 { // plu or minus 0
+ return s << 31
+ }
+ // Denormalized number -- renormalize it
+ for (m & 0x00000400) == 0 {
+ m <<= 1
+ e -= 1
+ }
+ e += 1
+ const zz uint32 = 0x0400
+ m &= ^zz
+ } else if e == 31 {
+ if m == 0 { // Inf
+ return (s << 31) | 0x7f800000
+ }
+ return (s << 31) | 0x7f800000 | (m << 13) // NaN
+ }
+ e = e + (127 - 15)
+ m = m << 13
+ return (s << 31) | (e << 23) | m
+}
+
+// GrowCap will return a new capacity for a slice, given the following:
+// - oldCap: current capacity
+// - unit: in-memory size of an element
+// - num: number of elements to add
+func growCap(oldCap, unit, num int) (newCap int) {
+ // appendslice logic (if cap < 1024, *2, else *1.25):
+ // leads to many copy calls, especially when copying bytes.
+ // bytes.Buffer model (2*cap + n): much better for bytes.
+ // smarter way is to take the byte-size of the appended element(type) into account
+
+ // maintain 3 thresholds:
+ // t1: if cap <= t1, newcap = 2x
+ // t2: if cap <= t2, newcap = 1.75x
+ // t3: if cap <= t3, newcap = 1.5x
+ // else newcap = 1.25x
+ //
+ // t1, t2, t3 >= 1024 always.
+ // i.e. if unit size >= 16, then always do 2x or 1.25x (ie t1, t2, t3 are all same)
+ //
+ // With this, appending for bytes increase by:
+ // 100% up to 4K
+ // 75% up to 8K
+ // 50% up to 16K
+ // 25% beyond that
+
+ // unit can be 0 e.g. for struct{}{}; handle that appropriately
+ var t1, t2, t3 int // thresholds
+ if unit <= 1 {
+ t1, t2, t3 = 4*1024, 8*1024, 16*1024
+ } else if unit < 16 {
+ t3 = 16 / unit * 1024
+ t1 = t3 * 1 / 4
+ t2 = t3 * 2 / 4
+ } else {
+ t1, t2, t3 = 1024, 1024, 1024
+ }
+
+ var x int // temporary variable
+
+ // x is multiplier here: one of 5, 6, 7 or 8; incr of 25%, 50%, 75% or 100% respectively
+ if oldCap <= t1 { // [0,t1]
+ x = 8
+ } else if oldCap > t3 { // (t3,infinity]
+ x = 5
+ } else if oldCap <= t2 { // (t1,t2]
+ x = 7
+ } else { // (t2,t3]
+ x = 6
+ }
+ newCap = x * oldCap / 4
+
+ if num > 0 {
+ newCap += num
+ }
+
+ // ensure newCap is a multiple of 64 (if it is > 64) or 16.
+ if newCap > 64 {
+ if x = newCap % 64; x != 0 {
+ x = newCap / 64
+ newCap = 64 * (x + 1)
+ }
+ } else {
+ if x = newCap % 16; x != 0 {
+ x = newCap / 16
+ newCap = 16 * (x + 1)
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/ugorji/go/codec/helper_not_unsafe.go b/vendor/github.com/ugorji/go/codec/helper_not_unsafe.go
new file mode 100644
index 00000000..fd52690c
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/helper_not_unsafe.go
@@ -0,0 +1,272 @@
+// +build !go1.7 safe appengine
+
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "reflect"
+ "sync/atomic"
+ "time"
+)
+
+const safeMode = true
+
+// stringView returns a view of the []byte as a string.
+// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
+// In regular safe mode, it is an allocation and copy.
+//
+// Usage: Always maintain a reference to v while result of this call is in use,
+// and call keepAlive4BytesView(v) at point where done with view.
+func stringView(v []byte) string {
+ return string(v)
+}
+
+// bytesView returns a view of the string as a []byte.
+// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
+// In regular safe mode, it is an allocation and copy.
+//
+// Usage: Always maintain a reference to v while result of this call is in use,
+// and call keepAlive4BytesView(v) at point where done with view.
+func bytesView(v string) []byte {
+ return []byte(v)
+}
+
+func definitelyNil(v interface{}) bool {
+ // this is a best-effort option.
+ // We just return false, so we don't unnecessarily incur the cost of reflection this early.
+ return false
+}
+
+func rv2i(rv reflect.Value) interface{} {
+ return rv.Interface()
+}
+
+func rt2id(rt reflect.Type) uintptr {
+ return reflect.ValueOf(rt).Pointer()
+}
+
+func rv2rtid(rv reflect.Value) uintptr {
+ return reflect.ValueOf(rv.Type()).Pointer()
+}
+
+func i2rtid(i interface{}) uintptr {
+ return reflect.ValueOf(reflect.TypeOf(i)).Pointer()
+}
+
+// --------------------------
+
+func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
+ switch v.Kind() {
+ case reflect.Invalid:
+ return true
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ if deref {
+ if v.IsNil() {
+ return true
+ }
+ return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
+ }
+ return v.IsNil()
+ case reflect.Struct:
+ return isEmptyStruct(v, tinfos, deref, checkStruct)
+ }
+ return false
+}
+
+// --------------------------
+// type ptrToRvMap struct{}
+
+// func (*ptrToRvMap) init() {}
+// func (*ptrToRvMap) get(i interface{}) reflect.Value {
+// return reflect.ValueOf(i).Elem()
+// }
+
+// --------------------------
+type atomicTypeInfoSlice struct { // expected to be 2 words
+ v atomic.Value
+}
+
+func (x *atomicTypeInfoSlice) load() []rtid2ti {
+ i := x.v.Load()
+ if i == nil {
+ return nil
+ }
+ return i.([]rtid2ti)
+}
+
+func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
+ x.v.Store(p)
+}
+
+// --------------------------
+func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
+ rv.SetBytes(d.rawBytes())
+}
+
+func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
+ rv.SetString(d.d.DecodeString())
+}
+
+func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
+ rv.SetBool(d.d.DecodeBool())
+}
+
+func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
+ rv.Set(reflect.ValueOf(d.d.DecodeTime()))
+}
+
+func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+ fv := d.d.DecodeFloat64()
+ if chkOvf.Float32(fv) {
+ d.errorf("float32 overflow: %v", fv)
+ }
+ rv.SetFloat(fv)
+}
+
+func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
+ rv.SetFloat(d.d.DecodeFloat64())
+}
+
+func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
+ rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
+}
+
+func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
+ rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 8))
+}
+
+func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
+ rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 16))
+}
+
+func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
+ rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 32))
+}
+
+func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
+ rv.SetInt(d.d.DecodeInt64())
+}
+
+func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
+ rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
+}
+
+func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
+ rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
+}
+
+func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
+ rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 8))
+}
+
+func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
+ rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 16))
+}
+
+func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
+ rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 32))
+}
+
+func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
+ rv.SetUint(d.d.DecodeUint64())
+}
+
+// ----------------
+
+func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeBool(rv.Bool())
+}
+
+func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeTime(rv2i(rv).(time.Time))
+}
+
+func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeString(cUTF8, rv.String())
+}
+
+func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeFloat64(rv.Float())
+}
+
+func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeFloat32(float32(rv.Float()))
+}
+
+func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeInt(rv.Int())
+}
+
+func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeUint(rv.Uint())
+}
+
+func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
+ e.e.EncodeUint(rv.Uint())
+}
+
+// // keepAlive4BytesView maintains a reference to the input parameter for bytesView.
+// //
+// // Usage: call this at point where done with the bytes view.
+// func keepAlive4BytesView(v string) {}
+
+// // keepAlive4BytesView maintains a reference to the input parameter for stringView.
+// //
+// // Usage: call this at point where done with the string view.
+// func keepAlive4StringView(v []byte) {}
+
+// func definitelyNil(v interface{}) bool {
+// rv := reflect.ValueOf(v)
+// switch rv.Kind() {
+// case reflect.Invalid:
+// return true
+// case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Slice, reflect.Map, reflect.Func:
+// return rv.IsNil()
+// default:
+// return false
+// }
+// }
diff --git a/vendor/github.com/ugorji/go/codec/helper_unsafe.go b/vendor/github.com/ugorji/go/codec/helper_unsafe.go
new file mode 100644
index 00000000..e3df60ab
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/helper_unsafe.go
@@ -0,0 +1,639 @@
+// +build !safe
+// +build !appengine
+// +build go1.7
+
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "reflect"
+ "sync/atomic"
+ "time"
+ "unsafe"
+)
+
+// This file has unsafe variants of some helper methods.
+// NOTE: See helper_not_unsafe.go for the usage information.
+
+// var zeroRTv [4]uintptr
+
+const safeMode = false
+const unsafeFlagIndir = 1 << 7 // keep in sync with GO_ROOT/src/reflect/value.go
+
+type unsafeString struct {
+ Data unsafe.Pointer
+ Len int
+}
+
+type unsafeSlice struct {
+ Data unsafe.Pointer
+ Len int
+ Cap int
+}
+
+type unsafeIntf struct {
+ typ unsafe.Pointer
+ word unsafe.Pointer
+}
+
+type unsafeReflectValue struct {
+ typ unsafe.Pointer
+ ptr unsafe.Pointer
+ flag uintptr
+}
+
+func stringView(v []byte) string {
+ if len(v) == 0 {
+ return ""
+ }
+ bx := (*unsafeSlice)(unsafe.Pointer(&v))
+ return *(*string)(unsafe.Pointer(&unsafeString{bx.Data, bx.Len}))
+}
+
+func bytesView(v string) []byte {
+ if len(v) == 0 {
+ return zeroByteSlice
+ }
+ sx := (*unsafeString)(unsafe.Pointer(&v))
+ return *(*[]byte)(unsafe.Pointer(&unsafeSlice{sx.Data, sx.Len, sx.Len}))
+}
+
+func definitelyNil(v interface{}) bool {
+ // There is no global way of checking if an interface is nil.
+ // For true references (map, ptr, func, chan), you can just look
+ // at the word of the interface. However, for slices, you have to dereference
+ // the word, and get a pointer to the 3-word interface value.
+ //
+ // However, the following are cheap calls
+ // - TypeOf(interface): cheap 2-line call.
+ // - ValueOf(interface{}): expensive
+ // - type.Kind: cheap call through an interface
+ // - Value.Type(): cheap call
+ // except it's a method value (e.g. r.Read, which implies that it is a Func)
+
+ return ((*unsafeIntf)(unsafe.Pointer(&v))).word == nil
+}
+
+func rv2i(rv reflect.Value) interface{} {
+ // TODO: consider a more generally-known optimization for reflect.Value ==> Interface
+ //
+ // Currently, we use this fragile method that taps into implememtation details from
+ // the source go stdlib reflect/value.go, and trims the implementation.
+
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ // true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
+ var ptr unsafe.Pointer
+ if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
+ ptr = *(*unsafe.Pointer)(urv.ptr)
+ } else {
+ ptr = urv.ptr
+ }
+ return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
+}
+
+func rt2id(rt reflect.Type) uintptr {
+ return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
+}
+
+func rv2rtid(rv reflect.Value) uintptr {
+ return uintptr((*unsafeReflectValue)(unsafe.Pointer(&rv)).typ)
+}
+
+func i2rtid(i interface{}) uintptr {
+ return uintptr(((*unsafeIntf)(unsafe.Pointer(&i))).typ)
+}
+
+// --------------------------
+
+func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&v))
+ if urv.flag == 0 {
+ return true
+ }
+ switch v.Kind() {
+ case reflect.Invalid:
+ return true
+ case reflect.String:
+ return (*unsafeString)(urv.ptr).Len == 0
+ case reflect.Slice:
+ return (*unsafeSlice)(urv.ptr).Len == 0
+ case reflect.Bool:
+ return !*(*bool)(urv.ptr)
+ case reflect.Int:
+ return *(*int)(urv.ptr) == 0
+ case reflect.Int8:
+ return *(*int8)(urv.ptr) == 0
+ case reflect.Int16:
+ return *(*int16)(urv.ptr) == 0
+ case reflect.Int32:
+ return *(*int32)(urv.ptr) == 0
+ case reflect.Int64:
+ return *(*int64)(urv.ptr) == 0
+ case reflect.Uint:
+ return *(*uint)(urv.ptr) == 0
+ case reflect.Uint8:
+ return *(*uint8)(urv.ptr) == 0
+ case reflect.Uint16:
+ return *(*uint16)(urv.ptr) == 0
+ case reflect.Uint32:
+ return *(*uint32)(urv.ptr) == 0
+ case reflect.Uint64:
+ return *(*uint64)(urv.ptr) == 0
+ case reflect.Uintptr:
+ return *(*uintptr)(urv.ptr) == 0
+ case reflect.Float32:
+ return *(*float32)(urv.ptr) == 0
+ case reflect.Float64:
+ return *(*float64)(urv.ptr) == 0
+ case reflect.Interface:
+ isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
+ if deref {
+ if isnil {
+ return true
+ }
+ return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
+ }
+ return isnil
+ case reflect.Ptr:
+ // isnil := urv.ptr == nil (not sufficient, as a pointer value encodes the type)
+ isnil := urv.ptr == nil || *(*unsafe.Pointer)(urv.ptr) == nil
+ if deref {
+ if isnil {
+ return true
+ }
+ return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
+ }
+ return isnil
+ case reflect.Struct:
+ return isEmptyStruct(v, tinfos, deref, checkStruct)
+ case reflect.Map, reflect.Array, reflect.Chan:
+ return v.Len() == 0
+ }
+ return false
+}
+
+// --------------------------
+
+// atomicTypeInfoSlice contains length and pointer to the array for a slice.
+// It is expected to be 2 words.
+//
+// Previously, we atomically loaded and stored the length and array pointer separately,
+// which could lead to some races.
+// We now just atomically store and load the pointer to the value directly.
+
+type atomicTypeInfoSlice struct { // expected to be 2 words
+ l int // length of the data array (must be first in struct, for 64-bit alignment necessary for 386)
+ v unsafe.Pointer // data array - Pointer (not uintptr) to maintain GC reference
+}
+
+func (x *atomicTypeInfoSlice) load() []rtid2ti {
+ xp := unsafe.Pointer(x)
+ x2 := *(*atomicTypeInfoSlice)(atomic.LoadPointer(&xp))
+ if x2.l == 0 {
+ return nil
+ }
+ return *(*[]rtid2ti)(unsafe.Pointer(&unsafeSlice{Data: x2.v, Len: x2.l, Cap: x2.l}))
+}
+
+func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
+ s := (*unsafeSlice)(unsafe.Pointer(&p))
+ xp := unsafe.Pointer(x)
+ atomic.StorePointer(&xp, unsafe.Pointer(&atomicTypeInfoSlice{l: s.Len, v: s.Data}))
+}
+
+// --------------------------
+func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*[]byte)(urv.ptr) = d.rawBytes()
+}
+
+func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*string)(urv.ptr) = d.d.DecodeString()
+}
+
+func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*bool)(urv.ptr) = d.d.DecodeBool()
+}
+
+func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*time.Time)(urv.ptr) = d.d.DecodeTime()
+}
+
+func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+ fv := d.d.DecodeFloat64()
+ if chkOvf.Float32(fv) {
+ d.errorf("float32 overflow: %v", fv)
+ }
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*float32)(urv.ptr) = float32(fv)
+}
+
+func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*float64)(urv.ptr) = d.d.DecodeFloat64()
+}
+
+func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*int)(urv.ptr) = int(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
+}
+
+func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*int8)(urv.ptr) = int8(chkOvf.IntV(d.d.DecodeInt64(), 8))
+}
+
+func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*int16)(urv.ptr) = int16(chkOvf.IntV(d.d.DecodeInt64(), 16))
+}
+
+func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*int32)(urv.ptr) = int32(chkOvf.IntV(d.d.DecodeInt64(), 32))
+}
+
+func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*int64)(urv.ptr) = d.d.DecodeInt64()
+}
+
+func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*uint)(urv.ptr) = uint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
+}
+
+func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*uintptr)(urv.ptr) = uintptr(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
+}
+
+func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*uint8)(urv.ptr) = uint8(chkOvf.UintV(d.d.DecodeUint64(), 8))
+}
+
+func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*uint16)(urv.ptr) = uint16(chkOvf.UintV(d.d.DecodeUint64(), 16))
+}
+
+func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*uint32)(urv.ptr) = uint32(chkOvf.UintV(d.d.DecodeUint64(), 32))
+}
+
+func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
+ urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ *(*uint64)(urv.ptr) = d.d.DecodeUint64()
+}
+
+// ------------
+
+func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeBool(*(*bool)(v.ptr))
+}
+
+func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeTime(*(*time.Time)(v.ptr))
+}
+
+func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeString(cUTF8, *(*string)(v.ptr))
+}
+
+func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeFloat64(*(*float64)(v.ptr))
+}
+
+func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeFloat32(*(*float32)(v.ptr))
+}
+
+func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeInt(int64(*(*int)(v.ptr)))
+}
+
+func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeInt(int64(*(*int8)(v.ptr)))
+}
+
+func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeInt(int64(*(*int16)(v.ptr)))
+}
+
+func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeInt(int64(*(*int32)(v.ptr)))
+}
+
+func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeInt(int64(*(*int64)(v.ptr)))
+}
+
+func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeUint(uint64(*(*uint)(v.ptr)))
+}
+
+func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeUint(uint64(*(*uint8)(v.ptr)))
+}
+
+func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeUint(uint64(*(*uint16)(v.ptr)))
+}
+
+func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeUint(uint64(*(*uint32)(v.ptr)))
+}
+
+func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeUint(uint64(*(*uint64)(v.ptr)))
+}
+
+func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
+ v := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+ e.e.EncodeUint(uint64(*(*uintptr)(v.ptr)))
+}
+
+// ------------
+
+// func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
+// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+// // if urv.flag&unsafeFlagIndir != 0 {
+// // urv.ptr = *(*unsafe.Pointer)(urv.ptr)
+// // }
+// *(*[]byte)(urv.ptr) = d.rawBytes()
+// }
+
+// func rv0t(rt reflect.Type) reflect.Value {
+// ut := (*unsafeIntf)(unsafe.Pointer(&rt))
+// // we need to determine whether ifaceIndir, and then whether to just pass 0 as the ptr
+// uv := unsafeReflectValue{ut.word, &zeroRTv, flag(rt.Kind())}
+// return *(*reflect.Value)(unsafe.Pointer(&uv})
+// }
+
+// func rv2i(rv reflect.Value) interface{} {
+// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+// // true references (map, func, chan, ptr - NOT slice) may be double-referenced as flagIndir
+// var ptr unsafe.Pointer
+// // kk := reflect.Kind(urv.flag & (1<<5 - 1))
+// // if (kk == reflect.Map || kk == reflect.Ptr || kk == reflect.Chan || kk == reflect.Func) && urv.flag&unsafeFlagIndir != 0 {
+// if refBitset.isset(byte(urv.flag&(1<<5-1))) && urv.flag&unsafeFlagIndir != 0 {
+// ptr = *(*unsafe.Pointer)(urv.ptr)
+// } else {
+// ptr = urv.ptr
+// }
+// return *(*interface{})(unsafe.Pointer(&unsafeIntf{typ: urv.typ, word: ptr}))
+// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
+// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+// }
+
+// func definitelyNil(v interface{}) bool {
+// var ui *unsafeIntf = (*unsafeIntf)(unsafe.Pointer(&v))
+// if ui.word == nil {
+// return true
+// }
+// var tk = reflect.TypeOf(v).Kind()
+// return (tk == reflect.Interface || tk == reflect.Slice) && *(*unsafe.Pointer)(ui.word) == nil
+// fmt.Printf(">>>> definitely nil: isnil: %v, TYPE: \t%T, word: %v, *word: %v, type: %v, nil: %v\n",
+// v == nil, v, word, *((*unsafe.Pointer)(word)), ui.typ, nil)
+// }
+
+// func keepAlive4BytesView(v string) {
+// runtime.KeepAlive(v)
+// }
+
+// func keepAlive4StringView(v []byte) {
+// runtime.KeepAlive(v)
+// }
+
+// func rt2id(rt reflect.Type) uintptr {
+// return uintptr(((*unsafeIntf)(unsafe.Pointer(&rt))).word)
+// // var i interface{} = rt
+// // // ui := (*unsafeIntf)(unsafe.Pointer(&i))
+// // return ((*unsafeIntf)(unsafe.Pointer(&i))).word
+// }
+
+// func rv2i(rv reflect.Value) interface{} {
+// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+// // non-reference type: already indir
+// // reference type: depend on flagIndir property ('cos maybe was double-referenced)
+// // const (unsafeRvFlagKindMask = 1<<5 - 1 , unsafeRvFlagIndir = 1 << 7 )
+// // rvk := reflect.Kind(urv.flag & (1<<5 - 1))
+// // if (rvk == reflect.Chan ||
+// // rvk == reflect.Func ||
+// // rvk == reflect.Interface ||
+// // rvk == reflect.Map ||
+// // rvk == reflect.Ptr ||
+// // rvk == reflect.UnsafePointer) && urv.flag&(1<<8) != 0 {
+// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
+// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
+// // }
+// if urv.flag&(1<<5-1) == uintptr(reflect.Map) && urv.flag&(1<<7) != 0 {
+// // fmt.Printf(">>>>> ---- double indirect reference: %v, %v\n", rvk, rv.Type())
+// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
+// }
+// // fmt.Printf(">>>>> ++++ direct reference: %v, %v\n", rvk, rv.Type())
+// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+// }
+
+// const (
+// unsafeRvFlagKindMask = 1<<5 - 1
+// unsafeRvKindDirectIface = 1 << 5
+// unsafeRvFlagIndir = 1 << 7
+// unsafeRvFlagAddr = 1 << 8
+// unsafeRvFlagMethod = 1 << 9
+
+// _USE_RV_INTERFACE bool = false
+// _UNSAFE_RV_DEBUG = true
+// )
+
+// type unsafeRtype struct {
+// _ [2]uintptr
+// _ uint32
+// _ uint8
+// _ uint8
+// _ uint8
+// kind uint8
+// _ [2]uintptr
+// _ int32
+// }
+
+// func _rv2i(rv reflect.Value) interface{} {
+// // Note: From use,
+// // - it's never an interface
+// // - the only calls here are for ifaceIndir types.
+// // (though that conditional is wrong)
+// // To know for sure, we need the value of t.kind (which is not exposed).
+// //
+// // Need to validate the path: type is indirect ==> only value is indirect ==> default (value is direct)
+// // - Type indirect, Value indirect: ==> numbers, boolean, slice, struct, array, string
+// // - Type Direct, Value indirect: ==> map???
+// // - Type Direct, Value direct: ==> pointers, unsafe.Pointer, func, chan, map
+// //
+// // TRANSLATES TO:
+// // if typeIndirect { } else if valueIndirect { } else { }
+// //
+// // Since we don't deal with funcs, then "flagNethod" is unset, and can be ignored.
+
+// if _USE_RV_INTERFACE {
+// return rv.Interface()
+// }
+// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+
+// // if urv.flag&unsafeRvFlagMethod != 0 || urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
+// // println("***** IS flag method or interface: delegating to rv.Interface()")
+// // return rv.Interface()
+// // }
+
+// // if urv.flag&unsafeRvFlagKindMask == uintptr(reflect.Interface) {
+// // println("***** IS Interface: delegate to rv.Interface")
+// // return rv.Interface()
+// // }
+// // if urv.flag&unsafeRvFlagKindMask&unsafeRvKindDirectIface == 0 {
+// // if urv.flag&unsafeRvFlagAddr == 0 {
+// // println("***** IS ifaceIndir typ")
+// // // ui := unsafeIntf{word: urv.ptr, typ: urv.typ}
+// // // return *(*interface{})(unsafe.Pointer(&ui))
+// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+// // }
+// // } else if urv.flag&unsafeRvFlagIndir != 0 {
+// // println("***** IS flagindir")
+// // // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
+// // } else {
+// // println("***** NOT flagindir")
+// // return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+// // }
+// // println("***** default: delegate to rv.Interface")
+
+// urt := (*unsafeRtype)(unsafe.Pointer(urv.typ))
+// if _UNSAFE_RV_DEBUG {
+// fmt.Printf(">>>> start: %v: ", rv.Type())
+// fmt.Printf("%v - %v\n", *urv, *urt)
+// }
+// if urt.kind&unsafeRvKindDirectIface == 0 {
+// if _UNSAFE_RV_DEBUG {
+// fmt.Printf("**** +ifaceIndir type: %v\n", rv.Type())
+// }
+// // println("***** IS ifaceIndir typ")
+// // if true || urv.flag&unsafeRvFlagAddr == 0 {
+// // // println(" ***** IS NOT addr")
+// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+// // }
+// } else if urv.flag&unsafeRvFlagIndir != 0 {
+// if _UNSAFE_RV_DEBUG {
+// fmt.Printf("**** +flagIndir type: %v\n", rv.Type())
+// }
+// // println("***** IS flagindir")
+// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: *(*unsafe.Pointer)(urv.ptr), typ: urv.typ}))
+// } else {
+// if _UNSAFE_RV_DEBUG {
+// fmt.Printf("**** -flagIndir type: %v\n", rv.Type())
+// }
+// // println("***** NOT flagindir")
+// return *(*interface{})(unsafe.Pointer(&unsafeIntf{word: urv.ptr, typ: urv.typ}))
+// }
+// // println("***** default: delegating to rv.Interface()")
+// // return rv.Interface()
+// }
+
+// var staticM0 = make(map[string]uint64)
+// var staticI0 = (int32)(-5)
+
+// func staticRv2iTest() {
+// i0 := (int32)(-5)
+// m0 := make(map[string]uint16)
+// m0["1"] = 1
+// for _, i := range []interface{}{
+// (int)(7),
+// (uint)(8),
+// (int16)(-9),
+// (uint16)(19),
+// (uintptr)(77),
+// (bool)(true),
+// float32(-32.7),
+// float64(64.9),
+// complex(float32(19), 5),
+// complex(float64(-32), 7),
+// [4]uint64{1, 2, 3, 4},
+// (chan<- int)(nil), // chan,
+// rv2i, // func
+// io.Writer(ioutil.Discard),
+// make(map[string]uint),
+// (map[string]uint)(nil),
+// staticM0,
+// m0,
+// &m0,
+// i0,
+// &i0,
+// &staticI0,
+// &staticM0,
+// []uint32{6, 7, 8},
+// "abc",
+// Raw{},
+// RawExt{},
+// &Raw{},
+// &RawExt{},
+// unsafe.Pointer(&i0),
+// } {
+// i2 := rv2i(reflect.ValueOf(i))
+// eq := reflect.DeepEqual(i, i2)
+// fmt.Printf(">>>> %v == %v? %v\n", i, i2, eq)
+// }
+// // os.Exit(0)
+// }
+
+// func init() {
+// staticRv2iTest()
+// }
+
+// func rv2i(rv reflect.Value) interface{} {
+// if _USE_RV_INTERFACE || rv.Kind() == reflect.Interface || rv.CanAddr() {
+// return rv.Interface()
+// }
+// // var i interface{}
+// // ui := (*unsafeIntf)(unsafe.Pointer(&i))
+// var ui unsafeIntf
+// urv := (*unsafeReflectValue)(unsafe.Pointer(&rv))
+// // fmt.Printf("urv: flag: %b, typ: %b, ptr: %b\n", urv.flag, uintptr(urv.typ), uintptr(urv.ptr))
+// if (urv.flag&unsafeRvFlagKindMask)&unsafeRvKindDirectIface == 0 {
+// if urv.flag&unsafeRvFlagAddr != 0 {
+// println("***** indirect and addressable! Needs typed move - delegate to rv.Interface()")
+// return rv.Interface()
+// }
+// println("****** indirect type/kind")
+// ui.word = urv.ptr
+// } else if urv.flag&unsafeRvFlagIndir != 0 {
+// println("****** unsafe rv flag indir")
+// ui.word = *(*unsafe.Pointer)(urv.ptr)
+// } else {
+// println("****** default: assign prt to word directly")
+// ui.word = urv.ptr
+// }
+// // ui.word = urv.ptr
+// ui.typ = urv.typ
+// // fmt.Printf("(pointers) ui.typ: %p, word: %p\n", ui.typ, ui.word)
+// // fmt.Printf("(binary) ui.typ: %b, word: %b\n", uintptr(ui.typ), uintptr(ui.word))
+// return *(*interface{})(unsafe.Pointer(&ui))
+// // return i
+// }
diff --git a/vendor/github.com/ugorji/go/codec/json.go b/vendor/github.com/ugorji/go/codec/json.go
new file mode 100644
index 00000000..bdd19966
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/json.go
@@ -0,0 +1,1423 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+// By default, this json support uses base64 encoding for bytes, because you cannot
+// store and read any arbitrary string in json (only unicode).
+// However, the user can configre how to encode/decode bytes.
+//
+// This library specifically supports UTF-8 for encoding and decoding only.
+//
+// Note that the library will happily encode/decode things which are not valid
+// json e.g. a map[int64]string. We do it for consistency. With valid json,
+// we will encode and decode appropriately.
+// Users can specify their map type if necessary to force it.
+//
+// Note:
+// - we cannot use strconv.Quote and strconv.Unquote because json quotes/unquotes differently.
+// We implement it here.
+
+// Top-level methods of json(End|Dec)Driver (which are implementations of (en|de)cDriver
+// MUST not call one-another.
+
+import (
+ "bytes"
+ "encoding/base64"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+)
+
+//--------------------------------
+
+var jsonLiterals = [...]byte{
+ '"', 't', 'r', 'u', 'e', '"',
+ '"', 'f', 'a', 'l', 's', 'e', '"',
+ '"', 'n', 'u', 'l', 'l', '"',
+}
+
+const (
+ jsonLitTrueQ = 0
+ jsonLitTrue = 1
+ jsonLitFalseQ = 6
+ jsonLitFalse = 7
+ jsonLitNullQ = 13
+ jsonLitNull = 14
+)
+
+const (
+ jsonU4Chk2 = '0'
+ jsonU4Chk1 = 'a' - 10
+ jsonU4Chk0 = 'A' - 10
+
+ jsonScratchArrayLen = 64
+)
+
+const (
+ // If !jsonValidateSymbols, decoding will be faster, by skipping some checks:
+ // - If we see first character of null, false or true,
+ // do not validate subsequent characters.
+ // - e.g. if we see a n, assume null and skip next 3 characters,
+ // and do not validate they are ull.
+ // P.S. Do not expect a significant decoding boost from this.
+ jsonValidateSymbols = true
+
+ jsonSpacesOrTabsLen = 128
+
+ jsonAlwaysReturnInternString = false
+)
+
+var (
+ // jsonTabs and jsonSpaces are used as caches for indents
+ jsonTabs, jsonSpaces [jsonSpacesOrTabsLen]byte
+
+ jsonCharHtmlSafeSet bitset128
+ jsonCharSafeSet bitset128
+ jsonCharWhitespaceSet bitset256
+ jsonNumSet bitset256
+)
+
+func init() {
+ for i := 0; i < jsonSpacesOrTabsLen; i++ {
+ jsonSpaces[i] = ' '
+ jsonTabs[i] = '\t'
+ }
+
+ // populate the safe values as true: note: ASCII control characters are (0-31)
+ // jsonCharSafeSet: all true except (0-31) " \
+ // jsonCharHtmlSafeSet: all true except (0-31) " \ < > &
+ var i byte
+ for i = 32; i < utf8.RuneSelf; i++ {
+ switch i {
+ case '"', '\\':
+ case '<', '>', '&':
+ jsonCharSafeSet.set(i) // = true
+ default:
+ jsonCharSafeSet.set(i)
+ jsonCharHtmlSafeSet.set(i)
+ }
+ }
+ for i = 0; i <= utf8.RuneSelf; i++ {
+ switch i {
+ case ' ', '\t', '\r', '\n':
+ jsonCharWhitespaceSet.set(i)
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-':
+ jsonNumSet.set(i)
+ }
+ }
+}
+
+// ----------------
+
+type jsonEncDriverTypical struct {
+ w encWriter
+ // w *encWriterSwitch
+ b *[jsonScratchArrayLen]byte
+ tw bool // term white space
+ c containerState
+}
+
+func (e *jsonEncDriverTypical) typical() {}
+
+func (e *jsonEncDriverTypical) reset(ee *jsonEncDriver) {
+ e.w = ee.ew
+ // e.w = &ee.e.encWriterSwitch
+ e.b = &ee.b
+ e.tw = ee.h.TermWhitespace
+ e.c = 0
+}
+
+func (e *jsonEncDriverTypical) WriteArrayStart(length int) {
+ e.w.writen1('[')
+ e.c = containerArrayStart
+}
+
+func (e *jsonEncDriverTypical) WriteArrayElem() {
+ if e.c != containerArrayStart {
+ e.w.writen1(',')
+ }
+ e.c = containerArrayElem
+}
+
+func (e *jsonEncDriverTypical) WriteArrayEnd() {
+ e.w.writen1(']')
+ e.c = containerArrayEnd
+}
+
+func (e *jsonEncDriverTypical) WriteMapStart(length int) {
+ e.w.writen1('{')
+ e.c = containerMapStart
+}
+
+func (e *jsonEncDriverTypical) WriteMapElemKey() {
+ if e.c != containerMapStart {
+ e.w.writen1(',')
+ }
+ e.c = containerMapKey
+}
+
+func (e *jsonEncDriverTypical) WriteMapElemValue() {
+ e.w.writen1(':')
+ e.c = containerMapValue
+}
+
+func (e *jsonEncDriverTypical) WriteMapEnd() {
+ e.w.writen1('}')
+ e.c = containerMapEnd
+}
+
+func (e *jsonEncDriverTypical) EncodeBool(b bool) {
+ if b {
+ e.w.writeb(jsonLiterals[jsonLitTrue : jsonLitTrue+4])
+ } else {
+ e.w.writeb(jsonLiterals[jsonLitFalse : jsonLitFalse+5])
+ }
+}
+
+func (e *jsonEncDriverTypical) EncodeFloat64(f float64) {
+ fmt, prec := jsonFloatStrconvFmtPrec(f)
+ e.w.writeb(strconv.AppendFloat(e.b[:0], f, fmt, prec, 64))
+}
+
+func (e *jsonEncDriverTypical) EncodeInt(v int64) {
+ e.w.writeb(strconv.AppendInt(e.b[:0], v, 10))
+}
+
+func (e *jsonEncDriverTypical) EncodeUint(v uint64) {
+ e.w.writeb(strconv.AppendUint(e.b[:0], v, 10))
+}
+
+func (e *jsonEncDriverTypical) EncodeFloat32(f float32) {
+ e.EncodeFloat64(float64(f))
+}
+
+func (e *jsonEncDriverTypical) atEndOfEncode() {
+ if e.tw {
+ e.w.writen1(' ')
+ }
+}
+
+// ----------------
+
+type jsonEncDriverGeneric struct {
+ w encWriter // encWriter // *encWriterSwitch
+ b *[jsonScratchArrayLen]byte
+ c containerState
+ // ds string // indent string
+ di int8 // indent per
+ d bool // indenting?
+ dt bool // indent using tabs
+ dl uint16 // indent level
+ ks bool // map key as string
+ is byte // integer as string
+ tw bool // term white space
+ _ [7]byte // padding
+}
+
+// indent is done as below:
+// - newline and indent are added before each mapKey or arrayElem
+// - newline and indent are added before each ending,
+// except there was no entry (so we can have {} or [])
+
+func (e *jsonEncDriverGeneric) reset(ee *jsonEncDriver) {
+ e.w = ee.ew
+ e.b = &ee.b
+ e.tw = ee.h.TermWhitespace
+ e.c = 0
+ e.d, e.dt, e.dl, e.di = false, false, 0, 0
+ h := ee.h
+ if h.Indent > 0 {
+ e.d = true
+ e.di = int8(h.Indent)
+ } else if h.Indent < 0 {
+ e.d = true
+ e.dt = true
+ e.di = int8(-h.Indent)
+ }
+ e.ks = h.MapKeyAsString
+ e.is = h.IntegerAsString
+}
+
+func (e *jsonEncDriverGeneric) WriteArrayStart(length int) {
+ if e.d {
+ e.dl++
+ }
+ e.w.writen1('[')
+ e.c = containerArrayStart
+}
+
+func (e *jsonEncDriverGeneric) WriteArrayElem() {
+ if e.c != containerArrayStart {
+ e.w.writen1(',')
+ }
+ if e.d {
+ e.writeIndent()
+ }
+ e.c = containerArrayElem
+}
+
+func (e *jsonEncDriverGeneric) WriteArrayEnd() {
+ if e.d {
+ e.dl--
+ if e.c != containerArrayStart {
+ e.writeIndent()
+ }
+ }
+ e.w.writen1(']')
+ e.c = containerArrayEnd
+}
+
+func (e *jsonEncDriverGeneric) WriteMapStart(length int) {
+ if e.d {
+ e.dl++
+ }
+ e.w.writen1('{')
+ e.c = containerMapStart
+}
+
+func (e *jsonEncDriverGeneric) WriteMapElemKey() {
+ if e.c != containerMapStart {
+ e.w.writen1(',')
+ }
+ if e.d {
+ e.writeIndent()
+ }
+ e.c = containerMapKey
+}
+
+func (e *jsonEncDriverGeneric) WriteMapElemValue() {
+ if e.d {
+ e.w.writen2(':', ' ')
+ } else {
+ e.w.writen1(':')
+ }
+ e.c = containerMapValue
+}
+
+func (e *jsonEncDriverGeneric) WriteMapEnd() {
+ if e.d {
+ e.dl--
+ if e.c != containerMapStart {
+ e.writeIndent()
+ }
+ }
+ e.w.writen1('}')
+ e.c = containerMapEnd
+}
+
+func (e *jsonEncDriverGeneric) writeIndent() {
+ e.w.writen1('\n')
+ x := int(e.di) * int(e.dl)
+ if e.dt {
+ for x > jsonSpacesOrTabsLen {
+ e.w.writeb(jsonTabs[:])
+ x -= jsonSpacesOrTabsLen
+ }
+ e.w.writeb(jsonTabs[:x])
+ } else {
+ for x > jsonSpacesOrTabsLen {
+ e.w.writeb(jsonSpaces[:])
+ x -= jsonSpacesOrTabsLen
+ }
+ e.w.writeb(jsonSpaces[:x])
+ }
+}
+
+func (e *jsonEncDriverGeneric) EncodeBool(b bool) {
+ if e.ks && e.c == containerMapKey {
+ if b {
+ e.w.writeb(jsonLiterals[jsonLitTrueQ : jsonLitTrueQ+6])
+ } else {
+ e.w.writeb(jsonLiterals[jsonLitFalseQ : jsonLitFalseQ+7])
+ }
+ } else {
+ if b {
+ e.w.writeb(jsonLiterals[jsonLitTrue : jsonLitTrue+4])
+ } else {
+ e.w.writeb(jsonLiterals[jsonLitFalse : jsonLitFalse+5])
+ }
+ }
+}
+
+func (e *jsonEncDriverGeneric) EncodeFloat64(f float64) {
+ // instead of using 'g', specify whether to use 'e' or 'f'
+ fmt, prec := jsonFloatStrconvFmtPrec(f)
+
+ var blen int
+ if e.ks && e.c == containerMapKey {
+ blen = 2 + len(strconv.AppendFloat(e.b[1:1], f, fmt, prec, 64))
+ e.b[0] = '"'
+ e.b[blen-1] = '"'
+ } else {
+ blen = len(strconv.AppendFloat(e.b[:0], f, fmt, prec, 64))
+ }
+ e.w.writeb(e.b[:blen])
+}
+
+func (e *jsonEncDriverGeneric) EncodeInt(v int64) {
+ x := e.is
+ if x == 'A' || x == 'L' && (v > 1<<53 || v < -(1<<53)) || (e.ks && e.c == containerMapKey) {
+ blen := 2 + len(strconv.AppendInt(e.b[1:1], v, 10))
+ e.b[0] = '"'
+ e.b[blen-1] = '"'
+ e.w.writeb(e.b[:blen])
+ return
+ }
+ e.w.writeb(strconv.AppendInt(e.b[:0], v, 10))
+}
+
+func (e *jsonEncDriverGeneric) EncodeUint(v uint64) {
+ x := e.is
+ if x == 'A' || x == 'L' && v > 1<<53 || (e.ks && e.c == containerMapKey) {
+ blen := 2 + len(strconv.AppendUint(e.b[1:1], v, 10))
+ e.b[0] = '"'
+ e.b[blen-1] = '"'
+ e.w.writeb(e.b[:blen])
+ return
+ }
+ e.w.writeb(strconv.AppendUint(e.b[:0], v, 10))
+}
+
+func (e *jsonEncDriverGeneric) EncodeFloat32(f float32) {
+ // e.encodeFloat(float64(f), 32)
+ // always encode all floats as IEEE 64-bit floating point.
+ // It also ensures that we can decode in full precision even if into a float32,
+ // as what is written is always to float64 precision.
+ e.EncodeFloat64(float64(f))
+}
+
+func (e *jsonEncDriverGeneric) atEndOfEncode() {
+ if e.tw {
+ if e.d {
+ e.w.writen1('\n')
+ } else {
+ e.w.writen1(' ')
+ }
+ }
+}
+
+// --------------------
+
+type jsonEncDriver struct {
+ noBuiltInTypes
+ e *Encoder
+ h *JsonHandle
+ ew encWriter // encWriter // *encWriterSwitch
+ se extWrapper
+ // ---- cpu cache line boundary?
+ bs []byte // scratch
+ // ---- cpu cache line boundary?
+ b [jsonScratchArrayLen]byte // scratch (encode time,
+}
+
+func (e *jsonEncDriver) EncodeNil() {
+ // We always encode nil as just null (never in quotes)
+ // This allows us to easily decode if a nil in the json stream
+ // ie if initial token is n.
+ e.ew.writeb(jsonLiterals[jsonLitNull : jsonLitNull+4])
+
+ // if e.h.MapKeyAsString && e.c == containerMapKey {
+ // e.ew.writeb(jsonLiterals[jsonLitNullQ : jsonLitNullQ+6])
+ // } else {
+ // e.ew.writeb(jsonLiterals[jsonLitNull : jsonLitNull+4])
+ // }
+}
+
+func (e *jsonEncDriver) EncodeTime(t time.Time) {
+ // Do NOT use MarshalJSON, as it allocates internally.
+ // instead, we call AppendFormat directly, using our scratch buffer (e.b)
+ if t.IsZero() {
+ e.EncodeNil()
+ } else {
+ e.b[0] = '"'
+ b := t.AppendFormat(e.b[1:1], time.RFC3339Nano)
+ e.b[len(b)+1] = '"'
+ e.ew.writeb(e.b[:len(b)+2])
+ }
+ // v, err := t.MarshalJSON(); if err != nil { e.e.error(err) } e.ew.writeb(v)
+}
+
+func (e *jsonEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, en *Encoder) {
+ if v := ext.ConvertExt(rv); v == nil {
+ e.EncodeNil()
+ } else {
+ en.encode(v)
+ }
+}
+
+func (e *jsonEncDriver) EncodeRawExt(re *RawExt, en *Encoder) {
+ // only encodes re.Value (never re.Data)
+ if re.Value == nil {
+ e.EncodeNil()
+ } else {
+ en.encode(re.Value)
+ }
+}
+
+func (e *jsonEncDriver) EncodeString(c charEncoding, v string) {
+ e.quoteStr(v)
+}
+
+func (e *jsonEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+ // if encoding raw bytes and RawBytesExt is configured, use it to encode
+ if v == nil {
+ e.EncodeNil()
+ return
+ }
+ if c == cRAW {
+ if e.se.InterfaceExt != nil {
+ e.EncodeExt(v, 0, &e.se, e.e)
+ return
+ }
+
+ slen := base64.StdEncoding.EncodedLen(len(v))
+ if cap(e.bs) >= slen+2 {
+ e.bs = e.bs[:slen+2]
+ } else {
+ e.bs = make([]byte, slen+2)
+ }
+ e.bs[0] = '"'
+ base64.StdEncoding.Encode(e.bs[1:], v)
+ e.bs[slen+1] = '"'
+ e.ew.writeb(e.bs)
+ } else {
+ e.quoteStr(stringView(v))
+ }
+}
+
+func (e *jsonEncDriver) EncodeAsis(v []byte) {
+ e.ew.writeb(v)
+}
+
+func (e *jsonEncDriver) quoteStr(s string) {
+ // adapted from std pkg encoding/json
+ const hex = "0123456789abcdef"
+ w := e.ew
+ htmlasis := e.h.HTMLCharsAsIs
+ w.writen1('"')
+ var start int
+ for i, slen := 0, len(s); i < slen; {
+ // encode all bytes < 0x20 (except \r, \n).
+ // also encode < > & to prevent security holes when served to some browsers.
+ if b := s[i]; b < utf8.RuneSelf {
+ // if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
+ // if (htmlasis && jsonCharSafeSet.isset(b)) || jsonCharHtmlSafeSet.isset(b) {
+ if jsonCharHtmlSafeSet.isset(b) || (htmlasis && jsonCharSafeSet.isset(b)) {
+ i++
+ continue
+ }
+ if start < i {
+ w.writestr(s[start:i])
+ }
+ switch b {
+ case '\\', '"':
+ w.writen2('\\', b)
+ case '\n':
+ w.writen2('\\', 'n')
+ case '\r':
+ w.writen2('\\', 'r')
+ case '\b':
+ w.writen2('\\', 'b')
+ case '\f':
+ w.writen2('\\', 'f')
+ case '\t':
+ w.writen2('\\', 't')
+ default:
+ w.writestr(`\u00`)
+ w.writen2(hex[b>>4], hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ c, size := utf8.DecodeRuneInString(s[i:])
+ if c == utf8.RuneError && size == 1 {
+ if start < i {
+ w.writestr(s[start:i])
+ }
+ w.writestr(`\ufffd`)
+ i += size
+ start = i
+ continue
+ }
+ // U+2028 is LINE SEPARATOR. U+2029 is PARAGRAPH SEPARATOR.
+ // Both technically valid JSON, but bomb on JSONP, so fix here unconditionally.
+ if c == '\u2028' || c == '\u2029' {
+ if start < i {
+ w.writestr(s[start:i])
+ }
+ w.writestr(`\u202`)
+ w.writen1(hex[c&0xF])
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ }
+ if start < len(s) {
+ w.writestr(s[start:])
+ }
+ w.writen1('"')
+}
+
+type jsonDecDriver struct {
+ noBuiltInTypes
+ d *Decoder
+ h *JsonHandle
+ r decReader // *decReaderSwitch // decReader
+ se extWrapper
+
+ // ---- writable fields during execution --- *try* to keep in sep cache line
+
+ c containerState
+ // tok is used to store the token read right after skipWhiteSpace.
+ tok uint8
+ fnull bool // found null from appendStringAsBytes
+ bs []byte // scratch. Initialized from b. Used for parsing strings or numbers.
+ bstr [8]byte // scratch used for string \UXXX parsing
+ // ---- cpu cache line boundary?
+ b [jsonScratchArrayLen]byte // scratch 1, used for parsing strings or numbers or time.Time
+ b2 [jsonScratchArrayLen]byte // scratch 2, used only for readUntil, decNumBytes
+
+ _ [3]uint64 // padding
+ // n jsonNum
+}
+
+// func jsonIsWS(b byte) bool {
+// // return b == ' ' || b == '\t' || b == '\r' || b == '\n'
+// return jsonCharWhitespaceSet.isset(b)
+// }
+
+func (d *jsonDecDriver) uncacheRead() {
+ if d.tok != 0 {
+ d.r.unreadn1()
+ d.tok = 0
+ }
+}
+
+func (d *jsonDecDriver) ReadMapStart() int {
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ const xc uint8 = '{'
+ if d.tok != xc {
+ d.d.errorf("read map - expect char '%c' but got char '%c'", xc, d.tok)
+ }
+ d.tok = 0
+ d.c = containerMapStart
+ return -1
+}
+
+func (d *jsonDecDriver) ReadArrayStart() int {
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ const xc uint8 = '['
+ if d.tok != xc {
+ d.d.errorf("read array - expect char '%c' but got char '%c'", xc, d.tok)
+ }
+ d.tok = 0
+ d.c = containerArrayStart
+ return -1
+}
+
+func (d *jsonDecDriver) CheckBreak() bool {
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ return d.tok == '}' || d.tok == ']'
+}
+
+// For the ReadXXX methods below, we could just delegate to helper functions
+// readContainerState(c containerState, xc uint8, check bool)
+// - ReadArrayElem would become:
+// readContainerState(containerArrayElem, ',', d.c != containerArrayStart)
+//
+// However, until mid-stack inlining comes in go1.11 which supports inlining of
+// one-liners, we explicitly write them all 5 out to elide the extra func call.
+//
+// TODO: For Go 1.11, if inlined, consider consolidating these.
+
+func (d *jsonDecDriver) ReadArrayElem() {
+ const xc uint8 = ','
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ if d.c != containerArrayStart {
+ if d.tok != xc {
+ d.d.errorf("read array element - expect char '%c' but got char '%c'", xc, d.tok)
+ }
+ d.tok = 0
+ }
+ d.c = containerArrayElem
+}
+
+func (d *jsonDecDriver) ReadArrayEnd() {
+ const xc uint8 = ']'
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ if d.tok != xc {
+ d.d.errorf("read array end - expect char '%c' but got char '%c'", xc, d.tok)
+ }
+ d.tok = 0
+ d.c = containerArrayEnd
+}
+
+func (d *jsonDecDriver) ReadMapElemKey() {
+ const xc uint8 = ','
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ if d.c != containerMapStart {
+ if d.tok != xc {
+ d.d.errorf("read map key - expect char '%c' but got char '%c'", xc, d.tok)
+ }
+ d.tok = 0
+ }
+ d.c = containerMapKey
+}
+
+func (d *jsonDecDriver) ReadMapElemValue() {
+ const xc uint8 = ':'
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ if d.tok != xc {
+ d.d.errorf("read map value - expect char '%c' but got char '%c'", xc, d.tok)
+ }
+ d.tok = 0
+ d.c = containerMapValue
+}
+
+func (d *jsonDecDriver) ReadMapEnd() {
+ const xc uint8 = '}'
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ if d.tok != xc {
+ d.d.errorf("read map end - expect char '%c' but got char '%c'", xc, d.tok)
+ }
+ d.tok = 0
+ d.c = containerMapEnd
+}
+
+func (d *jsonDecDriver) readLit(length, fromIdx uint8) {
+ bs := d.r.readx(int(length))
+ d.tok = 0
+ if jsonValidateSymbols && !bytes.Equal(bs, jsonLiterals[fromIdx:fromIdx+length]) {
+ d.d.errorf("expecting %s: got %s", jsonLiterals[fromIdx:fromIdx+length], bs)
+ return
+ }
+}
+
+func (d *jsonDecDriver) TryDecodeAsNil() bool {
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ // we shouldn't try to see if "null" was here, right?
+ // only the plain string: `null` denotes a nil (ie not quotes)
+ if d.tok == 'n' {
+ d.readLit(3, jsonLitNull+1) // (n)ull
+ return true
+ }
+ return false
+}
+
+func (d *jsonDecDriver) DecodeBool() (v bool) {
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ fquot := d.c == containerMapKey && d.tok == '"'
+ if fquot {
+ d.tok = d.r.readn1()
+ }
+ switch d.tok {
+ case 'f':
+ d.readLit(4, jsonLitFalse+1) // (f)alse
+ // v = false
+ case 't':
+ d.readLit(3, jsonLitTrue+1) // (t)rue
+ v = true
+ default:
+ d.d.errorf("decode bool: got first char %c", d.tok)
+ // v = false // "unreachable"
+ }
+ if fquot {
+ d.r.readn1()
+ }
+ return
+}
+
+func (d *jsonDecDriver) DecodeTime() (t time.Time) {
+ // read string, and pass the string into json.unmarshal
+ d.appendStringAsBytes()
+ if d.fnull {
+ return
+ }
+ t, err := time.Parse(time.RFC3339, stringView(d.bs))
+ if err != nil {
+ d.d.errorv(err)
+ }
+ return
+}
+
+func (d *jsonDecDriver) ContainerType() (vt valueType) {
+ // check container type by checking the first char
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+
+ // optimize this, so we don't do 4 checks but do one computation.
+ // return jsonContainerSet[d.tok]
+
+ // ContainerType is mostly called for Map and Array,
+ // so this conditional is good enough (max 2 checks typically)
+ if b := d.tok; b == '{' {
+ return valueTypeMap
+ } else if b == '[' {
+ return valueTypeArray
+ } else if b == 'n' {
+ return valueTypeNil
+ } else if b == '"' {
+ return valueTypeString
+ }
+ return valueTypeUnset
+}
+
+func (d *jsonDecDriver) decNumBytes() (bs []byte) {
+ // stores num bytes in d.bs
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ if d.tok == '"' {
+ bs = d.r.readUntil(d.b2[:0], '"')
+ bs = bs[:len(bs)-1]
+ } else {
+ d.r.unreadn1()
+ bs = d.r.readTo(d.bs[:0], &jsonNumSet)
+ }
+ d.tok = 0
+ return bs
+}
+
+func (d *jsonDecDriver) DecodeUint64() (u uint64) {
+ bs := d.decNumBytes()
+ n, neg, badsyntax, overflow := jsonParseInteger(bs)
+ if overflow {
+ d.d.errorf("overflow parsing unsigned integer: %s", bs)
+ } else if neg {
+ d.d.errorf("minus found parsing unsigned integer: %s", bs)
+ } else if badsyntax {
+ // fallback: try to decode as float, and cast
+ n = d.decUint64ViaFloat(stringView(bs))
+ }
+ return n
+}
+
+func (d *jsonDecDriver) DecodeInt64() (i int64) {
+ const cutoff = uint64(1 << uint(64-1))
+ bs := d.decNumBytes()
+ n, neg, badsyntax, overflow := jsonParseInteger(bs)
+ if overflow {
+ d.d.errorf("overflow parsing integer: %s", bs)
+ } else if badsyntax {
+ // d.d.errorf("invalid syntax for integer: %s", bs)
+ // fallback: try to decode as float, and cast
+ if neg {
+ n = d.decUint64ViaFloat(stringView(bs[1:]))
+ } else {
+ n = d.decUint64ViaFloat(stringView(bs))
+ }
+ }
+ if neg {
+ if n > cutoff {
+ d.d.errorf("overflow parsing integer: %s", bs)
+ }
+ i = -(int64(n))
+ } else {
+ if n >= cutoff {
+ d.d.errorf("overflow parsing integer: %s", bs)
+ }
+ i = int64(n)
+ }
+ return
+}
+
+func (d *jsonDecDriver) decUint64ViaFloat(s string) (u uint64) {
+ f, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ d.d.errorf("invalid syntax for integer: %s", s)
+ // d.d.errorv(err)
+ }
+ fi, ff := math.Modf(f)
+ if ff > 0 {
+ d.d.errorf("fractional part found parsing integer: %s", s)
+ } else if fi > float64(math.MaxUint64) {
+ d.d.errorf("overflow parsing integer: %s", s)
+ }
+ return uint64(fi)
+}
+
+func (d *jsonDecDriver) DecodeFloat64() (f float64) {
+ bs := d.decNumBytes()
+ f, err := strconv.ParseFloat(stringView(bs), 64)
+ if err != nil {
+ d.d.errorv(err)
+ }
+ return
+}
+
+func (d *jsonDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
+ if ext == nil {
+ re := rv.(*RawExt)
+ re.Tag = xtag
+ d.d.decode(&re.Value)
+ } else {
+ var v interface{}
+ d.d.decode(&v)
+ ext.UpdateExt(rv, v)
+ }
+ return
+}
+
+func (d *jsonDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
+ // if decoding into raw bytes, and the RawBytesExt is configured, use it to decode.
+ if d.se.InterfaceExt != nil {
+ bsOut = bs
+ d.DecodeExt(&bsOut, 0, &d.se)
+ return
+ }
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ // check if an "array" of uint8's (see ContainerType for how to infer if an array)
+ if d.tok == '[' {
+ bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+ return
+ }
+ d.appendStringAsBytes()
+ // base64 encodes []byte{} as "", and we encode nil []byte as null.
+ // Consequently, base64 should decode null as a nil []byte, and "" as an empty []byte{}.
+ // appendStringAsBytes returns a zero-len slice for both, so as not to reset d.bs.
+ // However, it sets a fnull field to true, so we can check if a null was found.
+ if len(d.bs) == 0 {
+ if d.fnull {
+ return nil
+ }
+ return []byte{}
+ }
+ bs0 := d.bs
+ slen := base64.StdEncoding.DecodedLen(len(bs0))
+ if slen <= cap(bs) {
+ bsOut = bs[:slen]
+ } else if zerocopy && slen <= cap(d.b2) {
+ bsOut = d.b2[:slen]
+ } else {
+ bsOut = make([]byte, slen)
+ }
+ slen2, err := base64.StdEncoding.Decode(bsOut, bs0)
+ if err != nil {
+ d.d.errorf("error decoding base64 binary '%s': %v", bs0, err)
+ return nil
+ }
+ if slen != slen2 {
+ bsOut = bsOut[:slen2]
+ }
+ return
+}
+
+func (d *jsonDecDriver) DecodeString() (s string) {
+ d.appendStringAsBytes()
+ return d.bsToString()
+}
+
+func (d *jsonDecDriver) DecodeStringAsBytes() (s []byte) {
+ d.appendStringAsBytes()
+ return d.bs
+}
+
+func (d *jsonDecDriver) appendStringAsBytes() {
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+
+ d.fnull = false
+ if d.tok != '"' {
+ // d.d.errorf("expect char '%c' but got char '%c'", '"', d.tok)
+ // handle non-string scalar: null, true, false or a number
+ switch d.tok {
+ case 'n':
+ d.readLit(3, jsonLitNull+1) // (n)ull
+ d.bs = d.bs[:0]
+ d.fnull = true
+ case 'f':
+ d.readLit(4, jsonLitFalse+1) // (f)alse
+ d.bs = d.bs[:5]
+ copy(d.bs, "false")
+ case 't':
+ d.readLit(3, jsonLitTrue+1) // (t)rue
+ d.bs = d.bs[:4]
+ copy(d.bs, "true")
+ default:
+ // try to parse a valid number
+ bs := d.decNumBytes()
+ if len(bs) <= cap(d.bs) {
+ d.bs = d.bs[:len(bs)]
+ } else {
+ d.bs = make([]byte, len(bs))
+ }
+ copy(d.bs, bs)
+ }
+ return
+ }
+
+ d.tok = 0
+ r := d.r
+ var cs = r.readUntil(d.b2[:0], '"')
+ var cslen = len(cs)
+ var c uint8
+ v := d.bs[:0]
+ // append on each byte seen can be expensive, so we just
+ // keep track of where we last read a contiguous set of
+ // non-special bytes (using cursor variable),
+ // and when we see a special byte
+ // e.g. end-of-slice, " or \,
+ // we will append the full range into the v slice before proceeding
+ for i, cursor := 0, 0; ; {
+ if i == cslen {
+ v = append(v, cs[cursor:]...)
+ cs = r.readUntil(d.b2[:0], '"')
+ cslen = len(cs)
+ i, cursor = 0, 0
+ }
+ c = cs[i]
+ if c == '"' {
+ v = append(v, cs[cursor:i]...)
+ break
+ }
+ if c != '\\' {
+ i++
+ continue
+ }
+ v = append(v, cs[cursor:i]...)
+ i++
+ c = cs[i]
+ switch c {
+ case '"', '\\', '/', '\'':
+ v = append(v, c)
+ case 'b':
+ v = append(v, '\b')
+ case 'f':
+ v = append(v, '\f')
+ case 'n':
+ v = append(v, '\n')
+ case 'r':
+ v = append(v, '\r')
+ case 't':
+ v = append(v, '\t')
+ case 'u':
+ var r rune
+ var rr uint32
+ if len(cs) < i+4 { // may help reduce bounds-checking
+ d.d.errorf("need at least 4 more bytes for unicode sequence")
+ }
+ // c = cs[i+4] // may help reduce bounds-checking
+ for j := 1; j < 5; j++ {
+ // best to use explicit if-else
+ // - not a table, etc which involve memory loads, array lookup with bounds checks, etc
+ c = cs[i+j]
+ if c >= '0' && c <= '9' {
+ rr = rr*16 + uint32(c-jsonU4Chk2)
+ } else if c >= 'a' && c <= 'f' {
+ rr = rr*16 + uint32(c-jsonU4Chk1)
+ } else if c >= 'A' && c <= 'F' {
+ rr = rr*16 + uint32(c-jsonU4Chk0)
+ } else {
+ r = unicode.ReplacementChar
+ i += 4
+ goto encode_rune
+ }
+ }
+ r = rune(rr)
+ i += 4
+ if utf16.IsSurrogate(r) {
+ if len(cs) >= i+6 && cs[i+2] == 'u' && cs[i+1] == '\\' {
+ i += 2
+ // c = cs[i+4] // may help reduce bounds-checking
+ var rr1 uint32
+ for j := 1; j < 5; j++ {
+ c = cs[i+j]
+ if c >= '0' && c <= '9' {
+ rr = rr*16 + uint32(c-jsonU4Chk2)
+ } else if c >= 'a' && c <= 'f' {
+ rr = rr*16 + uint32(c-jsonU4Chk1)
+ } else if c >= 'A' && c <= 'F' {
+ rr = rr*16 + uint32(c-jsonU4Chk0)
+ } else {
+ r = unicode.ReplacementChar
+ i += 4
+ goto encode_rune
+ }
+ }
+ r = utf16.DecodeRune(r, rune(rr1))
+ i += 4
+ } else {
+ r = unicode.ReplacementChar
+ goto encode_rune
+ }
+ }
+ encode_rune:
+ w2 := utf8.EncodeRune(d.bstr[:], r)
+ v = append(v, d.bstr[:w2]...)
+ default:
+ d.d.errorf("unsupported escaped value: %c", c)
+ }
+ i++
+ cursor = i
+ }
+ d.bs = v
+}
+
+func (d *jsonDecDriver) nakedNum(z *decNaked, bs []byte) (err error) {
+ const cutoff = uint64(1 << uint(64-1))
+ var n uint64
+ var neg, badsyntax, overflow bool
+
+ if d.h.PreferFloat {
+ goto F
+ }
+ n, neg, badsyntax, overflow = jsonParseInteger(bs)
+ if badsyntax || overflow {
+ goto F
+ }
+ if neg {
+ if n > cutoff {
+ goto F
+ }
+ z.v = valueTypeInt
+ z.i = -(int64(n))
+ } else if d.h.SignedInteger {
+ if n >= cutoff {
+ goto F
+ }
+ z.v = valueTypeInt
+ z.i = int64(n)
+ } else {
+ z.v = valueTypeUint
+ z.u = n
+ }
+ return
+F:
+ z.v = valueTypeFloat
+ z.f, err = strconv.ParseFloat(stringView(bs), 64)
+ return
+}
+
+func (d *jsonDecDriver) bsToString() string {
+ // if x := d.s.sc; x != nil && x.so && x.st == '}' { // map key
+ if jsonAlwaysReturnInternString || d.c == containerMapKey {
+ return d.d.string(d.bs)
+ }
+ return string(d.bs)
+}
+
+func (d *jsonDecDriver) DecodeNaked() {
+ z := d.d.n
+ // var decodeFurther bool
+
+ if d.tok == 0 {
+ d.tok = d.r.skip(&jsonCharWhitespaceSet)
+ }
+ switch d.tok {
+ case 'n':
+ d.readLit(3, jsonLitNull+1) // (n)ull
+ z.v = valueTypeNil
+ case 'f':
+ d.readLit(4, jsonLitFalse+1) // (f)alse
+ z.v = valueTypeBool
+ z.b = false
+ case 't':
+ d.readLit(3, jsonLitTrue+1) // (t)rue
+ z.v = valueTypeBool
+ z.b = true
+ case '{':
+ z.v = valueTypeMap // don't consume. kInterfaceNaked will call ReadMapStart
+ case '[':
+ z.v = valueTypeArray // don't consume. kInterfaceNaked will call ReadArrayStart
+ case '"':
+ // if a string, and MapKeyAsString, then try to decode it as a nil, bool or number first
+ d.appendStringAsBytes()
+ if len(d.bs) > 0 && d.c == containerMapKey && d.h.MapKeyAsString {
+ switch stringView(d.bs) {
+ case "null":
+ z.v = valueTypeNil
+ case "true":
+ z.v = valueTypeBool
+ z.b = true
+ case "false":
+ z.v = valueTypeBool
+ z.b = false
+ default:
+ // check if a number: float, int or uint
+ if err := d.nakedNum(z, d.bs); err != nil {
+ z.v = valueTypeString
+ z.s = d.bsToString()
+ }
+ }
+ } else {
+ z.v = valueTypeString
+ z.s = d.bsToString()
+ }
+ default: // number
+ bs := d.decNumBytes()
+ if len(bs) == 0 {
+ d.d.errorf("decode number from empty string")
+ return
+ }
+ if err := d.nakedNum(z, bs); err != nil {
+ d.d.errorf("decode number from %s: %v", bs, err)
+ return
+ }
+ }
+ // if decodeFurther {
+ // d.s.sc.retryRead()
+ // }
+ return
+}
+
+//----------------------
+
+// JsonHandle is a handle for JSON encoding format.
+//
+// Json is comprehensively supported:
+// - decodes numbers into interface{} as int, uint or float64
+// based on how the number looks and some config parameters e.g. PreferFloat, SignedInt, etc.
+// - decode integers from float formatted numbers e.g. 1.27e+8
+// - decode any json value (numbers, bool, etc) from quoted strings
+// - configurable way to encode/decode []byte .
+// by default, encodes and decodes []byte using base64 Std Encoding
+// - UTF-8 support for encoding and decoding
+//
+// It has better performance than the json library in the standard library,
+// by leveraging the performance improvements of the codec library.
+//
+// In addition, it doesn't read more bytes than necessary during a decode, which allows
+// reading multiple values from a stream containing json and non-json content.
+// For example, a user can read a json value, then a cbor value, then a msgpack value,
+// all from the same stream in sequence.
+//
+// Note that, when decoding quoted strings, invalid UTF-8 or invalid UTF-16 surrogate pairs are
+// not treated as an error. Instead, they are replaced by the Unicode replacement character U+FFFD.
+type JsonHandle struct {
+ textEncodingType
+ BasicHandle
+
+ // Indent indicates how a value is encoded.
+ // - If positive, indent by that number of spaces.
+ // - If negative, indent by that number of tabs.
+ Indent int8
+
+ // IntegerAsString controls how integers (signed and unsigned) are encoded.
+ //
+ // Per the JSON Spec, JSON numbers are 64-bit floating point numbers.
+ // Consequently, integers > 2^53 cannot be represented as a JSON number without losing precision.
+ // This can be mitigated by configuring how to encode integers.
+ //
+ // IntegerAsString interpretes the following values:
+ // - if 'L', then encode integers > 2^53 as a json string.
+ // - if 'A', then encode all integers as a json string
+ // containing the exact integer representation as a decimal.
+ // - else encode all integers as a json number (default)
+ IntegerAsString byte
+
+ // HTMLCharsAsIs controls how to encode some special characters to html: < > &
+ //
+ // By default, we encode them as \uXXX
+ // to prevent security holes when served from some browsers.
+ HTMLCharsAsIs bool
+
+ // PreferFloat says that we will default to decoding a number as a float.
+ // If not set, we will examine the characters of the number and decode as an
+ // integer type if it doesn't have any of the characters [.eE].
+ PreferFloat bool
+
+ // TermWhitespace says that we add a whitespace character
+ // at the end of an encoding.
+ //
+ // The whitespace is important, especially if using numbers in a context
+ // where multiple items are written to a stream.
+ TermWhitespace bool
+
+ // MapKeyAsString says to encode all map keys as strings.
+ //
+ // Use this to enforce strict json output.
+ // The only caveat is that nil value is ALWAYS written as null (never as "null")
+ MapKeyAsString bool
+
+ // _ [2]byte // padding
+
+ // Note: below, we store hardly-used items e.g. RawBytesExt is cached in the (en|de)cDriver.
+
+ // RawBytesExt, if configured, is used to encode and decode raw bytes in a custom way.
+ // If not configured, raw bytes are encoded to/from base64 text.
+ RawBytesExt InterfaceExt
+
+ _ [2]uint64 // padding
+}
+
+// Name returns the name of the handle: json
+func (h *JsonHandle) Name() string { return "json" }
+func (h *JsonHandle) hasElemSeparators() bool { return true }
+func (h *JsonHandle) typical() bool {
+ return h.Indent == 0 && !h.MapKeyAsString && h.IntegerAsString != 'A' && h.IntegerAsString != 'L'
+}
+
+type jsonTypical interface {
+ typical()
+}
+
+func (h *JsonHandle) recreateEncDriver(ed encDriver) (v bool) {
+ _, v = ed.(jsonTypical)
+ return v != h.typical()
+}
+
+// SetInterfaceExt sets an extension
+func (h *JsonHandle) SetInterfaceExt(rt reflect.Type, tag uint64, ext InterfaceExt) (err error) {
+ return h.SetExt(rt, tag, &extWrapper{bytesExtFailer{}, ext})
+}
+
+type jsonEncDriverTypicalImpl struct {
+ jsonEncDriver
+ jsonEncDriverTypical
+ _ [1]uint64 // padding
+}
+
+func (x *jsonEncDriverTypicalImpl) reset() {
+ x.jsonEncDriver.reset()
+ x.jsonEncDriverTypical.reset(&x.jsonEncDriver)
+}
+
+type jsonEncDriverGenericImpl struct {
+ jsonEncDriver
+ jsonEncDriverGeneric
+}
+
+func (x *jsonEncDriverGenericImpl) reset() {
+ x.jsonEncDriver.reset()
+ x.jsonEncDriverGeneric.reset(&x.jsonEncDriver)
+}
+
+func (h *JsonHandle) newEncDriver(e *Encoder) (ee encDriver) {
+ var hd *jsonEncDriver
+ if h.typical() {
+ var v jsonEncDriverTypicalImpl
+ ee = &v
+ hd = &v.jsonEncDriver
+ } else {
+ var v jsonEncDriverGenericImpl
+ ee = &v
+ hd = &v.jsonEncDriver
+ }
+ hd.e, hd.h, hd.bs = e, h, hd.b[:0]
+ hd.se.BytesExt = bytesExtFailer{}
+ ee.reset()
+ return
+}
+
+func (h *JsonHandle) newDecDriver(d *Decoder) decDriver {
+ // d := jsonDecDriver{r: r.(*bytesDecReader), h: h}
+ hd := jsonDecDriver{d: d, h: h}
+ hd.se.BytesExt = bytesExtFailer{}
+ hd.bs = hd.b[:0]
+ hd.reset()
+ return &hd
+}
+
+func (e *jsonEncDriver) reset() {
+ e.ew = e.e.w // e.e.w // &e.e.encWriterSwitch
+ e.se.InterfaceExt = e.h.RawBytesExt
+ if e.bs != nil {
+ e.bs = e.bs[:0]
+ }
+}
+
+func (d *jsonDecDriver) reset() {
+ d.r = d.d.r // &d.d.decReaderSwitch // d.d.r
+ d.se.InterfaceExt = d.h.RawBytesExt
+ if d.bs != nil {
+ d.bs = d.bs[:0]
+ }
+ d.c, d.tok = 0, 0
+ // d.n.reset()
+}
+
+func jsonFloatStrconvFmtPrec(f float64) (fmt byte, prec int) {
+ prec = -1
+ var abs = math.Abs(f)
+ if abs != 0 && (abs < 1e-6 || abs >= 1e21) {
+ fmt = 'e'
+ } else {
+ fmt = 'f'
+ // set prec to 1 iff mod is 0.
+ // better than using jsonIsFloatBytesB2 to check if a . or E in the float bytes.
+ // this ensures that every float has an e or .0 in it.
+ if abs <= 1 {
+ if abs == 0 || abs == 1 {
+ prec = 1
+ }
+ } else if _, mod := math.Modf(abs); mod == 0 {
+ prec = 1
+ }
+ }
+ return
+}
+
+// custom-fitted version of strconv.Parse(Ui|I)nt.
+// Also ensures we don't have to search for .eE to determine if a float or not.
+func jsonParseInteger(s []byte) (n uint64, neg, badSyntax, overflow bool) {
+ const maxUint64 = (1<<64 - 1)
+ const cutoff = maxUint64/10 + 1
+
+ if len(s) == 0 {
+ badSyntax = true
+ return
+ }
+ switch s[0] {
+ case '+':
+ s = s[1:]
+ case '-':
+ s = s[1:]
+ neg = true
+ }
+ for _, c := range s {
+ if c < '0' || c > '9' {
+ badSyntax = true
+ return
+ }
+ // unsigned integers don't overflow well on multiplication, so check cutoff here
+ // e.g. (maxUint64-5)*10 doesn't overflow well ...
+ if n >= cutoff {
+ overflow = true
+ return
+ }
+ n *= 10
+ n1 := n + uint64(c-'0')
+ if n1 < n || n1 > maxUint64 {
+ overflow = true
+ return
+ }
+ n = n1
+ }
+ return
+}
+
+var _ decDriver = (*jsonDecDriver)(nil)
+var _ encDriver = (*jsonEncDriverGenericImpl)(nil)
+var _ encDriver = (*jsonEncDriverTypicalImpl)(nil)
+var _ jsonTypical = (*jsonEncDriverTypical)(nil)
diff --git a/vendor/github.com/ugorji/go/codec/msgpack.go b/vendor/github.com/ugorji/go/codec/msgpack.go
new file mode 100644
index 00000000..3271579a
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/msgpack.go
@@ -0,0 +1,1092 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+/*
+MSGPACK
+
+Msgpack-c implementation powers the c, c++, python, ruby, etc libraries.
+We need to maintain compatibility with it and how it encodes integer values
+without caring about the type.
+
+For compatibility with behaviour of msgpack-c reference implementation:
+ - Go intX (>0) and uintX
+ IS ENCODED AS
+ msgpack +ve fixnum, unsigned
+ - Go intX (<0)
+ IS ENCODED AS
+ msgpack -ve fixnum, signed
+*/
+
+package codec
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "net/rpc"
+ "reflect"
+ "time"
+)
+
+const (
+ mpPosFixNumMin byte = 0x00
+ mpPosFixNumMax = 0x7f
+ mpFixMapMin = 0x80
+ mpFixMapMax = 0x8f
+ mpFixArrayMin = 0x90
+ mpFixArrayMax = 0x9f
+ mpFixStrMin = 0xa0
+ mpFixStrMax = 0xbf
+ mpNil = 0xc0
+ _ = 0xc1
+ mpFalse = 0xc2
+ mpTrue = 0xc3
+ mpFloat = 0xca
+ mpDouble = 0xcb
+ mpUint8 = 0xcc
+ mpUint16 = 0xcd
+ mpUint32 = 0xce
+ mpUint64 = 0xcf
+ mpInt8 = 0xd0
+ mpInt16 = 0xd1
+ mpInt32 = 0xd2
+ mpInt64 = 0xd3
+
+ // extensions below
+ mpBin8 = 0xc4
+ mpBin16 = 0xc5
+ mpBin32 = 0xc6
+ mpExt8 = 0xc7
+ mpExt16 = 0xc8
+ mpExt32 = 0xc9
+ mpFixExt1 = 0xd4
+ mpFixExt2 = 0xd5
+ mpFixExt4 = 0xd6
+ mpFixExt8 = 0xd7
+ mpFixExt16 = 0xd8
+
+ mpStr8 = 0xd9 // new
+ mpStr16 = 0xda
+ mpStr32 = 0xdb
+
+ mpArray16 = 0xdc
+ mpArray32 = 0xdd
+
+ mpMap16 = 0xde
+ mpMap32 = 0xdf
+
+ mpNegFixNumMin = 0xe0
+ mpNegFixNumMax = 0xff
+)
+
+var mpTimeExtTag int8 = -1
+var mpTimeExtTagU = uint8(mpTimeExtTag)
+
+// var mpdesc = map[byte]string{
+// mpPosFixNumMin: "PosFixNumMin",
+// mpPosFixNumMax: "PosFixNumMax",
+// mpFixMapMin: "FixMapMin",
+// mpFixMapMax: "FixMapMax",
+// mpFixArrayMin: "FixArrayMin",
+// mpFixArrayMax: "FixArrayMax",
+// mpFixStrMin: "FixStrMin",
+// mpFixStrMax: "FixStrMax",
+// mpNil: "Nil",
+// mpFalse: "False",
+// mpTrue: "True",
+// mpFloat: "Float",
+// mpDouble: "Double",
+// mpUint8: "Uint8",
+// mpUint16: "Uint16",
+// mpUint32: "Uint32",
+// mpUint64: "Uint64",
+// mpInt8: "Int8",
+// mpInt16: "Int16",
+// mpInt32: "Int32",
+// mpInt64: "Int64",
+// mpBin8: "Bin8",
+// mpBin16: "Bin16",
+// mpBin32: "Bin32",
+// mpExt8: "Ext8",
+// mpExt16: "Ext16",
+// mpExt32: "Ext32",
+// mpFixExt1: "FixExt1",
+// mpFixExt2: "FixExt2",
+// mpFixExt4: "FixExt4",
+// mpFixExt8: "FixExt8",
+// mpFixExt16: "FixExt16",
+// mpStr8: "Str8",
+// mpStr16: "Str16",
+// mpStr32: "Str32",
+// mpArray16: "Array16",
+// mpArray32: "Array32",
+// mpMap16: "Map16",
+// mpMap32: "Map32",
+// mpNegFixNumMin: "NegFixNumMin",
+// mpNegFixNumMax: "NegFixNumMax",
+// }
+
+func mpdesc(bd byte) string {
+ switch bd {
+ case mpNil:
+ return "nil"
+ case mpFalse:
+ return "false"
+ case mpTrue:
+ return "true"
+ case mpFloat, mpDouble:
+ return "float"
+ case mpUint8, mpUint16, mpUint32, mpUint64:
+ return "uint"
+ case mpInt8, mpInt16, mpInt32, mpInt64:
+ return "int"
+ default:
+ switch {
+ case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax:
+ return "int"
+ case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax:
+ return "int"
+ case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax:
+ return "string|bytes"
+ case bd == mpBin8, bd == mpBin16, bd == mpBin32:
+ return "bytes"
+ case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
+ return "array"
+ case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax:
+ return "map"
+ case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
+ return "ext"
+ default:
+ return "unknown"
+ }
+ }
+}
+
+// MsgpackSpecRpcMultiArgs is a special type which signifies to the MsgpackSpecRpcCodec
+// that the backend RPC service takes multiple arguments, which have been arranged
+// in sequence in the slice.
+//
+// The Codec then passes it AS-IS to the rpc service (without wrapping it in an
+// array of 1 element).
+type MsgpackSpecRpcMultiArgs []interface{}
+
+// A MsgpackContainer type specifies the different types of msgpackContainers.
+type msgpackContainerType struct {
+ fixCutoff int
+ bFixMin, b8, b16, b32 byte
+ hasFixMin, has8, has8Always bool
+}
+
+var (
+ msgpackContainerStr = msgpackContainerType{
+ 32, mpFixStrMin, mpStr8, mpStr16, mpStr32, true, true, false,
+ }
+ msgpackContainerBin = msgpackContainerType{
+ 0, 0, mpBin8, mpBin16, mpBin32, false, true, true,
+ }
+ msgpackContainerList = msgpackContainerType{
+ 16, mpFixArrayMin, 0, mpArray16, mpArray32, true, false, false,
+ }
+ msgpackContainerMap = msgpackContainerType{
+ 16, mpFixMapMin, 0, mpMap16, mpMap32, true, false, false,
+ }
+)
+
+//---------------------------------------------
+
+type msgpackEncDriver struct {
+ noBuiltInTypes
+ encDriverNoopContainerWriter
+ // encNoSeparator
+ e *Encoder
+ w encWriter
+ h *MsgpackHandle
+ x [8]byte
+ _ [3]uint64 // padding
+}
+
+func (e *msgpackEncDriver) EncodeNil() {
+ e.w.writen1(mpNil)
+}
+
+func (e *msgpackEncDriver) EncodeInt(i int64) {
+ // if i >= 0 {
+ // e.EncodeUint(uint64(i))
+ // } else if false &&
+ if i > math.MaxInt8 {
+ if i <= math.MaxInt16 {
+ e.w.writen1(mpInt16)
+ bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
+ } else if i <= math.MaxInt32 {
+ e.w.writen1(mpInt32)
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
+ } else {
+ e.w.writen1(mpInt64)
+ bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
+ }
+ } else if i >= -32 {
+ if e.h.NoFixedNum {
+ e.w.writen2(mpInt8, byte(i))
+ } else {
+ e.w.writen1(byte(i))
+ }
+ } else if i >= math.MinInt8 {
+ e.w.writen2(mpInt8, byte(i))
+ } else if i >= math.MinInt16 {
+ e.w.writen1(mpInt16)
+ bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
+ } else if i >= math.MinInt32 {
+ e.w.writen1(mpInt32)
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
+ } else {
+ e.w.writen1(mpInt64)
+ bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
+ }
+}
+
+func (e *msgpackEncDriver) EncodeUint(i uint64) {
+ if i <= math.MaxInt8 {
+ if e.h.NoFixedNum {
+ e.w.writen2(mpUint8, byte(i))
+ } else {
+ e.w.writen1(byte(i))
+ }
+ } else if i <= math.MaxUint8 {
+ e.w.writen2(mpUint8, byte(i))
+ } else if i <= math.MaxUint16 {
+ e.w.writen1(mpUint16)
+ bigenHelper{e.x[:2], e.w}.writeUint16(uint16(i))
+ } else if i <= math.MaxUint32 {
+ e.w.writen1(mpUint32)
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(i))
+ } else {
+ e.w.writen1(mpUint64)
+ bigenHelper{e.x[:8], e.w}.writeUint64(uint64(i))
+ }
+}
+
+func (e *msgpackEncDriver) EncodeBool(b bool) {
+ if b {
+ e.w.writen1(mpTrue)
+ } else {
+ e.w.writen1(mpFalse)
+ }
+}
+
+func (e *msgpackEncDriver) EncodeFloat32(f float32) {
+ e.w.writen1(mpFloat)
+ bigenHelper{e.x[:4], e.w}.writeUint32(math.Float32bits(f))
+}
+
+func (e *msgpackEncDriver) EncodeFloat64(f float64) {
+ e.w.writen1(mpDouble)
+ bigenHelper{e.x[:8], e.w}.writeUint64(math.Float64bits(f))
+}
+
+func (e *msgpackEncDriver) EncodeTime(t time.Time) {
+ if t.IsZero() {
+ e.EncodeNil()
+ return
+ }
+ t = t.UTC()
+ sec, nsec := t.Unix(), uint64(t.Nanosecond())
+ var data64 uint64
+ var l = 4
+ if sec >= 0 && sec>>34 == 0 {
+ data64 = (nsec << 34) | uint64(sec)
+ if data64&0xffffffff00000000 != 0 {
+ l = 8
+ }
+ } else {
+ l = 12
+ }
+ if e.h.WriteExt {
+ e.encodeExtPreamble(mpTimeExtTagU, l)
+ } else {
+ e.writeContainerLen(msgpackContainerStr, l)
+ }
+ switch l {
+ case 4:
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(data64))
+ case 8:
+ bigenHelper{e.x[:8], e.w}.writeUint64(data64)
+ case 12:
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(nsec))
+ bigenHelper{e.x[:8], e.w}.writeUint64(uint64(sec))
+ }
+}
+
+func (e *msgpackEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext, _ *Encoder) {
+ bs := ext.WriteExt(v)
+ if bs == nil {
+ e.EncodeNil()
+ return
+ }
+ if e.h.WriteExt {
+ e.encodeExtPreamble(uint8(xtag), len(bs))
+ e.w.writeb(bs)
+ } else {
+ e.EncodeStringBytes(cRAW, bs)
+ }
+}
+
+func (e *msgpackEncDriver) EncodeRawExt(re *RawExt, _ *Encoder) {
+ e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
+ e.w.writeb(re.Data)
+}
+
+func (e *msgpackEncDriver) encodeExtPreamble(xtag byte, l int) {
+ if l == 1 {
+ e.w.writen2(mpFixExt1, xtag)
+ } else if l == 2 {
+ e.w.writen2(mpFixExt2, xtag)
+ } else if l == 4 {
+ e.w.writen2(mpFixExt4, xtag)
+ } else if l == 8 {
+ e.w.writen2(mpFixExt8, xtag)
+ } else if l == 16 {
+ e.w.writen2(mpFixExt16, xtag)
+ } else if l < 256 {
+ e.w.writen2(mpExt8, byte(l))
+ e.w.writen1(xtag)
+ } else if l < 65536 {
+ e.w.writen1(mpExt16)
+ bigenHelper{e.x[:2], e.w}.writeUint16(uint16(l))
+ e.w.writen1(xtag)
+ } else {
+ e.w.writen1(mpExt32)
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(l))
+ e.w.writen1(xtag)
+ }
+}
+
+func (e *msgpackEncDriver) WriteArrayStart(length int) {
+ e.writeContainerLen(msgpackContainerList, length)
+}
+
+func (e *msgpackEncDriver) WriteMapStart(length int) {
+ e.writeContainerLen(msgpackContainerMap, length)
+}
+
+func (e *msgpackEncDriver) EncodeString(c charEncoding, s string) {
+ slen := len(s)
+ if c == cRAW && e.h.WriteExt {
+ e.writeContainerLen(msgpackContainerBin, slen)
+ } else {
+ e.writeContainerLen(msgpackContainerStr, slen)
+ }
+ if slen > 0 {
+ e.w.writestr(s)
+ }
+}
+
+func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
+ if bs == nil {
+ e.EncodeNil()
+ return
+ }
+ slen := len(bs)
+ if c == cRAW && e.h.WriteExt {
+ e.writeContainerLen(msgpackContainerBin, slen)
+ } else {
+ e.writeContainerLen(msgpackContainerStr, slen)
+ }
+ if slen > 0 {
+ e.w.writeb(bs)
+ }
+}
+
+func (e *msgpackEncDriver) writeContainerLen(ct msgpackContainerType, l int) {
+ if ct.hasFixMin && l < ct.fixCutoff {
+ e.w.writen1(ct.bFixMin | byte(l))
+ } else if ct.has8 && l < 256 && (ct.has8Always || e.h.WriteExt) {
+ e.w.writen2(ct.b8, uint8(l))
+ } else if l < 65536 {
+ e.w.writen1(ct.b16)
+ bigenHelper{e.x[:2], e.w}.writeUint16(uint16(l))
+ } else {
+ e.w.writen1(ct.b32)
+ bigenHelper{e.x[:4], e.w}.writeUint32(uint32(l))
+ }
+}
+
+//---------------------------------------------
+
+type msgpackDecDriver struct {
+ d *Decoder
+ r decReader // *Decoder decReader decReaderT
+ h *MsgpackHandle
+ // b [scratchByteArrayLen]byte
+ bd byte
+ bdRead bool
+ br bool // bytes reader
+ noBuiltInTypes
+ // noStreamingCodec
+ // decNoSeparator
+ decDriverNoopContainerReader
+ _ [3]uint64 // padding
+}
+
+// Note: This returns either a primitive (int, bool, etc) for non-containers,
+// or a containerType, or a specific type denoting nil or extension.
+// It is called when a nil interface{} is passed, leaving it up to the DecDriver
+// to introspect the stream and decide how best to decode.
+// It deciphers the value by looking at the stream first.
+func (d *msgpackDecDriver) DecodeNaked() {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ bd := d.bd
+ n := d.d.n
+ var decodeFurther bool
+
+ switch bd {
+ case mpNil:
+ n.v = valueTypeNil
+ d.bdRead = false
+ case mpFalse:
+ n.v = valueTypeBool
+ n.b = false
+ case mpTrue:
+ n.v = valueTypeBool
+ n.b = true
+
+ case mpFloat:
+ n.v = valueTypeFloat
+ n.f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+ case mpDouble:
+ n.v = valueTypeFloat
+ n.f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+
+ case mpUint8:
+ n.v = valueTypeUint
+ n.u = uint64(d.r.readn1())
+ case mpUint16:
+ n.v = valueTypeUint
+ n.u = uint64(bigen.Uint16(d.r.readx(2)))
+ case mpUint32:
+ n.v = valueTypeUint
+ n.u = uint64(bigen.Uint32(d.r.readx(4)))
+ case mpUint64:
+ n.v = valueTypeUint
+ n.u = uint64(bigen.Uint64(d.r.readx(8)))
+
+ case mpInt8:
+ n.v = valueTypeInt
+ n.i = int64(int8(d.r.readn1()))
+ case mpInt16:
+ n.v = valueTypeInt
+ n.i = int64(int16(bigen.Uint16(d.r.readx(2))))
+ case mpInt32:
+ n.v = valueTypeInt
+ n.i = int64(int32(bigen.Uint32(d.r.readx(4))))
+ case mpInt64:
+ n.v = valueTypeInt
+ n.i = int64(int64(bigen.Uint64(d.r.readx(8))))
+
+ default:
+ switch {
+ case bd >= mpPosFixNumMin && bd <= mpPosFixNumMax:
+ // positive fixnum (always signed)
+ n.v = valueTypeInt
+ n.i = int64(int8(bd))
+ case bd >= mpNegFixNumMin && bd <= mpNegFixNumMax:
+ // negative fixnum
+ n.v = valueTypeInt
+ n.i = int64(int8(bd))
+ case bd == mpStr8, bd == mpStr16, bd == mpStr32, bd >= mpFixStrMin && bd <= mpFixStrMax:
+ if d.h.RawToString {
+ n.v = valueTypeString
+ n.s = d.DecodeString()
+ } else {
+ n.v = valueTypeBytes
+ n.l = d.DecodeBytes(nil, false)
+ }
+ case bd == mpBin8, bd == mpBin16, bd == mpBin32:
+ n.v = valueTypeBytes
+ n.l = d.DecodeBytes(nil, false)
+ case bd == mpArray16, bd == mpArray32, bd >= mpFixArrayMin && bd <= mpFixArrayMax:
+ n.v = valueTypeArray
+ decodeFurther = true
+ case bd == mpMap16, bd == mpMap32, bd >= mpFixMapMin && bd <= mpFixMapMax:
+ n.v = valueTypeMap
+ decodeFurther = true
+ case bd >= mpFixExt1 && bd <= mpFixExt16, bd >= mpExt8 && bd <= mpExt32:
+ n.v = valueTypeExt
+ clen := d.readExtLen()
+ n.u = uint64(d.r.readn1())
+ if n.u == uint64(mpTimeExtTagU) {
+ n.v = valueTypeTime
+ n.t = d.decodeTime(clen)
+ } else {
+ n.l = d.r.readx(clen)
+ }
+ default:
+ d.d.errorf("cannot infer value: %s: Ox%x/%d/%s", msgBadDesc, bd, bd, mpdesc(bd))
+ }
+ }
+ if !decodeFurther {
+ d.bdRead = false
+ }
+ if n.v == valueTypeUint && d.h.SignedInteger {
+ n.v = valueTypeInt
+ n.i = int64(n.u)
+ }
+ return
+}
+
+// int can be decoded from msgpack type: intXXX or uintXXX
+func (d *msgpackDecDriver) DecodeInt64() (i int64) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ switch d.bd {
+ case mpUint8:
+ i = int64(uint64(d.r.readn1()))
+ case mpUint16:
+ i = int64(uint64(bigen.Uint16(d.r.readx(2))))
+ case mpUint32:
+ i = int64(uint64(bigen.Uint32(d.r.readx(4))))
+ case mpUint64:
+ i = int64(bigen.Uint64(d.r.readx(8)))
+ case mpInt8:
+ i = int64(int8(d.r.readn1()))
+ case mpInt16:
+ i = int64(int16(bigen.Uint16(d.r.readx(2))))
+ case mpInt32:
+ i = int64(int32(bigen.Uint32(d.r.readx(4))))
+ case mpInt64:
+ i = int64(bigen.Uint64(d.r.readx(8)))
+ default:
+ switch {
+ case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
+ i = int64(int8(d.bd))
+ case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
+ i = int64(int8(d.bd))
+ default:
+ d.d.errorf("cannot decode signed integer: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
+ return
+ }
+ }
+ d.bdRead = false
+ return
+}
+
+// uint can be decoded from msgpack type: intXXX or uintXXX
+func (d *msgpackDecDriver) DecodeUint64() (ui uint64) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ switch d.bd {
+ case mpUint8:
+ ui = uint64(d.r.readn1())
+ case mpUint16:
+ ui = uint64(bigen.Uint16(d.r.readx(2)))
+ case mpUint32:
+ ui = uint64(bigen.Uint32(d.r.readx(4)))
+ case mpUint64:
+ ui = bigen.Uint64(d.r.readx(8))
+ case mpInt8:
+ if i := int64(int8(d.r.readn1())); i >= 0 {
+ ui = uint64(i)
+ } else {
+ d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
+ return
+ }
+ case mpInt16:
+ if i := int64(int16(bigen.Uint16(d.r.readx(2)))); i >= 0 {
+ ui = uint64(i)
+ } else {
+ d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
+ return
+ }
+ case mpInt32:
+ if i := int64(int32(bigen.Uint32(d.r.readx(4)))); i >= 0 {
+ ui = uint64(i)
+ } else {
+ d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
+ return
+ }
+ case mpInt64:
+ if i := int64(bigen.Uint64(d.r.readx(8))); i >= 0 {
+ ui = uint64(i)
+ } else {
+ d.d.errorf("assigning negative signed value: %v, to unsigned type", i)
+ return
+ }
+ default:
+ switch {
+ case d.bd >= mpPosFixNumMin && d.bd <= mpPosFixNumMax:
+ ui = uint64(d.bd)
+ case d.bd >= mpNegFixNumMin && d.bd <= mpNegFixNumMax:
+ d.d.errorf("assigning negative signed value: %v, to unsigned type", int(d.bd))
+ return
+ default:
+ d.d.errorf("cannot decode unsigned integer: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
+ return
+ }
+ }
+ d.bdRead = false
+ return
+}
+
+// float can either be decoded from msgpack type: float, double or intX
+func (d *msgpackDecDriver) DecodeFloat64() (f float64) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == mpFloat {
+ f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+ } else if d.bd == mpDouble {
+ f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+ } else {
+ f = float64(d.DecodeInt64())
+ }
+ d.bdRead = false
+ return
+}
+
+// bool can be decoded from bool, fixnum 0 or 1.
+func (d *msgpackDecDriver) DecodeBool() (b bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == mpFalse || d.bd == 0 {
+ // b = false
+ } else if d.bd == mpTrue || d.bd == 1 {
+ b = true
+ } else {
+ d.d.errorf("cannot decode bool: %s: %x/%s", msgBadDesc, d.bd, mpdesc(d.bd))
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+
+ // check if an "array" of uint8's (see ContainerType for how to infer if an array)
+ bd := d.bd
+ // DecodeBytes could be from: bin str fixstr fixarray array ...
+ var clen int
+ vt := d.ContainerType()
+ switch vt {
+ case valueTypeBytes:
+ // valueTypeBytes may be a mpBin or an mpStr container
+ if bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
+ clen = d.readContainerLen(msgpackContainerBin)
+ } else {
+ clen = d.readContainerLen(msgpackContainerStr)
+ }
+ case valueTypeString:
+ clen = d.readContainerLen(msgpackContainerStr)
+ case valueTypeArray:
+ if zerocopy && len(bs) == 0 {
+ bs = d.d.b[:]
+ }
+ bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+ return
+ default:
+ d.d.errorf("invalid container type: expecting bin|str|array, got: 0x%x", uint8(vt))
+ return
+ }
+
+ // these are (bin|str)(8|16|32)
+ d.bdRead = false
+ // bytes may be nil, so handle it. if nil, clen=-1.
+ if clen < 0 {
+ return nil
+ }
+ if zerocopy {
+ if d.br {
+ return d.r.readx(clen)
+ } else if len(bs) == 0 {
+ bs = d.d.b[:]
+ }
+ }
+ return decByteSlice(d.r, clen, d.h.MaxInitLen, bs)
+}
+
+func (d *msgpackDecDriver) DecodeString() (s string) {
+ return string(d.DecodeBytes(d.d.b[:], true))
+}
+
+func (d *msgpackDecDriver) DecodeStringAsBytes() (s []byte) {
+ return d.DecodeBytes(d.d.b[:], true)
+}
+
+func (d *msgpackDecDriver) readNextBd() {
+ d.bd = d.r.readn1()
+ d.bdRead = true
+}
+
+func (d *msgpackDecDriver) uncacheRead() {
+ if d.bdRead {
+ d.r.unreadn1()
+ d.bdRead = false
+ }
+}
+
+func (d *msgpackDecDriver) ContainerType() (vt valueType) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ bd := d.bd
+ if bd == mpNil {
+ return valueTypeNil
+ } else if bd == mpBin8 || bd == mpBin16 || bd == mpBin32 ||
+ (!d.h.RawToString &&
+ (bd == mpStr8 || bd == mpStr16 || bd == mpStr32 || (bd >= mpFixStrMin && bd <= mpFixStrMax))) {
+ return valueTypeBytes
+ } else if d.h.RawToString &&
+ (bd == mpStr8 || bd == mpStr16 || bd == mpStr32 || (bd >= mpFixStrMin && bd <= mpFixStrMax)) {
+ return valueTypeString
+ } else if bd == mpArray16 || bd == mpArray32 || (bd >= mpFixArrayMin && bd <= mpFixArrayMax) {
+ return valueTypeArray
+ } else if bd == mpMap16 || bd == mpMap32 || (bd >= mpFixMapMin && bd <= mpFixMapMax) {
+ return valueTypeMap
+ }
+ // else {
+ // d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+ // }
+ return valueTypeUnset
+}
+
+func (d *msgpackDecDriver) TryDecodeAsNil() (v bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == mpNil {
+ d.bdRead = false
+ return true
+ }
+ return
+}
+
+func (d *msgpackDecDriver) readContainerLen(ct msgpackContainerType) (clen int) {
+ bd := d.bd
+ if bd == mpNil {
+ clen = -1 // to represent nil
+ } else if bd == ct.b8 {
+ clen = int(d.r.readn1())
+ } else if bd == ct.b16 {
+ clen = int(bigen.Uint16(d.r.readx(2)))
+ } else if bd == ct.b32 {
+ clen = int(bigen.Uint32(d.r.readx(4)))
+ } else if (ct.bFixMin & bd) == ct.bFixMin {
+ clen = int(ct.bFixMin ^ bd)
+ } else {
+ d.d.errorf("cannot read container length: %s: hex: %x, decimal: %d", msgBadDesc, bd, bd)
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *msgpackDecDriver) ReadMapStart() int {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ return d.readContainerLen(msgpackContainerMap)
+}
+
+func (d *msgpackDecDriver) ReadArrayStart() int {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ return d.readContainerLen(msgpackContainerList)
+}
+
+func (d *msgpackDecDriver) readExtLen() (clen int) {
+ switch d.bd {
+ case mpNil:
+ clen = -1 // to represent nil
+ case mpFixExt1:
+ clen = 1
+ case mpFixExt2:
+ clen = 2
+ case mpFixExt4:
+ clen = 4
+ case mpFixExt8:
+ clen = 8
+ case mpFixExt16:
+ clen = 16
+ case mpExt8:
+ clen = int(d.r.readn1())
+ case mpExt16:
+ clen = int(bigen.Uint16(d.r.readx(2)))
+ case mpExt32:
+ clen = int(bigen.Uint32(d.r.readx(4)))
+ default:
+ d.d.errorf("decoding ext bytes: found unexpected byte: %x", d.bd)
+ return
+ }
+ return
+}
+
+func (d *msgpackDecDriver) DecodeTime() (t time.Time) {
+ // decode time from string bytes or ext
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == mpNil {
+ d.bdRead = false
+ return
+ }
+ var clen int
+ switch d.ContainerType() {
+ case valueTypeBytes, valueTypeString:
+ clen = d.readContainerLen(msgpackContainerStr)
+ default:
+ // expect to see mpFixExt4,-1 OR mpFixExt8,-1 OR mpExt8,12,-1
+ d.bdRead = false
+ b2 := d.r.readn1()
+ if d.bd == mpFixExt4 && b2 == mpTimeExtTagU {
+ clen = 4
+ } else if d.bd == mpFixExt8 && b2 == mpTimeExtTagU {
+ clen = 8
+ } else if d.bd == mpExt8 && b2 == 12 && d.r.readn1() == mpTimeExtTagU {
+ clen = 12
+ } else {
+ d.d.errorf("invalid bytes for decoding time as extension: got 0x%x, 0x%x", d.bd, b2)
+ return
+ }
+ }
+ return d.decodeTime(clen)
+}
+
+func (d *msgpackDecDriver) decodeTime(clen int) (t time.Time) {
+ // bs = d.r.readx(clen)
+ d.bdRead = false
+ switch clen {
+ case 4:
+ t = time.Unix(int64(bigen.Uint32(d.r.readx(4))), 0).UTC()
+ case 8:
+ tv := bigen.Uint64(d.r.readx(8))
+ t = time.Unix(int64(tv&0x00000003ffffffff), int64(tv>>34)).UTC()
+ case 12:
+ nsec := bigen.Uint32(d.r.readx(4))
+ sec := bigen.Uint64(d.r.readx(8))
+ t = time.Unix(int64(sec), int64(nsec)).UTC()
+ default:
+ d.d.errorf("invalid length of bytes for decoding time - expecting 4 or 8 or 12, got %d", clen)
+ return
+ }
+ return
+}
+
+func (d *msgpackDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
+ if xtag > 0xff {
+ d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
+ return
+ }
+ realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
+ realxtag = uint64(realxtag1)
+ if ext == nil {
+ re := rv.(*RawExt)
+ re.Tag = realxtag
+ re.Data = detachZeroCopyBytes(d.br, re.Data, xbs)
+ } else {
+ ext.ReadExt(rv, xbs)
+ }
+ return
+}
+
+func (d *msgpackDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ xbd := d.bd
+ if xbd == mpBin8 || xbd == mpBin16 || xbd == mpBin32 {
+ xbs = d.DecodeBytes(nil, true)
+ } else if xbd == mpStr8 || xbd == mpStr16 || xbd == mpStr32 ||
+ (xbd >= mpFixStrMin && xbd <= mpFixStrMax) {
+ xbs = d.DecodeStringAsBytes()
+ } else {
+ clen := d.readExtLen()
+ xtag = d.r.readn1()
+ if verifyTag && xtag != tag {
+ d.d.errorf("wrong extension tag - got %b, expecting %v", xtag, tag)
+ return
+ }
+ xbs = d.r.readx(clen)
+ }
+ d.bdRead = false
+ return
+}
+
+//--------------------------------------------------
+
+//MsgpackHandle is a Handle for the Msgpack Schema-Free Encoding Format.
+type MsgpackHandle struct {
+ BasicHandle
+
+ // RawToString controls how raw bytes are decoded into a nil interface{}.
+ RawToString bool
+
+ // NoFixedNum says to output all signed integers as 2-bytes, never as 1-byte fixednum.
+ NoFixedNum bool
+
+ // WriteExt flag supports encoding configured extensions with extension tags.
+ // It also controls whether other elements of the new spec are encoded (ie Str8).
+ //
+ // With WriteExt=false, configured extensions are serialized as raw bytes
+ // and Str8 is not encoded.
+ //
+ // A stream can still be decoded into a typed value, provided an appropriate value
+ // is provided, but the type cannot be inferred from the stream. If no appropriate
+ // type is provided (e.g. decoding into a nil interface{}), you get back
+ // a []byte or string based on the setting of RawToString.
+ WriteExt bool
+
+ binaryEncodingType
+ noElemSeparators
+
+ // _ [1]uint64 // padding
+}
+
+// Name returns the name of the handle: msgpack
+func (h *MsgpackHandle) Name() string { return "msgpack" }
+
+// SetBytesExt sets an extension
+func (h *MsgpackHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
+ return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
+}
+
+func (h *MsgpackHandle) newEncDriver(e *Encoder) encDriver {
+ return &msgpackEncDriver{e: e, w: e.w, h: h}
+}
+
+func (h *MsgpackHandle) newDecDriver(d *Decoder) decDriver {
+ return &msgpackDecDriver{d: d, h: h, r: d.r, br: d.bytes}
+}
+
+func (e *msgpackEncDriver) reset() {
+ e.w = e.e.w
+}
+
+func (d *msgpackDecDriver) reset() {
+ d.r, d.br = d.d.r, d.d.bytes
+ d.bd, d.bdRead = 0, false
+}
+
+//--------------------------------------------------
+
+type msgpackSpecRpcCodec struct {
+ rpcCodec
+}
+
+// /////////////// Spec RPC Codec ///////////////////
+func (c *msgpackSpecRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
+ // WriteRequest can write to both a Go service, and other services that do
+ // not abide by the 1 argument rule of a Go service.
+ // We discriminate based on if the body is a MsgpackSpecRpcMultiArgs
+ var bodyArr []interface{}
+ if m, ok := body.(MsgpackSpecRpcMultiArgs); ok {
+ bodyArr = ([]interface{})(m)
+ } else {
+ bodyArr = []interface{}{body}
+ }
+ r2 := []interface{}{0, uint32(r.Seq), r.ServiceMethod, bodyArr}
+ return c.write(r2, nil, false)
+}
+
+func (c *msgpackSpecRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
+ var moe interface{}
+ if r.Error != "" {
+ moe = r.Error
+ }
+ if moe != nil && body != nil {
+ body = nil
+ }
+ r2 := []interface{}{1, uint32(r.Seq), moe, body}
+ return c.write(r2, nil, false)
+}
+
+func (c *msgpackSpecRpcCodec) ReadResponseHeader(r *rpc.Response) error {
+ return c.parseCustomHeader(1, &r.Seq, &r.Error)
+}
+
+func (c *msgpackSpecRpcCodec) ReadRequestHeader(r *rpc.Request) error {
+ return c.parseCustomHeader(0, &r.Seq, &r.ServiceMethod)
+}
+
+func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error {
+ if body == nil { // read and discard
+ return c.read(nil)
+ }
+ bodyArr := []interface{}{body}
+ return c.read(&bodyArr)
+}
+
+func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
+ if c.isClosed() {
+ return io.EOF
+ }
+
+ // We read the response header by hand
+ // so that the body can be decoded on its own from the stream at a later time.
+
+ const fia byte = 0x94 //four item array descriptor value
+ // Not sure why the panic of EOF is swallowed above.
+ // if bs1 := c.dec.r.readn1(); bs1 != fia {
+ // err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs1)
+ // return
+ // }
+ var ba [1]byte
+ var n int
+ for {
+ n, err = c.r.Read(ba[:])
+ if err != nil {
+ return
+ }
+ if n == 1 {
+ break
+ }
+ }
+
+ var b = ba[0]
+ if b != fia {
+ err = fmt.Errorf("not array - %s %x/%s", msgBadDesc, b, mpdesc(b))
+ } else {
+ err = c.read(&b)
+ if err == nil {
+ if b != expectTypeByte {
+ err = fmt.Errorf("%s - expecting %v but got %x/%s",
+ msgBadDesc, expectTypeByte, b, mpdesc(b))
+ } else {
+ err = c.read(msgid)
+ if err == nil {
+ err = c.read(methodOrError)
+ }
+ }
+ }
+ }
+ return
+}
+
+//--------------------------------------------------
+
+// msgpackSpecRpc is the implementation of Rpc that uses custom communication protocol
+// as defined in the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
+type msgpackSpecRpc struct{}
+
+// MsgpackSpecRpc implements Rpc using the communication protocol defined in
+// the msgpack spec at https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md .
+//
+// See GoRpc documentation, for information on buffering for better performance.
+var MsgpackSpecRpc msgpackSpecRpc
+
+func (x msgpackSpecRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
+ return &msgpackSpecRpcCodec{newRPCCodec(conn, h)}
+}
+
+func (x msgpackSpecRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
+ return &msgpackSpecRpcCodec{newRPCCodec(conn, h)}
+}
+
+var _ decDriver = (*msgpackDecDriver)(nil)
+var _ encDriver = (*msgpackEncDriver)(nil)
diff --git a/vendor/github.com/ugorji/go/codec/rpc.go b/vendor/github.com/ugorji/go/codec/rpc.go
new file mode 100644
index 00000000..9fb3c014
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/rpc.go
@@ -0,0 +1,232 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "bufio"
+ "errors"
+ "io"
+ "net/rpc"
+ "sync"
+)
+
+// Rpc provides a rpc Server or Client Codec for rpc communication.
+type Rpc interface {
+ ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
+ ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
+}
+
+// RPCOptions holds options specific to rpc functionality
+type RPCOptions struct {
+ // RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
+ //
+ // Set RPCNoBuffer=true to turn buffering off.
+ // Buffering can still be done if buffered connections are passed in, or
+ // buffering is configured on the handle.
+ RPCNoBuffer bool
+}
+
+// rpcCodec defines the struct members and common methods.
+type rpcCodec struct {
+ c io.Closer
+ r io.Reader
+ w io.Writer
+ f ioFlusher
+
+ dec *Decoder
+ enc *Encoder
+ // bw *bufio.Writer
+ // br *bufio.Reader
+ mu sync.Mutex
+ h Handle
+
+ cls bool
+ clsmu sync.RWMutex
+ clsErr error
+}
+
+func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
+ // return newRPCCodec2(bufio.NewReader(conn), bufio.NewWriter(conn), conn, h)
+ return newRPCCodec2(conn, conn, conn, h)
+}
+
+func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
+ // defensive: ensure that jsonH has TermWhitespace turned on.
+ if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
+ panic(errors.New("rpc requires a JsonHandle with TermWhitespace set to true"))
+ }
+ // always ensure that we use a flusher, and always flush what was written to the connection.
+ // we lose nothing by using a buffered writer internally.
+ f, ok := w.(ioFlusher)
+ bh := h.getBasicHandle()
+ if !bh.RPCNoBuffer {
+ if bh.WriterBufferSize <= 0 {
+ if !ok {
+ bw := bufio.NewWriter(w)
+ f, w = bw, bw
+ }
+ }
+ if bh.ReaderBufferSize <= 0 {
+ if _, ok = w.(ioPeeker); !ok {
+ if _, ok = w.(ioBuffered); !ok {
+ br := bufio.NewReader(r)
+ r = br
+ }
+ }
+ }
+ }
+ return rpcCodec{
+ c: c,
+ w: w,
+ r: r,
+ f: f,
+ h: h,
+ enc: NewEncoder(w, h),
+ dec: NewDecoder(r, h),
+ }
+}
+
+func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
+ if c.isClosed() {
+ return c.clsErr
+ }
+ err = c.enc.Encode(obj1)
+ if err == nil {
+ if writeObj2 {
+ err = c.enc.Encode(obj2)
+ }
+ // if err == nil && c.f != nil {
+ // err = c.f.Flush()
+ // }
+ }
+ if c.f != nil {
+ if err == nil {
+ err = c.f.Flush()
+ } else {
+ _ = c.f.Flush() // swallow flush error, so we maintain prior error on write
+ }
+ }
+ return
+}
+
+func (c *rpcCodec) swallow(err *error) {
+ defer panicToErr(c.dec, err)
+ c.dec.swallow()
+}
+
+func (c *rpcCodec) read(obj interface{}) (err error) {
+ if c.isClosed() {
+ return c.clsErr
+ }
+ //If nil is passed in, we should read and discard
+ if obj == nil {
+ // var obj2 interface{}
+ // return c.dec.Decode(&obj2)
+ c.swallow(&err)
+ return
+ }
+ return c.dec.Decode(obj)
+}
+
+func (c *rpcCodec) isClosed() (b bool) {
+ if c.c != nil {
+ c.clsmu.RLock()
+ b = c.cls
+ c.clsmu.RUnlock()
+ }
+ return
+}
+
+func (c *rpcCodec) Close() error {
+ if c.c == nil || c.isClosed() {
+ return c.clsErr
+ }
+ c.clsmu.Lock()
+ c.cls = true
+ c.clsErr = c.c.Close()
+ c.clsmu.Unlock()
+ return c.clsErr
+}
+
+func (c *rpcCodec) ReadResponseBody(body interface{}) error {
+ return c.read(body)
+}
+
+// -------------------------------------
+
+type goRpcCodec struct {
+ rpcCodec
+}
+
+func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
+ // Must protect for concurrent access as per API
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.write(r, body, true)
+}
+
+func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.write(r, body, true)
+}
+
+func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
+ return c.read(r)
+}
+
+func (c *goRpcCodec) ReadRequestHeader(r *rpc.Request) error {
+ return c.read(r)
+}
+
+func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
+ return c.read(body)
+}
+
+// -------------------------------------
+
+// goRpc is the implementation of Rpc that uses the communication protocol
+// as defined in net/rpc package.
+type goRpc struct{}
+
+// GoRpc implements Rpc using the communication protocol defined in net/rpc package.
+//
+// Note: network connection (from net.Dial, of type io.ReadWriteCloser) is not buffered.
+//
+// For performance, you should configure WriterBufferSize and ReaderBufferSize on the handle.
+// This ensures we use an adequate buffer during reading and writing.
+// If not configured, we will internally initialize and use a buffer during reads and writes.
+// This can be turned off via the RPCNoBuffer option on the Handle.
+// var handle codec.JsonHandle
+// handle.RPCNoBuffer = true // turns off attempt by rpc module to initialize a buffer
+//
+// Example 1: one way of configuring buffering explicitly:
+// var handle codec.JsonHandle // codec handle
+// handle.ReaderBufferSize = 1024
+// handle.WriterBufferSize = 1024
+// var conn io.ReadWriteCloser // connection got from a socket
+// var serverCodec = GoRpc.ServerCodec(conn, handle)
+// var clientCodec = GoRpc.ClientCodec(conn, handle)
+//
+// Example 2: you can also explicitly create a buffered connection yourself,
+// and not worry about configuring the buffer sizes in the Handle.
+// var handle codec.Handle // codec handle
+// var conn io.ReadWriteCloser // connection got from a socket
+// var bufconn = struct { // bufconn here is a buffered io.ReadWriteCloser
+// io.Closer
+// *bufio.Reader
+// *bufio.Writer
+// }{conn, bufio.NewReader(conn), bufio.NewWriter(conn)}
+// var serverCodec = GoRpc.ServerCodec(bufconn, handle)
+// var clientCodec = GoRpc.ClientCodec(bufconn, handle)
+//
+var GoRpc goRpc
+
+func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
+ return &goRpcCodec{newRPCCodec(conn, h)}
+}
+
+func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
+ return &goRpcCodec{newRPCCodec(conn, h)}
+}
diff --git a/vendor/github.com/ugorji/go/codec/simple.go b/vendor/github.com/ugorji/go/codec/simple.go
new file mode 100644
index 00000000..f1e181ef
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/simple.go
@@ -0,0 +1,652 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+package codec
+
+import (
+ "math"
+ "reflect"
+ "time"
+)
+
+const (
+ _ uint8 = iota
+ simpleVdNil = 1
+ simpleVdFalse = 2
+ simpleVdTrue = 3
+ simpleVdFloat32 = 4
+ simpleVdFloat64 = 5
+
+ // each lasts for 4 (ie n, n+1, n+2, n+3)
+ simpleVdPosInt = 8
+ simpleVdNegInt = 12
+
+ simpleVdTime = 24
+
+ // containers: each lasts for 4 (ie n, n+1, n+2, ... n+7)
+ simpleVdString = 216
+ simpleVdByteArray = 224
+ simpleVdArray = 232
+ simpleVdMap = 240
+ simpleVdExt = 248
+)
+
+type simpleEncDriver struct {
+ noBuiltInTypes
+ // encNoSeparator
+ e *Encoder
+ h *SimpleHandle
+ w encWriter
+ b [8]byte
+ // c containerState
+ encDriverTrackContainerWriter
+ // encDriverNoopContainerWriter
+ _ [2]uint64 // padding
+}
+
+func (e *simpleEncDriver) EncodeNil() {
+ e.w.writen1(simpleVdNil)
+}
+
+func (e *simpleEncDriver) EncodeBool(b bool) {
+ if e.h.EncZeroValuesAsNil && e.c != containerMapKey && !b {
+ e.EncodeNil()
+ return
+ }
+ if b {
+ e.w.writen1(simpleVdTrue)
+ } else {
+ e.w.writen1(simpleVdFalse)
+ }
+}
+
+func (e *simpleEncDriver) EncodeFloat32(f float32) {
+ if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
+ e.EncodeNil()
+ return
+ }
+ e.w.writen1(simpleVdFloat32)
+ bigenHelper{e.b[:4], e.w}.writeUint32(math.Float32bits(f))
+}
+
+func (e *simpleEncDriver) EncodeFloat64(f float64) {
+ if e.h.EncZeroValuesAsNil && e.c != containerMapKey && f == 0.0 {
+ e.EncodeNil()
+ return
+ }
+ e.w.writen1(simpleVdFloat64)
+ bigenHelper{e.b[:8], e.w}.writeUint64(math.Float64bits(f))
+}
+
+func (e *simpleEncDriver) EncodeInt(v int64) {
+ if v < 0 {
+ e.encUint(uint64(-v), simpleVdNegInt)
+ } else {
+ e.encUint(uint64(v), simpleVdPosInt)
+ }
+}
+
+func (e *simpleEncDriver) EncodeUint(v uint64) {
+ e.encUint(v, simpleVdPosInt)
+}
+
+func (e *simpleEncDriver) encUint(v uint64, bd uint8) {
+ if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == 0 {
+ e.EncodeNil()
+ return
+ }
+ if v <= math.MaxUint8 {
+ e.w.writen2(bd, uint8(v))
+ } else if v <= math.MaxUint16 {
+ e.w.writen1(bd + 1)
+ bigenHelper{e.b[:2], e.w}.writeUint16(uint16(v))
+ } else if v <= math.MaxUint32 {
+ e.w.writen1(bd + 2)
+ bigenHelper{e.b[:4], e.w}.writeUint32(uint32(v))
+ } else { // if v <= math.MaxUint64 {
+ e.w.writen1(bd + 3)
+ bigenHelper{e.b[:8], e.w}.writeUint64(v)
+ }
+}
+
+func (e *simpleEncDriver) encLen(bd byte, length int) {
+ if length == 0 {
+ e.w.writen1(bd)
+ } else if length <= math.MaxUint8 {
+ e.w.writen1(bd + 1)
+ e.w.writen1(uint8(length))
+ } else if length <= math.MaxUint16 {
+ e.w.writen1(bd + 2)
+ bigenHelper{e.b[:2], e.w}.writeUint16(uint16(length))
+ } else if int64(length) <= math.MaxUint32 {
+ e.w.writen1(bd + 3)
+ bigenHelper{e.b[:4], e.w}.writeUint32(uint32(length))
+ } else {
+ e.w.writen1(bd + 4)
+ bigenHelper{e.b[:8], e.w}.writeUint64(uint64(length))
+ }
+}
+
+func (e *simpleEncDriver) EncodeExt(rv interface{}, xtag uint64, ext Ext, _ *Encoder) {
+ bs := ext.WriteExt(rv)
+ if bs == nil {
+ e.EncodeNil()
+ return
+ }
+ e.encodeExtPreamble(uint8(xtag), len(bs))
+ e.w.writeb(bs)
+}
+
+func (e *simpleEncDriver) EncodeRawExt(re *RawExt, _ *Encoder) {
+ e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
+ e.w.writeb(re.Data)
+}
+
+func (e *simpleEncDriver) encodeExtPreamble(xtag byte, length int) {
+ e.encLen(simpleVdExt, length)
+ e.w.writen1(xtag)
+}
+
+func (e *simpleEncDriver) WriteArrayStart(length int) {
+ e.c = containerArrayStart
+ e.encLen(simpleVdArray, length)
+}
+
+func (e *simpleEncDriver) WriteMapStart(length int) {
+ e.c = containerMapStart
+ e.encLen(simpleVdMap, length)
+}
+
+func (e *simpleEncDriver) EncodeString(c charEncoding, v string) {
+ if false && e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == "" {
+ e.EncodeNil()
+ return
+ }
+ e.encLen(simpleVdString, len(v))
+ e.w.writestr(v)
+}
+
+// func (e *simpleEncDriver) EncodeSymbol(v string) {
+// e.EncodeString(cUTF8, v)
+// }
+
+func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+ // if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == nil {
+ if v == nil {
+ e.EncodeNil()
+ return
+ }
+ e.encLen(simpleVdByteArray, len(v))
+ e.w.writeb(v)
+}
+
+func (e *simpleEncDriver) EncodeTime(t time.Time) {
+ // if e.h.EncZeroValuesAsNil && e.c != containerMapKey && t.IsZero() {
+ if t.IsZero() {
+ e.EncodeNil()
+ return
+ }
+ v, err := t.MarshalBinary()
+ if err != nil {
+ e.e.errorv(err)
+ return
+ }
+ // time.Time marshalbinary takes about 14 bytes.
+ e.w.writen2(simpleVdTime, uint8(len(v)))
+ e.w.writeb(v)
+}
+
+//------------------------------------
+
+type simpleDecDriver struct {
+ d *Decoder
+ h *SimpleHandle
+ r decReader
+ bdRead bool
+ bd byte
+ br bool // a bytes reader?
+ c containerState
+ // b [scratchByteArrayLen]byte
+ noBuiltInTypes
+ // noStreamingCodec
+ decDriverNoopContainerReader
+ _ [3]uint64 // padding
+}
+
+func (d *simpleDecDriver) readNextBd() {
+ d.bd = d.r.readn1()
+ d.bdRead = true
+}
+
+func (d *simpleDecDriver) uncacheRead() {
+ if d.bdRead {
+ d.r.unreadn1()
+ d.bdRead = false
+ }
+}
+
+func (d *simpleDecDriver) ContainerType() (vt valueType) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ switch d.bd {
+ case simpleVdNil:
+ return valueTypeNil
+ case simpleVdByteArray, simpleVdByteArray + 1,
+ simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+ return valueTypeBytes
+ case simpleVdString, simpleVdString + 1,
+ simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
+ return valueTypeString
+ case simpleVdArray, simpleVdArray + 1,
+ simpleVdArray + 2, simpleVdArray + 3, simpleVdArray + 4:
+ return valueTypeArray
+ case simpleVdMap, simpleVdMap + 1,
+ simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
+ return valueTypeMap
+ // case simpleVdTime:
+ // return valueTypeTime
+ }
+ // else {
+ // d.d.errorf("isContainerType: unsupported parameter: %v", vt)
+ // }
+ return valueTypeUnset
+}
+
+func (d *simpleDecDriver) TryDecodeAsNil() bool {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == simpleVdNil {
+ d.bdRead = false
+ return true
+ }
+ return false
+}
+
+func (d *simpleDecDriver) decCheckInteger() (ui uint64, neg bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ switch d.bd {
+ case simpleVdPosInt:
+ ui = uint64(d.r.readn1())
+ case simpleVdPosInt + 1:
+ ui = uint64(bigen.Uint16(d.r.readx(2)))
+ case simpleVdPosInt + 2:
+ ui = uint64(bigen.Uint32(d.r.readx(4)))
+ case simpleVdPosInt + 3:
+ ui = uint64(bigen.Uint64(d.r.readx(8)))
+ case simpleVdNegInt:
+ ui = uint64(d.r.readn1())
+ neg = true
+ case simpleVdNegInt + 1:
+ ui = uint64(bigen.Uint16(d.r.readx(2)))
+ neg = true
+ case simpleVdNegInt + 2:
+ ui = uint64(bigen.Uint32(d.r.readx(4)))
+ neg = true
+ case simpleVdNegInt + 3:
+ ui = uint64(bigen.Uint64(d.r.readx(8)))
+ neg = true
+ default:
+ d.d.errorf("integer only valid from pos/neg integer1..8. Invalid descriptor: %v", d.bd)
+ return
+ }
+ // don't do this check, because callers may only want the unsigned value.
+ // if ui > math.MaxInt64 {
+ // d.d.errorf("decIntAny: Integer out of range for signed int64: %v", ui)
+ // return
+ // }
+ return
+}
+
+func (d *simpleDecDriver) DecodeInt64() (i int64) {
+ ui, neg := d.decCheckInteger()
+ i = chkOvf.SignedIntV(ui)
+ if neg {
+ i = -i
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) DecodeUint64() (ui uint64) {
+ ui, neg := d.decCheckInteger()
+ if neg {
+ d.d.errorf("assigning negative signed value to unsigned type")
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) DecodeFloat64() (f float64) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == simpleVdFloat32 {
+ f = float64(math.Float32frombits(bigen.Uint32(d.r.readx(4))))
+ } else if d.bd == simpleVdFloat64 {
+ f = math.Float64frombits(bigen.Uint64(d.r.readx(8)))
+ } else {
+ if d.bd >= simpleVdPosInt && d.bd <= simpleVdNegInt+3 {
+ f = float64(d.DecodeInt64())
+ } else {
+ d.d.errorf("float only valid from float32/64: Invalid descriptor: %v", d.bd)
+ return
+ }
+ }
+ d.bdRead = false
+ return
+}
+
+// bool can be decoded from bool only (single byte).
+func (d *simpleDecDriver) DecodeBool() (b bool) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == simpleVdTrue {
+ b = true
+ } else if d.bd == simpleVdFalse {
+ } else {
+ d.d.errorf("cannot decode bool - %s: %x", msgBadDesc, d.bd)
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) ReadMapStart() (length int) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ d.bdRead = false
+ d.c = containerMapStart
+ return d.decLen()
+}
+
+func (d *simpleDecDriver) ReadArrayStart() (length int) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ d.bdRead = false
+ d.c = containerArrayStart
+ return d.decLen()
+}
+
+func (d *simpleDecDriver) ReadArrayElem() {
+ d.c = containerArrayElem
+}
+
+func (d *simpleDecDriver) ReadArrayEnd() {
+ d.c = containerArrayEnd
+}
+
+func (d *simpleDecDriver) ReadMapElemKey() {
+ d.c = containerMapKey
+}
+
+func (d *simpleDecDriver) ReadMapElemValue() {
+ d.c = containerMapValue
+}
+
+func (d *simpleDecDriver) ReadMapEnd() {
+ d.c = containerMapEnd
+}
+
+func (d *simpleDecDriver) decLen() int {
+ switch d.bd % 8 {
+ case 0:
+ return 0
+ case 1:
+ return int(d.r.readn1())
+ case 2:
+ return int(bigen.Uint16(d.r.readx(2)))
+ case 3:
+ ui := uint64(bigen.Uint32(d.r.readx(4)))
+ if chkOvf.Uint(ui, intBitsize) {
+ d.d.errorf("overflow integer: %v", ui)
+ return 0
+ }
+ return int(ui)
+ case 4:
+ ui := bigen.Uint64(d.r.readx(8))
+ if chkOvf.Uint(ui, intBitsize) {
+ d.d.errorf("overflow integer: %v", ui)
+ return 0
+ }
+ return int(ui)
+ }
+ d.d.errorf("cannot read length: bd%%8 must be in range 0..4. Got: %d", d.bd%8)
+ return -1
+}
+
+func (d *simpleDecDriver) DecodeString() (s string) {
+ return string(d.DecodeBytes(d.d.b[:], true))
+}
+
+func (d *simpleDecDriver) DecodeStringAsBytes() (s []byte) {
+ return d.DecodeBytes(d.d.b[:], true)
+}
+
+func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == simpleVdNil {
+ d.bdRead = false
+ return
+ }
+ // check if an "array" of uint8's (see ContainerType for how to infer if an array)
+ if d.bd >= simpleVdArray && d.bd <= simpleVdMap+4 {
+ if len(bs) == 0 && zerocopy {
+ bs = d.d.b[:]
+ }
+ bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+ return
+ }
+
+ clen := d.decLen()
+ d.bdRead = false
+ if zerocopy {
+ if d.br {
+ return d.r.readx(clen)
+ } else if len(bs) == 0 {
+ bs = d.d.b[:]
+ }
+ }
+ return decByteSlice(d.r, clen, d.d.h.MaxInitLen, bs)
+}
+
+func (d *simpleDecDriver) DecodeTime() (t time.Time) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ if d.bd == simpleVdNil {
+ d.bdRead = false
+ return
+ }
+ if d.bd != simpleVdTime {
+ d.d.errorf("invalid descriptor for time.Time - expect 0x%x, received 0x%x", simpleVdTime, d.bd)
+ return
+ }
+ d.bdRead = false
+ clen := int(d.r.readn1())
+ b := d.r.readx(clen)
+ if err := (&t).UnmarshalBinary(b); err != nil {
+ d.d.errorv(err)
+ }
+ return
+}
+
+func (d *simpleDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) (realxtag uint64) {
+ if xtag > 0xff {
+ d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
+ return
+ }
+ realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
+ realxtag = uint64(realxtag1)
+ if ext == nil {
+ re := rv.(*RawExt)
+ re.Tag = realxtag
+ re.Data = detachZeroCopyBytes(d.br, re.Data, xbs)
+ } else {
+ ext.ReadExt(rv, xbs)
+ }
+ return
+}
+
+func (d *simpleDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+ switch d.bd {
+ case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
+ l := d.decLen()
+ xtag = d.r.readn1()
+ if verifyTag && xtag != tag {
+ d.d.errorf("wrong extension tag. Got %b. Expecting: %v", xtag, tag)
+ return
+ }
+ xbs = d.r.readx(l)
+ case simpleVdByteArray, simpleVdByteArray + 1,
+ simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+ xbs = d.DecodeBytes(nil, true)
+ default:
+ d.d.errorf("ext - %s - expecting extensions/bytearray, got: 0x%x", msgBadDesc, d.bd)
+ return
+ }
+ d.bdRead = false
+ return
+}
+
+func (d *simpleDecDriver) DecodeNaked() {
+ if !d.bdRead {
+ d.readNextBd()
+ }
+
+ n := d.d.n
+ var decodeFurther bool
+
+ switch d.bd {
+ case simpleVdNil:
+ n.v = valueTypeNil
+ case simpleVdFalse:
+ n.v = valueTypeBool
+ n.b = false
+ case simpleVdTrue:
+ n.v = valueTypeBool
+ n.b = true
+ case simpleVdPosInt, simpleVdPosInt + 1, simpleVdPosInt + 2, simpleVdPosInt + 3:
+ if d.h.SignedInteger {
+ n.v = valueTypeInt
+ n.i = d.DecodeInt64()
+ } else {
+ n.v = valueTypeUint
+ n.u = d.DecodeUint64()
+ }
+ case simpleVdNegInt, simpleVdNegInt + 1, simpleVdNegInt + 2, simpleVdNegInt + 3:
+ n.v = valueTypeInt
+ n.i = d.DecodeInt64()
+ case simpleVdFloat32:
+ n.v = valueTypeFloat
+ n.f = d.DecodeFloat64()
+ case simpleVdFloat64:
+ n.v = valueTypeFloat
+ n.f = d.DecodeFloat64()
+ case simpleVdTime:
+ n.v = valueTypeTime
+ n.t = d.DecodeTime()
+ case simpleVdString, simpleVdString + 1,
+ simpleVdString + 2, simpleVdString + 3, simpleVdString + 4:
+ n.v = valueTypeString
+ n.s = d.DecodeString()
+ case simpleVdByteArray, simpleVdByteArray + 1,
+ simpleVdByteArray + 2, simpleVdByteArray + 3, simpleVdByteArray + 4:
+ n.v = valueTypeBytes
+ n.l = d.DecodeBytes(nil, false)
+ case simpleVdExt, simpleVdExt + 1, simpleVdExt + 2, simpleVdExt + 3, simpleVdExt + 4:
+ n.v = valueTypeExt
+ l := d.decLen()
+ n.u = uint64(d.r.readn1())
+ n.l = d.r.readx(l)
+ case simpleVdArray, simpleVdArray + 1, simpleVdArray + 2,
+ simpleVdArray + 3, simpleVdArray + 4:
+ n.v = valueTypeArray
+ decodeFurther = true
+ case simpleVdMap, simpleVdMap + 1, simpleVdMap + 2, simpleVdMap + 3, simpleVdMap + 4:
+ n.v = valueTypeMap
+ decodeFurther = true
+ default:
+ d.d.errorf("cannot infer value - %s 0x%x", msgBadDesc, d.bd)
+ }
+
+ if !decodeFurther {
+ d.bdRead = false
+ }
+ return
+}
+
+//------------------------------------
+
+// SimpleHandle is a Handle for a very simple encoding format.
+//
+// simple is a simplistic codec similar to binc, but not as compact.
+// - Encoding of a value is always preceded by the descriptor byte (bd)
+// - True, false, nil are encoded fully in 1 byte (the descriptor)
+// - Integers (intXXX, uintXXX) are encoded in 1, 2, 4 or 8 bytes (plus a descriptor byte).
+// There are positive (uintXXX and intXXX >= 0) and negative (intXXX < 0) integers.
+// - Floats are encoded in 4 or 8 bytes (plus a descriptor byte)
+// - Length of containers (strings, bytes, array, map, extensions)
+// are encoded in 0, 1, 2, 4 or 8 bytes.
+// Zero-length containers have no length encoded.
+// For others, the number of bytes is given by pow(2, bd%3)
+// - maps are encoded as [bd] [length] [[key][value]]...
+// - arrays are encoded as [bd] [length] [value]...
+// - extensions are encoded as [bd] [length] [tag] [byte]...
+// - strings/bytearrays are encoded as [bd] [length] [byte]...
+// - time.Time are encoded as [bd] [length] [byte]...
+//
+// The full spec will be published soon.
+type SimpleHandle struct {
+ BasicHandle
+ binaryEncodingType
+ noElemSeparators
+ // EncZeroValuesAsNil says to encode zero values for numbers, bool, string, etc as nil
+ EncZeroValuesAsNil bool
+
+ // _ [1]uint64 // padding
+}
+
+// Name returns the name of the handle: simple
+func (h *SimpleHandle) Name() string { return "simple" }
+
+// SetBytesExt sets an extension
+func (h *SimpleHandle) SetBytesExt(rt reflect.Type, tag uint64, ext BytesExt) (err error) {
+ return h.SetExt(rt, tag, &extWrapper{ext, interfaceExtFailer{}})
+}
+
+func (h *SimpleHandle) hasElemSeparators() bool { return true } // as it implements Write(Map|Array)XXX
+
+func (h *SimpleHandle) newEncDriver(e *Encoder) encDriver {
+ return &simpleEncDriver{e: e, w: e.w, h: h}
+}
+
+func (h *SimpleHandle) newDecDriver(d *Decoder) decDriver {
+ return &simpleDecDriver{d: d, h: h, r: d.r, br: d.bytes}
+}
+
+func (e *simpleEncDriver) reset() {
+ e.c = 0
+ e.w = e.e.w
+}
+
+func (d *simpleDecDriver) reset() {
+ d.c = 0
+ d.r, d.br = d.d.r, d.d.bytes
+ d.bd, d.bdRead = 0, false
+}
+
+var _ decDriver = (*simpleDecDriver)(nil)
+var _ encDriver = (*simpleEncDriver)(nil)
diff --git a/vendor/github.com/ugorji/go/codec/xml.go b/vendor/github.com/ugorji/go/codec/xml.go
new file mode 100644
index 00000000..19fc36ca
--- /dev/null
+++ b/vendor/github.com/ugorji/go/codec/xml.go
@@ -0,0 +1,508 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build ignore
+
+package codec
+
+import "reflect"
+
+/*
+
+A strict Non-validating namespace-aware XML 1.0 parser and (en|de)coder.
+
+We are attempting this due to perceived issues with encoding/xml:
+ - Complicated. It tried to do too much, and is not as simple to use as json.
+ - Due to over-engineering, reflection is over-used AND performance suffers:
+ java is 6X faster:http://fabsk.eu/blog/category/informatique/dev/golang/
+ even PYTHON performs better: http://outgoing.typepad.com/outgoing/2014/07/exploring-golang.html
+
+codec framework will offer the following benefits
+ - VASTLY improved performance (when using reflection-mode or codecgen)
+ - simplicity and consistency: with the rest of the supported formats
+ - all other benefits of codec framework (streaming, codegeneration, etc)
+
+codec is not a drop-in replacement for encoding/xml.
+It is a replacement, based on the simplicity and performance of codec.
+Look at it like JAXB for Go.
+
+Challenges:
+ - Need to output XML preamble, with all namespaces at the right location in the output.
+ - Each "end" block is dynamic, so we need to maintain a context-aware stack
+ - How to decide when to use an attribute VS an element
+ - How to handle chardata, attr, comment EXPLICITLY.
+ - Should it output fragments?
+ e.g. encoding a bool should just output true OR false, which is not well-formed XML.
+
+Extend the struct tag. See representative example:
+ type X struct {
+ ID uint8 `codec:"http://ugorji.net/x-namespace xid id,omitempty,toarray,attr,cdata"`
+ // format: [namespace-uri ][namespace-prefix ]local-name, ...
+ }
+
+Based on this, we encode
+ - fields as elements, BUT
+ encode as attributes if struct tag contains ",attr" and is a scalar (bool, number or string)
+ - text as entity-escaped text, BUT encode as CDATA if struct tag contains ",cdata".
+
+To handle namespaces:
+ - XMLHandle is denoted as being namespace-aware.
+ Consequently, we WILL use the ns:name pair to encode and decode if defined, else use the plain name.
+ - *Encoder and *Decoder know whether the Handle "prefers" namespaces.
+ - add *Encoder.getEncName(*structFieldInfo).
+ No one calls *structFieldInfo.indexForEncName directly anymore
+ - OR better yet: indexForEncName is namespace-aware, and helper.go is all namespace-aware
+ indexForEncName takes a parameter of the form namespace:local-name OR local-name
+ - add *Decoder.getStructFieldInfo(encName string) // encName here is either like abc, or h1:nsabc
+ by being a method on *Decoder, or maybe a method on the Handle itself.
+ No one accesses .encName anymore
+ - let encode.go and decode.go use these (for consistency)
+ - only problem exists for gen.go, where we create a big switch on encName.
+ Now, we also have to add a switch on strings.endsWith(kName, encNsName)
+ - gen.go will need to have many more methods, and then double-on the 2 switch loops like:
+ switch k {
+ case "abc" : x.abc()
+ case "def" : x.def()
+ default {
+ switch {
+ case !nsAware: panic(...)
+ case strings.endsWith(":abc"): x.abc()
+ case strings.endsWith(":def"): x.def()
+ default: panic(...)
+ }
+ }
+ }
+
+The structure below accommodates this:
+
+ type typeInfo struct {
+ sfi []*structFieldInfo // sorted by encName
+ sfins // sorted by namespace
+ sfia // sorted, to have those with attributes at the top. Needed to write XML appropriately.
+ sfip // unsorted
+ }
+ type structFieldInfo struct {
+ encName
+ nsEncName
+ ns string
+ attr bool
+ cdata bool
+ }
+
+indexForEncName is now an internal helper function that takes a sorted array
+(one of ti.sfins or ti.sfi). It is only used by *Encoder.getStructFieldInfo(...)
+
+There will be a separate parser from the builder.
+The parser will have a method: next() xmlToken method. It has lookahead support,
+so you can pop multiple tokens, make a determination, and push them back in the order popped.
+This will be needed to determine whether we are "nakedly" decoding a container or not.
+The stack will be implemented using a slice and push/pop happens at the [0] element.
+
+xmlToken has fields:
+ - type uint8: 0 | ElementStart | ElementEnd | AttrKey | AttrVal | Text
+ - value string
+ - ns string
+
+SEE: http://www.xml.com/pub/a/98/10/guide0.html?page=3#ENTDECL
+
+The following are skipped when parsing:
+ - External Entities (from external file)
+ - Notation Declaration e.g.
+ - Entity Declarations & References
+ - XML Declaration (assume UTF-8)
+ - XML Directive i.e.
+ - Other Declarations: Notation, etc.
+ - Comment
+ - Processing Instruction
+ - schema / DTD for validation:
+ We are not a VALIDATING parser. Validation is done elsewhere.
+ However, some parts of the DTD internal subset are used (SEE BELOW).
+ For Attribute List Declarations e.g.
+
+ We considered using the ATTLIST to get "default" value, but not to validate the contents. (VETOED)
+
+The following XML features are supported
+ - Namespace
+ - Element
+ - Attribute
+ - cdata
+ - Unicode escape
+
+The following DTD (when as an internal sub-set) features are supported:
+ - Internal Entities e.g.
+ AND entities for the set: [<>&"']
+ - Parameter entities e.g.
+
+
+At decode time, a structure containing the following is kept
+ - namespace mapping
+ - default attribute values
+ - all internal entities (<>&"' and others written in the document)
+
+When decode starts, it parses XML namespace declarations and creates a map in the
+xmlDecDriver. While parsing, that map continuously gets updated.
+The only problem happens when a namespace declaration happens on the node that it defines.
+e.g.
+To handle this, each Element must be fully parsed at a time,
+even if it amounts to multiple tokens which are returned one at a time on request.
+
+xmlns is a special attribute name.
+ - It is used to define namespaces, including the default
+ - It is never returned as an AttrKey or AttrVal.
+ *We may decide later to allow user to use it e.g. you want to parse the xmlns mappings into a field.*
+
+Number, bool, null, mapKey, etc can all be decoded from any xmlToken.
+This accommodates map[int]string for example.
+
+It should be possible to create a schema from the types,
+or vice versa (generate types from schema with appropriate tags).
+This is however out-of-scope from this parsing project.
+
+We should write all namespace information at the first point that it is referenced in the tree,
+and use the mapping for all child nodes and attributes. This means that state is maintained
+at a point in the tree. This also means that calls to Decode or MustDecode will reset some state.
+
+When decoding, it is important to keep track of entity references and default attribute values.
+It seems these can only be stored in the DTD components. We should honor them when decoding.
+
+Configuration for XMLHandle will look like this:
+
+ XMLHandle
+ DefaultNS string
+ // Encoding:
+ NS map[string]string // ns URI to key, used for encoding
+ // Decoding: in case ENTITY declared in external schema or dtd, store info needed here
+ Entities map[string]string // map of entity rep to character
+
+
+During encode, if a namespace mapping is not defined for a namespace found on a struct,
+then we create a mapping for it using nsN (where N is 1..1000000, and doesn't conflict
+with any other namespace mapping).
+
+Note that different fields in a struct can have different namespaces.
+However, all fields will default to the namespace on the _struct field (if defined).
+
+An XML document is a name, a map of attributes and a list of children.
+Consequently, we cannot "DecodeNaked" into a map[string]interface{} (for example).
+We have to "DecodeNaked" into something that resembles XML data.
+
+To support DecodeNaked (decode into nil interface{}), we have to define some "supporting" types:
+ type Name struct { // Preferred. Less allocations due to conversions.
+ Local string
+ Space string
+ }
+ type Element struct {
+ Name Name
+ Attrs map[Name]string
+ Children []interface{} // each child is either *Element or string
+ }
+Only two "supporting" types are exposed for XML: Name and Element.
+
+// ------------------
+
+We considered 'type Name string' where Name is like "Space Local" (space-separated).
+We decided against it, because each creation of a name would lead to
+double allocation (first convert []byte to string, then concatenate them into a string).
+The benefit is that it is faster to read Attrs from a map. But given that Element is a value
+object, we want to eschew methods and have public exposed variables.
+
+We also considered the following, where xml types were not value objects, and we used
+intelligent accessor methods to extract information and for performance.
+*** WE DECIDED AGAINST THIS. ***
+ type Attr struct {
+ Name Name
+ Value string
+ }
+ // Element is a ValueObject: There are no accessor methods.
+ // Make element self-contained.
+ type Element struct {
+ Name Name
+ attrsMap map[string]string // where key is "Space Local"
+ attrs []Attr
+ childrenT []string
+ childrenE []Element
+ childrenI []int // each child is a index into T or E.
+ }
+ func (x *Element) child(i) interface{} // returns string or *Element
+
+// ------------------
+
+Per XML spec and our default handling, white space is always treated as
+insignificant between elements, except in a text node. The xml:space='preserve'
+attribute is ignored.
+
+**Note: there is no xml: namespace. The xml: attributes were defined before namespaces.**
+**So treat them as just "directives" that should be interpreted to mean something**.
+
+On encoding, we support indenting aka prettifying markup in the same way we support it for json.
+
+A document or element can only be encoded/decoded from/to a struct. In this mode:
+ - struct name maps to element name (or tag-info from _struct field)
+ - fields are mapped to child elements or attributes
+
+A map is either encoded as attributes on current element, or as a set of child elements.
+Maps are encoded as attributes iff their keys and values are primitives (number, bool, string).
+
+A list is encoded as a set of child elements.
+
+Primitives (number, bool, string) are encoded as an element, attribute or text
+depending on the context.
+
+Extensions must encode themselves as a text string.
+
+Encoding is tough, specifically when encoding mappings, because we need to encode
+as either attribute or element. To do this, we need to default to encoding as attributes,
+and then let Encoder inform the Handle when to start encoding as nodes.
+i.e. Encoder does something like:
+
+ h.EncodeMapStart()
+ h.Encode(), h.Encode(), ...
+ h.EncodeMapNotAttrSignal() // this is not a bool, because it's a signal
+ h.Encode(), h.Encode(), ...
+ h.EncodeEnd()
+
+Only XMLHandle understands this, and will set itself to start encoding as elements.
+
+This support extends to maps. For example, if a struct field is a map, and it has
+the struct tag signifying it should be attr, then all its fields are encoded as attributes.
+e.g.
+
+ type X struct {
+ M map[string]int `codec:"m,attr"` // encode keys as attributes named
+ }
+
+Question:
+ - if encoding a map, what if map keys have spaces in them???
+ Then they cannot be attributes or child elements. Error.
+
+Options to consider adding later:
+ - For attribute values, normalize by trimming beginning and ending white space,
+ and converting every white space sequence to a single space.
+ - ATTLIST restrictions are enforced.
+ e.g. default value of xml:space, skipping xml:XYZ style attributes, etc.
+ - Consider supporting NON-STRICT mode (e.g. to handle HTML parsing).
+ Some elements e.g. br, hr, etc need not close and should be auto-closed
+ ... (see http://www.w3.org/TR/html4/loose.dtd)
+ An expansive set of entities are pre-defined.
+ - Have easy way to create a HTML parser:
+ add a HTML() method to XMLHandle, that will set Strict=false, specify AutoClose,
+ and add HTML Entities to the list.
+ - Support validating element/attribute XMLName before writing it.
+ Keep this behind a flag, which is set to false by default (for performance).
+ type XMLHandle struct {
+ CheckName bool
+ }
+
+Misc:
+
+ROADMAP (1 weeks):
+ - build encoder (1 day)
+ - build decoder (based off xmlParser) (1 day)
+ - implement xmlParser (2 days).
+ Look at encoding/xml for inspiration.
+ - integrate and TEST (1 days)
+ - write article and post it (1 day)
+
+// ---------- MORE NOTES FROM 2017-11-30 ------------
+
+when parsing
+- parse the attributes first
+- then parse the nodes
+
+basically:
+- if encoding a field: we use the field name for the wrapper
+- if encoding a non-field, then just use the element type name
+
+ map[string]string ==> ... or
+ ... OR
+ val1val2... <- PREFERED
+ []string ==> v1v2...
+ string v1 ==> v1
+ bool true ==> true
+ float 1.0 ==> 1.0
+ ...
+
+ F1 map[string]string ==> abcval... OR
+ val... OR
+ val... <- PREFERED
+ F2 []string ==> v1v2...
+ F3 bool ==> true
+ ...
+
+- a scalar is encoded as:
+ (value) of type T ==>
+ (value) of field F ==>
+- A kv-pair is encoded as:
+ (key,value) ==> OR